OLD | NEW |
---|---|
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" |
24 #include "base/stl_util.h" | 23 #include "base/stl_util.h" |
25 #include "base/threading/thread_restrictions.h" | 24 #include "base/threading/thread_restrictions.h" |
26 #include "base/threading/thread_task_runner_handle.h" | 25 #include "base/threading/thread_task_runner_handle.h" |
27 #include "components/device_event_log/device_event_log.h" | 26 #include "components/device_event_log/device_event_log.h" |
28 #include "device/usb/usb_device_linux.h" | 27 #include "device/usb/usb_device_linux.h" |
29 #include "net/base/io_buffer.h" | 28 #include "net/base/io_buffer.h" |
30 | 29 |
31 namespace device { | 30 namespace device { |
32 | 31 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 // TODO(reillyg): Add a specific error message whenever one of the cases | 126 // TODO(reillyg): Add a specific error message whenever one of the cases |
128 // above fails to match. | 127 // above fails to match. |
129 USB_LOG(ERROR) << "Unknown system error: " | 128 USB_LOG(ERROR) << "Unknown system error: " |
130 << logging::SystemErrorCodeToString(rc); | 129 << logging::SystemErrorCodeToString(rc); |
131 return USB_TRANSFER_ERROR; | 130 return USB_TRANSFER_ERROR; |
132 } | 131 } |
133 } | 132 } |
134 | 133 |
135 } // namespace | 134 } // namespace |
136 | 135 |
137 class UsbDeviceHandleUsbfs::FileThreadHelper | 136 class UsbDeviceHandleUsbfs::FileThreadHelper { |
138 : public base::MessageLoop::DestructionObserver { | |
139 public: | 137 public: |
140 FileThreadHelper(int fd, | 138 FileThreadHelper(int fd, |
141 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, | 139 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, |
142 scoped_refptr<base::SequencedTaskRunner> task_runner); | 140 scoped_refptr<base::SequencedTaskRunner> task_runner); |
143 ~FileThreadHelper() override; | 141 ~FileThreadHelper(); |
144 | 142 |
145 static void Start(std::unique_ptr<FileThreadHelper> self); | 143 void Start(); |
146 | 144 |
147 // base::MessageLoop::DestructionObserver overrides. | 145 void SetConfiguration(int configuration_value, |
148 void WillDestroyCurrentMessageLoop() override; | 146 const ResultCallback& callback); |
147 void ReleaseInterface(int interface_number, const ResultCallback& callback); | |
148 void SetInterface(int interface_number, | |
149 int alternate_setting, | |
150 const ResultCallback& callback); | |
151 void ResetDevice(const ResultCallback& callback); | |
152 void ClearHalt(uint8_t endpoint_address, const ResultCallback& callback); | |
153 void DiscardUrb(Transfer* transfer); | |
149 | 154 |
150 private: | 155 private: |
151 // Called when |fd_| is writable without blocking. | 156 // Called when |fd_| is writable without blocking. |
152 void OnFileCanWriteWithoutBlocking(); | 157 void OnFileCanWriteWithoutBlocking(); |
153 | 158 |
154 int fd_; | 159 int fd_; |
155 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; | 160 scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; |
156 scoped_refptr<base::SequencedTaskRunner> task_runner_; | 161 scoped_refptr<base::SequencedTaskRunner> task_runner_; |
157 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; | 162 std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; |
158 base::ThreadChecker thread_checker_; | 163 base::ThreadChecker thread_checker_; |
159 | 164 |
160 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); | 165 DISALLOW_COPY_AND_ASSIGN(FileThreadHelper); |
161 }; | 166 }; |
162 | 167 |
168 struct UsbDeviceHandleUsbfs::Transfer { | |
169 Transfer() = delete; | |
170 Transfer(scoped_refptr<net::IOBuffer> buffer, | |
171 const TransferCallback& callback, | |
172 scoped_refptr<base::SingleThreadTaskRunner> callback_runner); | |
173 Transfer(scoped_refptr<net::IOBuffer> buffer, | |
174 const IsochronousTransferCallback& callback); | |
175 ~Transfer(); | |
176 | |
177 void* operator new(std::size_t size, size_t number_of_iso_packets); | |
178 void RunCallback(UsbTransferStatus status, size_t bytes_transferred); | |
179 void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets); | |
180 | |
181 scoped_refptr<net::IOBuffer> control_transfer_buffer; | |
182 scoped_refptr<net::IOBuffer> buffer; | |
183 base::CancelableClosure timeout_closure; | |
184 bool cancelled = false; | |
185 | |
186 // When the URB is |cancelled| these two flags track whether the URB has both | |
187 // been |discarded| and |reaped| since the possiblity of last-minute | |
188 // completion makes these two conditions race. | |
189 bool discarded = false; | |
190 bool reaped = false; | |
191 | |
192 private: | |
193 TransferCallback callback; | |
194 IsochronousTransferCallback isoc_callback; | |
195 scoped_refptr<base::SingleThreadTaskRunner> callback_runner; | |
196 | |
197 DISALLOW_COPY_AND_ASSIGN(Transfer); | |
198 | |
199 public: | |
200 // The |urb| field must be the last in the struct so that the extra space | |
201 // allocated by the overridden new function above extends the length of its | |
202 // |iso_frame_desc| field. | |
203 usbdevfs_urb urb; | |
204 }; | |
205 | |
163 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( | 206 UsbDeviceHandleUsbfs::FileThreadHelper::FileThreadHelper( |
164 int fd, | 207 int fd, |
165 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, | 208 scoped_refptr<UsbDeviceHandleUsbfs> device_handle, |
166 scoped_refptr<base::SequencedTaskRunner> task_runner) | 209 scoped_refptr<base::SequencedTaskRunner> task_runner) |
167 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {} | 210 : fd_(fd), device_handle_(device_handle), task_runner_(task_runner) {} |
168 | 211 |
169 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { | 212 UsbDeviceHandleUsbfs::FileThreadHelper::~FileThreadHelper() { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 213 DCHECK(thread_checker_.CalledOnValidThread()); |
171 base::MessageLoop::current()->RemoveDestructionObserver(this); | |
172 } | 214 } |
173 | 215 |
174 // static | 216 void UsbDeviceHandleUsbfs::FileThreadHelper::Start() { |
175 void UsbDeviceHandleUsbfs::FileThreadHelper::Start( | |
176 std::unique_ptr<FileThreadHelper> self) { | |
177 base::ThreadRestrictions::AssertIOAllowed(); | 217 base::ThreadRestrictions::AssertIOAllowed(); |
178 self->thread_checker_.DetachFromThread(); | 218 thread_checker_.DetachFromThread(); |
219 DCHECK(thread_checker_.CalledOnValidThread()); | |
179 | 220 |
180 // Linux indicates that URBs are available to reap by marking the file | 221 // Linux indicates that URBs are available to reap by marking the file |
181 // descriptor writable. | 222 // descriptor writable. |
182 self->watch_controller_ = base::FileDescriptorWatcher::WatchWritable( | 223 watch_controller_ = base::FileDescriptorWatcher::WatchWritable( |
183 self->fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, | 224 fd_, base::Bind(&FileThreadHelper::OnFileCanWriteWithoutBlocking, |
184 base::Unretained(self.get()))); | 225 base::Unretained(this))); |
185 | |
186 // |self| is now owned by the current message loop. | |
187 base::MessageLoop::current()->AddDestructionObserver(self.release()); | |
188 } | 226 } |
189 | 227 |
190 void UsbDeviceHandleUsbfs::FileThreadHelper::WillDestroyCurrentMessageLoop() { | 228 void UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration( |
229 int configuration_value, | |
230 const ResultCallback& callback) { | |
191 DCHECK(thread_checker_.CalledOnValidThread()); | 231 DCHECK(thread_checker_.CalledOnValidThread()); |
192 delete this; | 232 int rc = |
233 HANDLE_EINTR(ioctl(fd_, USBDEVFS_SETCONFIGURATION, &configuration_value)); | |
234 if (rc) | |
235 USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value; | |
236 task_runner_->PostTask( | |
237 FROM_HERE, | |
238 base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationComplete, | |
239 device_handle_, configuration_value, rc == 0, callback)); | |
240 } | |
241 | |
242 void UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface( | |
243 int interface_number, | |
244 const ResultCallback& callback) { | |
245 DCHECK(thread_checker_.CalledOnValidThread()); | |
246 int rc = | |
247 HANDLE_EINTR(ioctl(fd_, USBDEVFS_RELEASEINTERFACE, &interface_number)); | |
248 if (rc) { | |
249 USB_PLOG(DEBUG) << "Failed to release interface " << interface_number; | |
250 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | |
251 } else { | |
252 task_runner_->PostTask( | |
253 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete, | |
254 device_handle_, interface_number, callback)); | |
255 } | |
256 } | |
257 | |
258 void UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface( | |
259 int interface_number, | |
260 int alternate_setting, | |
261 const ResultCallback& callback) { | |
262 DCHECK(thread_checker_.CalledOnValidThread()); | |
263 usbdevfs_setinterface cmd = {0}; | |
264 cmd.interface = interface_number; | |
265 cmd.altsetting = alternate_setting; | |
266 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SETINTERFACE, &cmd)); | |
267 if (rc) { | |
268 USB_PLOG(DEBUG) << "Failed to set interface " << interface_number | |
269 << " to alternate setting " << alternate_setting; | |
270 } | |
271 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); | |
272 } | |
273 | |
274 void UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice( | |
275 const ResultCallback& callback) { | |
276 DCHECK(thread_checker_.CalledOnValidThread()); | |
277 // TODO(reillyg): libusb releases interfaces before and then reclaims | |
278 // interfaces after a reset. We should probably do this too or document that | |
279 // callers have to call ClaimInterface as well. | |
280 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_RESET, nullptr)); | |
281 if (rc) | |
282 USB_PLOG(DEBUG) << "Failed to reset the device"; | |
283 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); | |
284 } | |
285 | |
286 void UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt( | |
287 uint8_t endpoint_address, | |
288 const ResultCallback& callback) { | |
289 DCHECK(thread_checker_.CalledOnValidThread()); | |
290 int tmp_endpoint = endpoint_address; | |
291 int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLEAR_HALT, &tmp_endpoint)); | |
292 if (rc) { | |
293 USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint " | |
294 << static_cast<int>(endpoint_address); | |
295 } | |
296 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); | |
297 } | |
298 | |
299 void UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb(Transfer* transfer) { | |
300 DCHECK(thread_checker_.CalledOnValidThread()); | |
301 HANDLE_EINTR(ioctl(fd_, USBDEVFS_DISCARDURB, &transfer->urb)); | |
302 | |
303 task_runner_->PostTask( | |
304 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::UrbDiscarded, device_handle_, | |
305 transfer)); | |
193 } | 306 } |
194 | 307 |
195 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { | 308 void UsbDeviceHandleUsbfs::FileThreadHelper::OnFileCanWriteWithoutBlocking() { |
196 DCHECK(thread_checker_.CalledOnValidThread()); | 309 DCHECK(thread_checker_.CalledOnValidThread()); |
197 | 310 |
198 const size_t MAX_URBS_PER_EVENT = 10; | 311 const size_t MAX_URBS_PER_EVENT = 10; |
199 std::vector<usbdevfs_urb*> urbs; | 312 std::vector<usbdevfs_urb*> urbs; |
200 urbs.reserve(MAX_URBS_PER_EVENT); | 313 urbs.reserve(MAX_URBS_PER_EVENT); |
201 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { | 314 for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) { |
202 usbdevfs_urb* urb; | 315 usbdevfs_urb* urb; |
(...skipping 11 matching lines...) Expand all Loading... | |
214 } else { | 327 } else { |
215 urbs.push_back(urb); | 328 urbs.push_back(urb); |
216 } | 329 } |
217 } | 330 } |
218 | 331 |
219 task_runner_->PostTask( | 332 task_runner_->PostTask( |
220 FROM_HERE, | 333 FROM_HERE, |
221 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); | 334 base::Bind(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs)); |
222 } | 335 } |
223 | 336 |
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( | 337 UsbDeviceHandleUsbfs::Transfer::Transfer( |
263 scoped_refptr<net::IOBuffer> buffer, | 338 scoped_refptr<net::IOBuffer> buffer, |
264 const TransferCallback& callback, | 339 const TransferCallback& callback, |
265 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) | 340 scoped_refptr<base::SingleThreadTaskRunner> callback_runner) |
266 : buffer(buffer), callback(callback), callback_runner(callback_runner) { | 341 : buffer(buffer), callback(callback), callback_runner(callback_runner) { |
267 memset(&urb, 0, sizeof(urb)); | 342 memset(&urb, 0, sizeof(urb)); |
268 urb.usercontext = this; | 343 urb.usercontext = this; |
269 urb.buffer = buffer->data(); | 344 urb.buffer = buffer->data(); |
270 } | 345 } |
271 | 346 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | 393 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) |
319 : device_(device), | 394 : device_(device), |
320 fd_(std::move(fd)), | 395 fd_(std::move(fd)), |
321 blocking_task_runner_(blocking_task_runner) { | 396 blocking_task_runner_(blocking_task_runner) { |
322 DCHECK(device_); | 397 DCHECK(device_); |
323 DCHECK(fd_.is_valid()); | 398 DCHECK(fd_.is_valid()); |
324 DCHECK(blocking_task_runner_); | 399 DCHECK(blocking_task_runner_); |
325 | 400 |
326 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 401 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
327 | 402 |
328 std::unique_ptr<FileThreadHelper> helper( | 403 helper_.reset(new FileThreadHelper(fd_.get(), this, task_runner_)); |
329 new FileThreadHelper(fd_.get(), this, task_runner_)); | |
330 helper_ = helper.get(); | |
331 blocking_task_runner_->PostTask( | 404 blocking_task_runner_->PostTask( |
332 FROM_HERE, base::Bind(&FileThreadHelper::Start, base::Passed(&helper))); | 405 FROM_HERE, |
406 base::Bind(&FileThreadHelper::Start, base::Unretained(helper_.get()))); | |
scheib
2017/04/04 20:17:15
blocking_task_runner is ref counted. And helper_ i
Reilly Grant (use Gerrit)
2017/04/04 20:31:40
helper_ can only be destroyed on the FILE thread a
| |
333 } | 407 } |
334 | 408 |
335 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { | 409 scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { |
336 return device_; | 410 return device_; |
337 } | 411 } |
338 | 412 |
339 void UsbDeviceHandleUsbfs::Close() { | 413 void UsbDeviceHandleUsbfs::Close() { |
340 if (!device_) | 414 if (!device_) |
341 return; // Already closed. | 415 return; // Already closed. |
342 | 416 |
343 // On the |task_runner_| thread check |device_| to see if the handle is | 417 // 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 | 418 // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to |
345 // see if the handle is closed. | 419 // see if the handle is closed. |
346 device_->HandleClosed(this); | 420 device_->HandleClosed(this); |
347 device_ = nullptr; | 421 device_ = nullptr; |
348 | 422 |
349 for (const auto& transfer : transfers_) | 423 for (const auto& transfer : transfers_) |
350 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); | 424 CancelTransfer(transfer.get(), USB_TRANSFER_CANCELLED); |
351 | 425 |
352 blocking_task_runner_->PostTask( | 426 blocking_task_runner_->PostTask( |
353 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); | 427 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); |
354 } | 428 } |
355 | 429 |
356 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, | 430 void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, |
357 const ResultCallback& callback) { | 431 const ResultCallback& callback) { |
358 // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request | 432 // 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 | 433 // to the device so it must be performed on a thread where it is okay to |
360 // block. | 434 // block. |
361 blocking_task_runner_->PostTask( | 435 blocking_task_runner_->PostTask( |
362 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetConfigurationBlocking, | 436 FROM_HERE, |
363 this, configuration_value, callback)); | 437 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetConfiguration, |
438 base::Unretained(helper_.get()), configuration_value, | |
439 callback)); | |
364 } | 440 } |
365 | 441 |
366 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, | 442 void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, |
367 const ResultCallback& callback) { | 443 const ResultCallback& callback) { |
368 if (!device_) { | 444 if (!device_) { |
369 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); | 445 task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
370 return; | 446 return; |
371 } | 447 } |
372 | 448 |
373 if (base::ContainsKey(interfaces_, interface_number)) { | 449 if (base::ContainsKey(interfaces_, interface_number)) { |
(...skipping 13 matching lines...) Expand all Loading... | |
387 } | 463 } |
388 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); | 464 task_runner_->PostTask(FROM_HERE, base::Bind(callback, rc == 0)); |
389 } | 465 } |
390 | 466 |
391 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, | 467 void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, |
392 const ResultCallback& callback) { | 468 const ResultCallback& callback) { |
393 // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the | 469 // 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 | 470 // device to restore alternate setting 0 so it must be performed on a thread |
395 // where it is okay to block. | 471 // where it is okay to block. |
396 blocking_task_runner_->PostTask( | 472 blocking_task_runner_->PostTask( |
397 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ReleaseInterfaceBlocking, | 473 FROM_HERE, |
398 this, interface_number, callback)); | 474 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ReleaseInterface, |
475 base::Unretained(helper_.get()), interface_number, callback)); | |
399 } | 476 } |
400 | 477 |
401 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( | 478 void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( |
402 int interface_number, | 479 int interface_number, |
403 int alternate_setting, | 480 int alternate_setting, |
404 const ResultCallback& callback) { | 481 const ResultCallback& callback) { |
405 // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE | 482 // 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 | 483 // request to the device so it must be performed on a thread where it is okay |
407 // to block. | 484 // to block. |
408 blocking_task_runner_->PostTask( | 485 blocking_task_runner_->PostTask( |
409 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::SetInterfaceBlocking, this, | 486 FROM_HERE, |
410 interface_number, alternate_setting, callback)); | 487 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::SetInterface, |
488 base::Unretained(helper_.get()), interface_number, | |
489 alternate_setting, callback)); | |
411 } | 490 } |
412 | 491 |
413 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { | 492 void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { |
414 // USBDEVFS_RESET is synchronous because it waits for the port to be reset | 493 // 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 | 494 // and the device re-enumerated so it must be performed on a thread where it |
416 // is okay to block. | 495 // is okay to block. |
417 blocking_task_runner_->PostTask( | 496 blocking_task_runner_->PostTask( |
418 FROM_HERE, | 497 FROM_HERE, |
419 base::Bind(&UsbDeviceHandleUsbfs::ResetDeviceBlocking, this, callback)); | 498 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ResetDevice, |
499 base::Unretained(helper_.get()), callback)); | |
420 } | 500 } |
421 | 501 |
422 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, | 502 void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, |
423 const ResultCallback& callback) { | 503 const ResultCallback& callback) { |
424 // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE | 504 // 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 | 505 // request to the device so it must be performed on a thread where it is okay |
426 // to block. | 506 // to block. |
427 blocking_task_runner_->PostTask( | 507 blocking_task_runner_->PostTask( |
428 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::ClearHaltBlocking, this, | 508 FROM_HERE, |
429 endpoint_address, callback)); | 509 base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::ClearHalt, |
510 base::Unretained(helper_.get()), endpoint_address, callback)); | |
430 } | 511 } |
431 | 512 |
432 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, | 513 void UsbDeviceHandleUsbfs::ControlTransfer(UsbEndpointDirection direction, |
433 TransferRequestType request_type, | 514 TransferRequestType request_type, |
434 TransferRecipient recipient, | 515 TransferRecipient recipient, |
435 uint8_t request, | 516 uint8_t request, |
436 uint16_t value, | 517 uint16_t value, |
437 uint16_t index, | 518 uint16_t index, |
438 scoped_refptr<net::IOBuffer> buffer, | 519 scoped_refptr<net::IOBuffer> buffer, |
439 size_t length, | 520 size_t length, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
520 return it->second.interface; | 601 return it->second.interface; |
521 return nullptr; | 602 return nullptr; |
522 } | 603 } |
523 | 604 |
524 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { | 605 UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() { |
525 DCHECK(!device_) << "Handle must be closed before it is destroyed."; | 606 DCHECK(!device_) << "Handle must be closed before it is destroyed."; |
526 } | 607 } |
527 | 608 |
528 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { | 609 void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() { |
529 ignore_result(fd_.release()); | 610 ignore_result(fd_.release()); |
530 delete helper_; | 611 helper_.reset(); |
531 } | 612 } |
532 | 613 |
533 void UsbDeviceHandleUsbfs::CloseBlocking() { | 614 void UsbDeviceHandleUsbfs::CloseBlocking() { |
534 fd_.reset(-1); | 615 fd_.reset(-1); |
535 delete helper_; | 616 helper_.reset(); |
536 } | 617 ; |
scheib
2017/04/04 20:17:15
;
Reilly Grant (use Gerrit)
2017/04/04 20:31:40
Done.
| |
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 } | 618 } |
554 | 619 |
555 void UsbDeviceHandleUsbfs::SetConfigurationComplete( | 620 void UsbDeviceHandleUsbfs::SetConfigurationComplete( |
556 int configuration_value, | 621 int configuration_value, |
557 bool success, | 622 bool success, |
558 const ResultCallback& callback) { | 623 const ResultCallback& callback) { |
559 if (success && device_) { | 624 if (success && device_) { |
560 device_->ActiveConfigurationChanged(configuration_value); | 625 device_->ActiveConfigurationChanged(configuration_value); |
561 // TODO(reillyg): If all interfaces are unclaimed before a new configuration | 626 // TODO(reillyg): If all interfaces are unclaimed before a new configuration |
562 // is set then this will do nothing. Investigate. | 627 // is set then this will do nothing. Investigate. |
563 RefreshEndpointInfo(); | 628 RefreshEndpointInfo(); |
564 } | 629 } |
565 callback.Run(success); | 630 callback.Run(success); |
566 } | 631 } |
567 | 632 |
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( | 633 void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete( |
589 int interface_number, | 634 int interface_number, |
590 const ResultCallback& callback) { | 635 const ResultCallback& callback) { |
591 auto it = interfaces_.find(interface_number); | 636 auto it = interfaces_.find(interface_number); |
592 DCHECK(it != interfaces_.end()); | 637 DCHECK(it != interfaces_.end()); |
593 interfaces_.erase(it); | 638 interfaces_.erase(it); |
594 RefreshEndpointInfo(); | 639 RefreshEndpointInfo(); |
595 callback.Run(true); | 640 callback.Run(true); |
596 } | 641 } |
597 | 642 |
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( | 643 void UsbDeviceHandleUsbfs::IsochronousTransferInternal( |
650 uint8_t endpoint_address, | 644 uint8_t endpoint_address, |
651 scoped_refptr<net::IOBuffer> buffer, | 645 scoped_refptr<net::IOBuffer> buffer, |
652 size_t total_length, | 646 size_t total_length, |
653 const std::vector<uint32_t>& packet_lengths, | 647 const std::vector<uint32_t>& packet_lengths, |
654 unsigned int timeout, | 648 unsigned int timeout, |
655 const IsochronousTransferCallback& callback) { | 649 const IsochronousTransferCallback& callback) { |
656 if (!device_) { | 650 if (!device_) { |
657 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); | 651 ReportIsochronousError(packet_lengths, callback, USB_TRANSFER_DISCONNECT); |
658 return; | 652 return; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
868 packets[i].length = transfer->urb.iso_frame_desc[i].length; | 862 packets[i].length = transfer->urb.iso_frame_desc[i].length; |
869 packets[i].transferred_length = 0; | 863 packets[i].transferred_length = 0; |
870 packets[i].status = status; | 864 packets[i].status = status; |
871 } | 865 } |
872 transfer->RunIsochronousCallback(packets); | 866 transfer->RunIsochronousCallback(packets); |
873 } else { | 867 } else { |
874 transfer->RunCallback(status, 0); | 868 transfer->RunCallback(status, 0); |
875 } | 869 } |
876 | 870 |
877 blocking_task_runner_->PostTask( | 871 blocking_task_runner_->PostTask( |
878 FROM_HERE, | 872 FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb, |
879 base::Bind(&UsbDeviceHandleUsbfs::DiscardUrbBlocking, this, transfer)); | 873 base::Unretained(helper_.get()), transfer)); |
880 } | 874 } |
881 | 875 |
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 | 876 |
891 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { | 877 void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { |
892 transfer->discarded = true; | 878 transfer->discarded = true; |
893 if (transfer->reaped) | 879 if (transfer->reaped) |
894 RemoveFromTransferList(transfer); | 880 RemoveFromTransferList(transfer); |
895 } | 881 } |
896 | 882 |
897 } // namespace device | 883 } // namespace device |
OLD | NEW |