Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: device/usb/usb_device_handle_usbfs.cc

Issue 2797433005: Remove MessageLoop destruction observer from //device/usb (Closed)
Patch Set: Further clarify cross-thread ownership Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/usb/usb_device_handle_usbfs.h ('k') | device/usb/usb_service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/usb/usb_device_handle_usbfs.h" 5 #include "device/usb/usb_device_handle_usbfs.h"
6 6
7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21 7 #if defined(OS_ANDROID) && __ANDROID_API__ < 21
8 #include <linux/usb_ch9.h> 8 #include <linux/usb_ch9.h>
9 #else 9 #else
10 #include <linux/usb/ch9.h> 10 #include <linux/usb/ch9.h>
11 #endif 11 #endif
12 12
13 #include <linux/usbdevice_fs.h> 13 #include <linux/usbdevice_fs.h>
14 #include <sys/ioctl.h> 14 #include <sys/ioctl.h>
15 15
16 #include <numeric> 16 #include <numeric>
17 17
18 #include "base/bind.h" 18 #include "base/bind.h"
19 #include "base/cancelable_callback.h" 19 #include "base/cancelable_callback.h"
20 #include "base/files/file_descriptor_watcher_posix.h" 20 #include "base/files/file_descriptor_watcher_posix.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/posix/eintr_wrapper.h" 22 #include "base/posix/eintr_wrapper.h"
23 #include "base/sequence_checker.h"
24 #include "base/stl_util.h" 24 #include "base/stl_util.h"
25 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
26 #include "base/threading/thread_task_runner_handle.h" 26 #include "base/threading/thread_task_runner_handle.h"
27 #include "components/device_event_log/device_event_log.h" 27 #include "components/device_event_log/device_event_log.h"
28 #include "device/usb/usb_device_linux.h" 28 #include "device/usb/usb_device_linux.h"
29 #include "net/base/io_buffer.h" 29 #include "net/base/io_buffer.h"
30 30
31 namespace device { 31 namespace device {
32 32
33 namespace { 33 namespace {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // TODO(reillyg): Add a specific error message whenever one of the cases 127 // TODO(reillyg): Add a specific error message whenever one of the cases
128 // above fails to match. 128 // above fails to match.
129 USB_LOG(ERROR) << "Unknown system error: " 129 USB_LOG(ERROR) << "Unknown system error: "
130 << logging::SystemErrorCodeToString(rc); 130 << logging::SystemErrorCodeToString(rc);
131 return USB_TRANSFER_ERROR; 131 return USB_TRANSFER_ERROR;
132 } 132 }
133 } 133 }
134 134
135 } // namespace 135 } // namespace
136 136
137 class UsbDeviceHandleUsbfs::FileThreadHelper 137 class UsbDeviceHandleUsbfs::FileThreadHelper {
138 : public base::MessageLoop::DestructionObserver {
139 public: 138 public:
140 FileThreadHelper(int fd, 139 FileThreadHelper(base::ScopedFD fd,
141 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, 140 scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
142 scoped_refptr<base::SequencedTaskRunner> task_runner); 141 scoped_refptr<base::SequencedTaskRunner> task_runner);
143 ~FileThreadHelper() override; 142 ~FileThreadHelper();
144 143
145 static void Start(std::unique_ptr<FileThreadHelper> self); 144 void Start();
146 145 void ReleaseFileDescriptor();
147 // base::MessageLoop::DestructionObserver overrides. 146
148 void WillDestroyCurrentMessageLoop() override; 147 void SetConfiguration(int configuration_value,
148 const ResultCallback& callback);
149 void ReleaseInterface(int interface_number, const ResultCallback& callback);
150 void SetInterface(int interface_number,
151 int alternate_setting,
152 const ResultCallback& callback);
153 void ResetDevice(const ResultCallback& callback);
154 void ClearHalt(uint8_t endpoint_address, const ResultCallback& callback);
155 void DiscardUrb(Transfer* transfer);
149 156
150 private: 157 private:
151 // Called when |fd_| is writable without blocking. 158 // Called when |fd_| is writable without blocking.
152 void OnFileCanWriteWithoutBlocking(); 159 void OnFileCanWriteWithoutBlocking();
153 160
154 int fd_; 161 base::ScopedFD fd_;
155 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; 162 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_;
156 scoped_refptr<base::SequencedTaskRunner> task_runner_; 163 scoped_refptr<base::SequencedTaskRunner> task_runner_;
157 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; 164 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
158 base::ThreadChecker thread_checker_; 165 base::SequenceChecker sequence_checker_;
159 166
160 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); 167 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper);
161 }; 168 };
162 169
170 struct UsbDeviceHandleUsbfs::Transfer {
171 Transfer() = delete;
172 Transfer(scoped_refptr<net::IOBuffer> buffer,
173 const TransferCallback& callback,
174 scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
175 Transfer(scoped_refptr<net::IOBuffer> buffer,
176 const IsochronousTransferCallback& callback);
177 ~Transfer();
178
179 void* operator new(std::size_t size, size_t number_of_iso_packets);
180 void RunCallback(UsbTransferStatus status, size_t bytes_transferred);
181 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);
182
183 scoped_refptr<net::IOBuffer> control_transfer_buffer;
184 scoped_refptr<net::IOBuffer> buffer;
185 base::CancelableClosure timeout_closure;
186 bool cancelled = false;
187
188 // When the URB is |cancelled| these two flags track whether the URB has both
189 // been |discarded| and |reaped| since the possiblity of last-minute
190 // completion makes these two conditions race.
191 bool discarded = false;
192 bool reaped = false;
193
194 private:
195 TransferCallback callback;
196 IsochronousTransferCallback isoc_callback;
197 scoped_refptr<base::SingleThreadTaskRunner> callback_runner;
198
199 DISALLOW_COPY_AND_ASSIGN(Transfer);
200
201 public:
202 // The |urb| field must be the last in the struct so that the extra space
203 // allocated by the overridden new function above extends the length of its
204 // |iso_frame_desc| field.
205 usbdevfs_urb urb;
206 };
207
163 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( 208 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper(
164 int fd, 209 base::ScopedFD fd,
165 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, 210 scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
166 scoped_refptr<base::SequencedTaskRunner> task_runner) 211 scoped_refptr<base::SequencedTaskRunner> task_runner)
167 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {} 212 : fd_(std::move(fd)),
213 device_handle_(std::move(device_handle)),
214 task_runner_(std::move(task_runner)) {}
168 215
169 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { 216 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() {
170 DCHECK(thread_checker_.CalledOnValidThread()); 217 DCHECK(sequence_checker_.CalledOnValidSequence());
171 base::MessageLoop::current()->RemoveDestructionObserver(this); 218 }
172 } 219
173 220 void UsbDeviceHandleUsbfs::FileThreadHelper::Start() {
174 // static
175 void UsbDeviceHandleUsbfs::FileThreadHelper::Start(
176 std::unique_ptr<FileThreadHelper> self) {
177 base::ThreadRestrictions::AssertIOAllowed(); 221 base::ThreadRestrictions::AssertIOAllowed();
178 self->thread_checker_.DetachFromThread(); 222 sequence_checker_.DetachFromSequence();
223 DCHECK(sequence_checker_.CalledOnValidSequence());
179 224
180 // Linux indicates that URBs are available to reap by marking the file 225 // Linux indicates that URBs are available to reap by marking the file
181 // descriptor writable. 226 // descriptor writable.
182 self->watch_controller_ = base::FileDescriptorWatcher::WatchWritable( 227 watch_controller_ = base::FileDescriptorWatcher::WatchWritable(
183 self->fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, 228 fd_.get(), base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking,
184 base::Unretained(self.get()))); 229 base::Unretained(this)));
185 230 }
186 // |self| is now owned by the current message loop. 231
187 base::MessageLoop::current()->AddDestructionObserver(self.release()); 232 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseFileDescriptor() {
188 } 233 // This method intentionally leaks the file descriptor.
189 234 DCHECK(sequence_checker_.CalledOnValidSequence());
190 void UsbDeviceHandleUsbfs::FileThreadHelper::WillDestroyCurrentMessageLoop() { 235 watch_controller_.reset();
191 DCHECK(thread_checker_.CalledOnValidThread()); 236 ignore_result(fd_.release());
192 delete this; 237 }
238
239 void UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration(
240 int configuration_value,
241 const ResultCallback& callback) {
242 DCHECK(sequence_checker_.CalledOnValidSequence());
243
244 int rc = HANDLE_EINTR(
245 ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value));
246 if (rc)
247 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
248 task_runner_->PostTask(
249 FROM_HERE,
250 base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
251 device_handle_, configuration_value, rc == 0, callback));
252 }
253
254 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface(
255 int interface_number,
256 const ResultCallback& callback) {
257 DCHECK(sequence_checker_.CalledOnValidSequence());
258
259 int rc = HANDLE_EINTR(
260 ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number));
261 if (rc) {
262 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
263 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
264 } else {
265 task_runner_->PostTask(
266 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
267 device_handle_, interface_number, callback));
268 }
269 }
270
271 void UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface(
272 int interface_number,
273 int alternate_setting,
274 const ResultCallback& callback) {
275 DCHECK(sequence_checker_.CalledOnValidSequence());
276
277 usbdevfs_setinterface cmd = {0};
278 cmd.interface = interface_number;
279 cmd.altsetting = alternate_setting;
280 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SETINTERFACE, &cmd));
281 if (rc) {
282 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
283 << " to alternate setting " << alternate_setting;
284 }
285 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
286 }
287
288 void UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice(
289 const ResultCallback& callback) {
290 DCHECK(sequence_checker_.CalledOnValidSequence());
291
292 // TODO(reillyg): libusb releases interfaces before and then reclaims
293 // interfaces after a reset. We should probably do this too or document that
294 // callers have to call ClaimInterface as well.
295 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr));
296 if (rc)
297 USB_PLOG(DEBUG) << "Failed to reset the device";
298 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
299 }
300
301 void UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt(
302 uint8_t endpoint_address,
303 const ResultCallback& callback) {
304 DCHECK(sequence_checker_.CalledOnValidSequence());
305
306 int tmp_endpoint = endpoint_address;
307 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_CLEAR_HALT, &tmp_endpoint));
308 if (rc) {
309 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
310 << static_cast<int>(endpoint_address);
311 }
312 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
313 }
314
315 void UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb(Transfer* transfer) {
316 DCHECK(sequence_checker_.CalledOnValidSequence());
317
318 HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));
319
320 task_runner_->PostTask(
321 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, device_handle_,
322 transfer));
193 } 323 }
194 324
195 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { 325 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() {
196 DCHECK(thread_checker_.CalledOnValidThread()); 326 DCHECK(sequence_checker_.CalledOnValidSequence());
197 327
198 const size_t MAX_URBS_PER_EVENT = 10; 328 const size_t MAX_URBS_PER_EVENT = 10;
199 std::vector<usbdevfs_urb*> urbs; 329 std::vector<usbdevfs_urb*> urbs;
200 urbs.reserve(MAX_URBS_PER_EVENT); 330 urbs.reserve(MAX_URBS_PER_EVENT);
201 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { 331 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) {
202 usbdevfs_urb* urb; 332 usbdevfs_urb* urb;
203 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_REAPURBNDELAY, &urb)); 333 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_REAPURBNDELAY, &urb));
204 if (rc) { 334 if (rc) {
205 if (errno == EAGAIN) 335 if (errno == EAGAIN)
206 break; 336 break;
207 USB_PLOG(DEBUG) << "Failed to reap urbs"; 337 USB_PLOG(DEBUG) << "Failed to reap urbs";
208 if (errno == ENODEV) { 338 if (errno == ENODEV) {
209 // Device has disconnected. Stop watching the file descriptor to avoid 339 // Device has disconnected. Stop watching the file descriptor to avoid
210 // looping until |device_handle_| is closed. 340 // looping until |device_handle_| is closed.
211 watch_controller_.reset(); 341 watch_controller_.reset();
212 break; 342 break;
213 } 343 }
214 } else { 344 } else {
215 urbs.push_back(urb); 345 urbs.push_back(urb);
216 } 346 }
217 } 347 }
218 348
219 task_runner_->PostTask( 349 task_runner_->PostTask(
220 FROM_HERE, 350 FROM_HERE,
221 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); 351 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs));
222 } 352 }
223 353
224 struct UsbDeviceHandleUsbfs::Transfer {
225 Transfer() = delete;
226 Transfer(scoped_refptr<net::IOBuffer> buffer,
227 const TransferCallback& callback,
228 scoped_refptr<base::SingleThreadTaskRunner> callback_runner);
229 Transfer(scoped_refptr<net::IOBuffer> buffer,
230 const IsochronousTransferCallback& callback);
231 ~Transfer();
232
233 void* operator new(std::size_t size, size_t number_of_iso_packets);
234 void RunCallback(UsbTransferStatus status, size_t bytes_transferred);
235 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);
236
237 scoped_refptr<net::IOBuffer> control_transfer_buffer;
238 scoped_refptr<net::IOBuffer> buffer;
239 base::CancelableClosure timeout_closure;
240 bool cancelled = false;
241
242 // When the URB is |cancelled| these two flags track whether the URB has both
243 // been |discarded| and |reaped| since the possiblity of last-minute
244 // completion makes these two conditions race.
245 bool discarded = false;
246 bool reaped = false;
247
248 private:
249 TransferCallback callback;
250 IsochronousTransferCallback isoc_callback;
251 scoped_refptr<base::SingleThreadTaskRunner> callback_runner;
252
253 DISALLOW_COPY_AND_ASSIGN(Transfer);
254
255 public:
256 // The |urb| field must be the last in the struct so that the extra space
257 // allocated by the overridden new function above extends the length of its
258 // |iso_frame_desc| field.
259 usbdevfs_urb urb;
260 };
261
262 UsbDeviceHandleUsbfs::Transfer::Transfer( 354 UsbDeviceHandleUsbfs::Transfer::Transfer(
263 scoped_refptr<net::IOBuffer> buffer, 355 scoped_refptr<net::IOBuffer> buffer,
264 const TransferCallback& callback, 356 const TransferCallback& callback,
265 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) 357 scoped_refptr<base::SingleThreadTaskRunner> callback_runner)
266 : buffer(buffer), callback(callback), callback_runner(callback_runner) { 358 : buffer(buffer), callback(callback), callback_runner(callback_runner) {
267 memset(&urb, 0, sizeof(urb)); 359 memset(&urb, 0, sizeof(urb));
268 urb.usercontext = this; 360 urb.usercontext = this;
269 urb.buffer = buffer->data(); 361 urb.buffer = buffer->data();
270 } 362 }
271 363
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 DCHECK(isoc_callback); 402 DCHECK(isoc_callback);
311 isoc_callback.Run(buffer, packets); 403 isoc_callback.Run(buffer, packets);
312 isoc_callback.Reset(); 404 isoc_callback.Reset();
313 } 405 }
314 406
315 UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( 407 UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs(
316 scoped_refptr<UsbDevice> device, 408 scoped_refptr<UsbDevice> device,
317 base::ScopedFD fd, 409 base::ScopedFD fd,
318 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) 410 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
319 : device_(device), 411 : device_(device),
320 fd_(std::move(fd)), 412 fd_(fd.get()),
413 task_runner_(base::ThreadTaskRunnerHandle::Get()),
321 blocking_task_runner_(blocking_task_runner) { 414 blocking_task_runner_(blocking_task_runner) {
322 DCHECK(device_); 415 DCHECK(device_);
323 DCHECK(fd_.is_valid()); 416 DCHECK(fd.is_valid());
324 DCHECK(blocking_task_runner_); 417 DCHECK(blocking_task_runner_);
325 418
326 task_runner_ = base::ThreadTaskRunnerHandle::Get(); 419 helper_.reset(new FileThreadHelper(std::move(fd), this, task_runner_));
327
328 std::unique_ptr<FileThreadHelper> helper(
329 new FileThreadHelper(fd_.get(), this, task_runner_));
330 helper_ = helper.get();
331 blocking_task_runner_->PostTask( 420 blocking_task_runner_->PostTask(
332 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); 421 FROM_HERE,
422 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get())));
333 } 423 }
334 424
335 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { 425 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const {
336 return device_; 426 return device_;
337 } 427 }
338 428
339 void UsbDeviceHandleUsbfs::Close() { 429 void UsbDeviceHandleUsbfs::Close() {
340 if (!device_) 430 if (!device_)
341 return; // Already closed. 431 return; // Already closed.
342 432
343 // On the |task_runner_| thread check |device_| to see if the handle is 433 // On the |task_runner_| thread check |device_| to see if the handle is
344 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to 434 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to
345 // see if the handle is closed. 435 // see if the handle is closed.
346 device_->HandleClosed(this); 436 device_->HandleClosed(this);
347 device_ = nullptr; 437 device_ = nullptr;
348 438
349 for (const auto& transfer : transfers_) 439 for (const auto& transfer : transfers_)
350 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); 440 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED);
351 441
442 // Releases |helper_|.
352 blocking_task_runner_->PostTask( 443 blocking_task_runner_->PostTask(
353 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); 444 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this));
354 } 445 }
355 446
356 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, 447 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
357 const ResultCallback& callback) { 448 const ResultCallback& callback) {
449 if (!device_) {
450 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
451 return;
452 }
453
358 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request 454 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request
359 // to the device so it must be performed on a thread where it is okay to 455 // to the device so it must be performed on a thread where it is okay to
360 // block. 456 // block.
361 blocking_task_runner_->PostTask( 457 blocking_task_runner_->PostTask(
362 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationBlocking, 458 FROM_HERE,
363 this, configuration_value, callback)); 459 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration,
460 base::Unretained(helper_.get()), configuration_value,
461 callback));
364 } 462 }
365 463
366 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, 464 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
367 const ResultCallback& callback) { 465 const ResultCallback& callback) {
368 if (!device_) { 466 if (!device_) {
369 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 467 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
370 return; 468 return;
371 } 469 }
372 470
373 if (base::ContainsKey(interfaces_, interface_number)) { 471 if (base::ContainsKey(interfaces_, interface_number)) {
374 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed."; 472 USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed.";
375 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); 473 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
376 return; 474 return;
377 } 475 }
378 476
379 // It appears safe to assume that this ioctl will not block. 477 // It appears safe to assume that this ioctl will not block.
380 int rc = HANDLE_EINTR( 478 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLAIMINTERFACE, &interface_number));
381 ioctl(fd_.get(), USBDEVFS_CLAIMINTERFACE, &interface_number));
382 if (rc) { 479 if (rc) {
383 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number; 480 USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number;
384 } else { 481 } else {
385 interfaces_[interface_number].alternate_setting = 0; 482 interfaces_[interface_number].alternate_setting = 0;
386 RefreshEndpointInfo(); 483 RefreshEndpointInfo();
387 } 484 }
388 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); 485 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
389 } 486 }
390 487
391 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, 488 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
392 const ResultCallback& callback) { 489 const ResultCallback& callback) {
490 if (!device_) {
491 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
492 return;
493 }
494
393 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the 495 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the
394 // device to restore alternate setting 0 so it must be performed on a thread 496 // device to restore alternate setting 0 so it must be performed on a thread
395 // where it is okay to block. 497 // where it is okay to block.
396 blocking_task_runner_->PostTask( 498 blocking_task_runner_->PostTask(
397 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking, 499 FROM_HERE,
398 this, interface_number, callback)); 500 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface,
501 base::Unretained(helper_.get()), interface_number, callback));
399 } 502 }
400 503
401 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( 504 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
402 int interface_number, 505 int interface_number,
403 int alternate_setting, 506 int alternate_setting,
404 const ResultCallback& callback) { 507 const ResultCallback& callback) {
508 if (!device_) {
509 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
510 return;
511 }
512
405 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE 513 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE
406 // request to the device so it must be performed on a thread where it is okay 514 // request to the device so it must be performed on a thread where it is okay
407 // to block. 515 // to block.
408 blocking_task_runner_->PostTask( 516 blocking_task_runner_->PostTask(
409 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetInterfaceBlocking, this, 517 FROM_HERE,
410 interface_number, alternate_setting, callback)); 518 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface,
519 base::Unretained(helper_.get()), interface_number,
520 alternate_setting, callback));
411 } 521 }
412 522
413 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { 523 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) {
524 if (!device_) {
525 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
526 return;
527 }
528
414 // USBDEVFS_RESET is synchronous because it waits for the port to be reset 529 // USBDEVFS_RESET is synchronous because it waits for the port to be reset
415 // and the device re-enumerated so it must be performed on a thread where it 530 // and the device re-enumerated so it must be performed on a thread where it
416 // is okay to block. 531 // is okay to block.
417 blocking_task_runner_->PostTask( 532 blocking_task_runner_->PostTask(
418 FROM_HERE, 533 FROM_HERE,
419 base::Bind(&UsbDeviceHandleUsbfs::ResetDeviceBlocking, this, callback)); 534 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice,
535 base::Unretained(helper_.get()), callback));
420 } 536 }
421 537
422 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, 538 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address,
423 const ResultCallback& callback) { 539 const ResultCallback& callback) {
540 if (!device_) {
541 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
542 return;
543 }
544
424 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE 545 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE
425 // request to the device so it must be performed on a thread where it is okay 546 // request to the device so it must be performed on a thread where it is okay
426 // to block. 547 // to block.
427 blocking_task_runner_->PostTask( 548 blocking_task_runner_->PostTask(
428 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ClearHaltBlocking, this, 549 FROM_HERE,
429 endpoint_address, callback)); 550 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt,
551 base::Unretained(helper_.get()), endpoint_address, callback));
430 } 552 }
431 553
432 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, 554 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction,
433 TransferRequestType request_type, 555 TransferRequestType request_type,
434 TransferRecipient recipient, 556 TransferRecipient recipient,
435 uint8_t request, 557 uint8_t request,
436 uint16_t value, 558 uint16_t value,
437 uint16_t index, 559 uint16_t index,
438 scoped_refptr<net::IOBuffer> buffer, 560 scoped_refptr<net::IOBuffer> buffer,
439 size_t length, 561 size_t length,
(...skipping 10 matching lines...) Expand all
450 transfer->control_transfer_buffer = 572 transfer->control_transfer_buffer =
451 BuildControlTransferBuffer(direction, request_type, recipient, request, 573 BuildControlTransferBuffer(direction, request_type, recipient, request,
452 value, index, buffer, length); 574 value, index, buffer, length);
453 transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL; 575 transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL;
454 transfer->urb.endpoint = 0; 576 transfer->urb.endpoint = 0;
455 transfer->urb.buffer = transfer->control_transfer_buffer->data(); 577 transfer->urb.buffer = transfer->control_transfer_buffer->data();
456 transfer->urb.buffer_length = 8 + length; 578 transfer->urb.buffer_length = 8 + length;
457 579
458 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported 580 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
459 // by USBDEVFS_REAPURBNDELAY. 581 // by USBDEVFS_REAPURBNDELAY.
460 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); 582 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
461 if (rc) { 583 if (rc) {
462 rc = logging::GetLastSystemErrorCode(); 584 rc = logging::GetLastSystemErrorCode();
463 USB_PLOG(DEBUG) << "Failed to submit control transfer"; 585 USB_PLOG(DEBUG) << "Failed to submit control transfer";
464 task_runner_->PostTask( 586 task_runner_->PostTask(
465 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); 587 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0));
466 } else { 588 } else {
467 SetUpTimeoutCallback(transfer.get(), timeout); 589 SetUpTimeoutCallback(transfer.get(), timeout);
468 transfers_.push_back(std::move(transfer)); 590 transfers_.push_back(std::move(transfer));
469 } 591 }
470 } 592 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 if (it != endpoints_.end()) 641 if (it != endpoints_.end())
520 return it->second.interface; 642 return it->second.interface;
521 return nullptr; 643 return nullptr;
522 } 644 }
523 645
524 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { 646 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() {
525 DCHECK(!device_) << "Handle must be closed before it is destroyed."; 647 DCHECK(!device_) << "Handle must be closed before it is destroyed.";
526 } 648 }
527 649
528 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { 650 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() {
529 ignore_result(fd_.release()); 651 // Calls to this method must be posted to |blocking_task_runner_|.
530 delete helper_; 652 helper_->ReleaseFileDescriptor();
653 helper_.reset();
531 } 654 }
532 655
533 void UsbDeviceHandleUsbfs::CloseBlocking() { 656 void UsbDeviceHandleUsbfs::CloseBlocking() {
534 fd_.reset(-1); 657 // Calls to this method must be posted to |blocking_task_runner_|.
535 delete helper_; 658 helper_.reset();
536 }
537
538 void UsbDeviceHandleUsbfs::SetConfigurationBlocking(
539 int configuration_value,
540 const ResultCallback& callback) {
541 if (!fd_.is_valid()) {
542 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
543 return;
544 }
545
546 int rc = HANDLE_EINTR(
547 ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value));
548 if (rc)
549 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
550 task_runner_->PostTask(
551 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
552 this, configuration_value, rc == 0, callback));
553 } 659 }
554 660
555 void UsbDeviceHandleUsbfs::SetConfigurationComplete( 661 void UsbDeviceHandleUsbfs::SetConfigurationComplete(
556 int configuration_value, 662 int configuration_value,
557 bool success, 663 bool success,
558 const ResultCallback& callback) { 664 const ResultCallback& callback) {
559 if (success && device_) { 665 if (success && device_) {
560 device_->ActiveConfigurationChanged(configuration_value); 666 device_->ActiveConfigurationChanged(configuration_value);
561 // TODO(reillyg): If all interfaces are unclaimed before a new configuration 667 // TODO(reillyg): If all interfaces are unclaimed before a new configuration
562 // is set then this will do nothing. Investigate. 668 // is set then this will do nothing. Investigate.
563 RefreshEndpointInfo(); 669 RefreshEndpointInfo();
564 } 670 }
565 callback.Run(success); 671 callback.Run(success);
566 } 672 }
567 673
568 void UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking(
569 int interface_number,
570 const ResultCallback& callback) {
571 if (!fd_.is_valid()) {
572 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
573 return;
574 }
575
576 int rc = HANDLE_EINTR(
577 ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number));
578 if (rc) {
579 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
580 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
581 } else {
582 task_runner_->PostTask(
583 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
584 this, interface_number, callback));
585 }
586 }
587
588 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete( 674 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(
589 int interface_number, 675 int interface_number,
590 const ResultCallback& callback) { 676 const ResultCallback& callback) {
591 auto it = interfaces_.find(interface_number); 677 auto it = interfaces_.find(interface_number);
592 DCHECK(it != interfaces_.end()); 678 DCHECK(it != interfaces_.end());
593 interfaces_.erase(it); 679 interfaces_.erase(it);
594 RefreshEndpointInfo(); 680 RefreshEndpointInfo();
595 callback.Run(true); 681 callback.Run(true);
596 } 682 }
597 683
598 void UsbDeviceHandleUsbfs::SetInterfaceBlocking(
599 int interface_number,
600 int alternate_setting,
601 const ResultCallback& callback) {
602 if (!fd_.is_valid()) {
603 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
604 return;
605 }
606
607 usbdevfs_setinterface cmd = {0};
608 cmd.interface = interface_number;
609 cmd.altsetting = alternate_setting;
610 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SETINTERFACE, &cmd));
611 if (rc) {
612 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
613 << " to alternate setting " << alternate_setting;
614 }
615 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
616 }
617
618 void UsbDeviceHandleUsbfs::ResetDeviceBlocking(const ResultCallback& callback) {
619 if (!fd_.is_valid()) {
620 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
621 return;
622 }
623
624 // TODO(reillyg): libusb releases interfaces before and then reclaims
625 // interfaces after a reset. We should probably do this too or document that
626 // callers have to call ClaimInterface as well.
627 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr));
628 if (rc)
629 USB_PLOG(DEBUG) << "Failed to reset the device";
630 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
631 }
632
633 void UsbDeviceHandleUsbfs::ClearHaltBlocking(uint8_t endpoint_address,
634 const ResultCallback& callback) {
635 if (!fd_.is_valid()) {
636 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
637 return;
638 }
639
640 int tmp_endpoint = endpoint_address;
641 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_CLEAR_HALT, &tmp_endpoint));
642 if (rc) {
643 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
644 << static_cast<int>(endpoint_address);
645 }
646 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0));
647 }
648
649 void UsbDeviceHandleUsbfs::IsochronousTransferInternal( 684 void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
650 uint8_t endpoint_address, 685 uint8_t endpoint_address,
651 scoped_refptr<net::IOBuffer> buffer, 686 scoped_refptr<net::IOBuffer> buffer,
652 size_t total_length, 687 size_t total_length,
653 const std::vector<uint32_t>& packet_lengths, 688 const std::vector<uint32_t>& packet_lengths,
654 unsigned int timeout, 689 unsigned int timeout,
655 const IsochronousTransferCallback& callback) { 690 const IsochronousTransferCallback& callback) {
656 if (!device_) { 691 if (!device_) {
657 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); 692 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT);
658 return; 693 return;
(...skipping 13 matching lines...) Expand all
672 transfer->urb.endpoint = endpoint_address; 707 transfer->urb.endpoint = endpoint_address;
673 transfer->urb.buffer_length = total_length; 708 transfer->urb.buffer_length = total_length;
674 709
675 for (size_t i = 0; i < packet_lengths.size(); ++i) 710 for (size_t i = 0; i < packet_lengths.size(); ++i)
676 transfer->urb.iso_frame_desc[i].length = packet_lengths[i]; 711 transfer->urb.iso_frame_desc[i].length = packet_lengths[i];
677 712
678 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported 713 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
679 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can 714 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can
680 // accept arbitrarily large transfer requests, hopefully also using a scatter- 715 // accept arbitrarily large transfer requests, hopefully also using a scatter-
681 // gather list. 716 // gather list.
682 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); 717 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
683 if (rc) { 718 if (rc) {
684 rc = logging::GetLastSystemErrorCode(); 719 rc = logging::GetLastSystemErrorCode();
685 USB_PLOG(DEBUG) << "Failed to submit transfer"; 720 USB_PLOG(DEBUG) << "Failed to submit transfer";
686 ReportIsochronousError(packet_lengths, callback, ConvertTransferResult(rc)); 721 ReportIsochronousError(packet_lengths, callback, ConvertTransferResult(rc));
687 } else { 722 } else {
688 SetUpTimeoutCallback(transfer.get(), timeout); 723 SetUpTimeoutCallback(transfer.get(), timeout);
689 transfers_.push_back(std::move(transfer)); 724 transfers_.push_back(std::move(transfer));
690 } 725 }
691 } 726 }
692 727
(...skipping 25 matching lines...) Expand all
718 std::unique_ptr<Transfer> transfer( 753 std::unique_ptr<Transfer> transfer(
719 new (0) Transfer(buffer, callback, callback_runner)); 754 new (0) Transfer(buffer, callback, callback_runner));
720 transfer->urb.endpoint = endpoint_address; 755 transfer->urb.endpoint = endpoint_address;
721 transfer->urb.buffer_length = length; 756 transfer->urb.buffer_length = length;
722 transfer->urb.type = ConvertTransferType(it->second.type); 757 transfer->urb.type = ConvertTransferType(it->second.type);
723 758
724 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported 759 // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
725 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can 760 // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can
726 // accept arbitrarily large transfer requests, hopefully also using a scatter- 761 // accept arbitrarily large transfer requests, hopefully also using a scatter-
727 // gather list. 762 // gather list.
728 int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SUBMITURB, &transfer->urb)); 763 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
729 if (rc) { 764 if (rc) {
730 rc = logging::GetLastSystemErrorCode(); 765 rc = logging::GetLastSystemErrorCode();
731 USB_PLOG(DEBUG) << "Failed to submit transfer"; 766 USB_PLOG(DEBUG) << "Failed to submit transfer";
732 callback_runner->PostTask( 767 callback_runner->PostTask(
733 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0)); 768 FROM_HERE, base::Bind(callback, ConvertTransferResult(rc), nullptr, 0));
734 } else { 769 } else {
735 SetUpTimeoutCallback(transfer.get(), timeout); 770 SetUpTimeoutCallback(transfer.get(), timeout);
736 transfers_.push_back(std::move(transfer)); 771 transfers_.push_back(std::move(transfer));
737 } 772 }
738 } 773 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 packets[i].length = transfer->urb.iso_frame_desc[i].length; 903 packets[i].length = transfer->urb.iso_frame_desc[i].length;
869 packets[i].transferred_length = 0; 904 packets[i].transferred_length = 0;
870 packets[i].status = status; 905 packets[i].status = status;
871 } 906 }
872 transfer->RunIsochronousCallback(packets); 907 transfer->RunIsochronousCallback(packets);
873 } else { 908 } else {
874 transfer->RunCallback(status, 0); 909 transfer->RunCallback(status, 0);
875 } 910 }
876 911
877 blocking_task_runner_->PostTask( 912 blocking_task_runner_->PostTask(
878 FROM_HERE, 913 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb,
879 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer)); 914 base::Unretained(helper_.get()), transfer));
880 } 915 }
881 916
882 void UsbDeviceHandleUsbfs::DiscardUrbBlocking(Transfer* transfer) {
883 if (fd_.is_valid())
884 HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));
885
886 task_runner_->PostTask(
887 FROM_HERE,
888 base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, this, transfer));
889 }
890 917
891 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { 918 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
892 transfer->discarded = true; 919 transfer->discarded = true;
893 if (transfer->reaped) 920 if (transfer->reaped)
894 RemoveFromTransferList(transfer); 921 RemoveFromTransferList(transfer);
895 } 922 }
896 923
897 } // namespace device 924 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/usb_device_handle_usbfs.h ('k') | device/usb/usb_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698