1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/usb/usb_device_handle_impl.h"
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string16.h"
15 #include "base/synchronization/lock.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "device/usb/usb_context.h"
18 #include "device/usb/usb_descriptors.h"
19 #include "device/usb/usb_device_impl.h"
20 #include "device/usb/usb_error.h"
21 #include "device/usb/usb_service.h"
22 #include "third_party/libusb/src/libusb/libusb.h"
26 typedef libusb_device
* PlatformUsbDevice
;
28 void HandleTransferCompletion(PlatformUsbTransferHandle transfer
);
32 static uint8
ConvertTransferDirection(const UsbEndpointDirection direction
) {
34 case USB_DIRECTION_INBOUND
:
35 return LIBUSB_ENDPOINT_IN
;
36 case USB_DIRECTION_OUTBOUND
:
37 return LIBUSB_ENDPOINT_OUT
;
40 return LIBUSB_ENDPOINT_IN
;
44 static uint8
CreateRequestType(
45 const UsbEndpointDirection direction
,
46 const UsbDeviceHandle::TransferRequestType request_type
,
47 const UsbDeviceHandle::TransferRecipient recipient
) {
48 uint8 result
= ConvertTransferDirection(direction
);
50 switch (request_type
) {
51 case UsbDeviceHandle::STANDARD
:
52 result
|= LIBUSB_REQUEST_TYPE_STANDARD
;
54 case UsbDeviceHandle::CLASS
:
55 result
|= LIBUSB_REQUEST_TYPE_CLASS
;
57 case UsbDeviceHandle::VENDOR
:
58 result
|= LIBUSB_REQUEST_TYPE_VENDOR
;
60 case UsbDeviceHandle::RESERVED
:
61 result
|= LIBUSB_REQUEST_TYPE_RESERVED
;
66 case UsbDeviceHandle::DEVICE
:
67 result
|= LIBUSB_RECIPIENT_DEVICE
;
69 case UsbDeviceHandle::INTERFACE
:
70 result
|= LIBUSB_RECIPIENT_INTERFACE
;
72 case UsbDeviceHandle::ENDPOINT
:
73 result
|= LIBUSB_RECIPIENT_ENDPOINT
;
75 case UsbDeviceHandle::OTHER
:
76 result
|= LIBUSB_RECIPIENT_OTHER
;
83 static UsbTransferStatus
ConvertTransferStatus(
84 const libusb_transfer_status status
) {
86 case LIBUSB_TRANSFER_COMPLETED
:
87 return USB_TRANSFER_COMPLETED
;
88 case LIBUSB_TRANSFER_ERROR
:
89 return USB_TRANSFER_ERROR
;
90 case LIBUSB_TRANSFER_TIMED_OUT
:
91 return USB_TRANSFER_TIMEOUT
;
92 case LIBUSB_TRANSFER_STALL
:
93 return USB_TRANSFER_STALLED
;
94 case LIBUSB_TRANSFER_NO_DEVICE
:
95 return USB_TRANSFER_DISCONNECT
;
96 case LIBUSB_TRANSFER_OVERFLOW
:
97 return USB_TRANSFER_OVERFLOW
;
98 case LIBUSB_TRANSFER_CANCELLED
:
99 return USB_TRANSFER_CANCELLED
;
102 return USB_TRANSFER_ERROR
;
108 class UsbDeviceHandleImpl::InterfaceClaimer
109 : public base::RefCountedThreadSafe
<UsbDeviceHandleImpl::InterfaceClaimer
> {
111 InterfaceClaimer(const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
112 const int interface_number
);
116 int alternate_setting() const { return alternate_setting_
; }
117 void set_alternate_setting(const int alternate_setting
) {
118 alternate_setting_
= alternate_setting
;
122 friend class UsbDevice
;
123 friend class base::RefCountedThreadSafe
<InterfaceClaimer
>;
126 const scoped_refptr
<UsbDeviceHandleImpl
> handle_
;
127 const int interface_number_
;
128 int alternate_setting_
;
130 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer
);
133 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
134 const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
135 const int interface_number
)
137 interface_number_(interface_number
),
138 alternate_setting_(0) {
141 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
142 libusb_release_interface(handle_
->handle(), interface_number_
);
145 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const {
146 const int rv
= libusb_claim_interface(handle_
->handle(), interface_number_
);
147 if (rv
!= LIBUSB_SUCCESS
) {
148 VLOG(1) << "Failed to claim interface: "
149 << ConvertPlatformUsbErrorToString(rv
);
151 return rv
== LIBUSB_SUCCESS
;
154 struct UsbDeviceHandleImpl::Transfer
{
158 void Complete(UsbTransferStatus status
, size_t bytes_transferred
);
160 UsbTransferType transfer_type
;
161 scoped_refptr
<net::IOBuffer
> buffer
;
162 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
> claimed_interface
;
163 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
;
165 UsbTransferCallback callback
;
168 UsbDeviceHandleImpl::Transfer::Transfer()
169 : transfer_type(USB_TRANSFER_CONTROL
), length(0) {
172 UsbDeviceHandleImpl::Transfer::~Transfer() {
175 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status
,
176 size_t bytes_transferred
) {
177 if (task_runner
->RunsTasksOnCurrentThread()) {
178 callback
.Run(status
, buffer
, bytes_transferred
);
180 task_runner
->PostTask(
181 FROM_HERE
, base::Bind(callback
, status
, buffer
, bytes_transferred
));
185 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr
<UsbContext
> context
,
186 UsbDeviceImpl
* device
,
187 PlatformUsbDeviceHandle handle
,
188 const UsbConfigDescriptor
& config
)
193 task_runner_(base::ThreadTaskRunnerHandle::Get()) {
194 DCHECK(handle
) << "Cannot create device with NULL handle.";
197 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
198 DCHECK(thread_checker_
.CalledOnValidThread());
200 libusb_close(handle_
);
204 scoped_refptr
<UsbDevice
> UsbDeviceHandleImpl::GetDevice() const {
205 return static_cast<UsbDevice
*>(device_
);
208 void UsbDeviceHandleImpl::Close() {
209 DCHECK(thread_checker_
.CalledOnValidThread());
211 device_
->Close(this);
215 void LIBUSB_CALL
UsbDeviceHandleImpl::PlatformTransferCallback(
216 PlatformUsbTransferHandle transfer
) {
217 UsbDeviceHandleImpl
* device_handle
=
218 reinterpret_cast<UsbDeviceHandleImpl
*>(transfer
->user_data
);
219 device_handle
->task_runner_
->PostTask(
222 &UsbDeviceHandleImpl::CompleteTransfer
, device_handle
, transfer
));
225 void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle
) {
226 DCHECK(ContainsKey(transfers_
, handle
)) << "Missing transfer completed";
228 Transfer transfer
= transfers_
[handle
];
229 transfers_
.erase(handle
);
231 DCHECK_GE(handle
->actual_length
, 0) << "Negative actual length received";
232 size_t actual_length
=
233 static_cast<size_t>(std::max(handle
->actual_length
, 0));
235 DCHECK(transfer
.length
>= actual_length
)
236 << "data too big for our buffer (libusb failure?)";
238 switch (transfer
.transfer_type
) {
239 case USB_TRANSFER_CONTROL
:
240 // If the transfer is a control transfer we do not expose the control
241 // setup header to the caller. This logic strips off the header if
242 // present before invoking the callback provided with the transfer.
243 if (actual_length
> 0) {
244 CHECK(transfer
.length
>= LIBUSB_CONTROL_SETUP_SIZE
)
245 << "buffer was not correctly set: too small for the control header";
247 if (transfer
.length
>= (LIBUSB_CONTROL_SETUP_SIZE
+ actual_length
)) {
248 // If the payload is zero bytes long, pad out the allocated buffer
249 // size to one byte so that an IOBuffer of that size can be allocated.
250 scoped_refptr
<net::IOBuffer
> resized_buffer
=
251 new net::IOBuffer(static_cast<int>(
252 std::max(actual_length
, static_cast<size_t>(1))));
253 memcpy(resized_buffer
->data(),
254 transfer
.buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
,
256 transfer
.buffer
= resized_buffer
;
261 case USB_TRANSFER_ISOCHRONOUS
:
262 // Isochronous replies might carry data in the different isoc packets even
263 // if the transfer actual_data value is zero. Furthermore, not all of the
264 // received packets might contain data, so we need to calculate how many
265 // data bytes we are effectively providing and pack the results.
266 if (actual_length
== 0) {
267 size_t packet_buffer_start
= 0;
268 for (int i
= 0; i
< handle
->num_iso_packets
; ++i
) {
269 PlatformUsbIsoPacketDescriptor packet
= &handle
->iso_packet_desc
[i
];
270 if (packet
->actual_length
> 0) {
271 // We don't need to copy as long as all packets until now provide
272 // all the data the packet can hold.
273 if (actual_length
< packet_buffer_start
) {
274 CHECK(packet_buffer_start
+ packet
->actual_length
<=
276 memmove(transfer
.buffer
->data() + actual_length
,
277 transfer
.buffer
->data() + packet_buffer_start
,
278 packet
->actual_length
);
280 actual_length
+= packet
->actual_length
;
283 packet_buffer_start
+= packet
->length
;
288 case USB_TRANSFER_BULK
:
289 case USB_TRANSFER_INTERRUPT
:
293 NOTREACHED() << "Invalid usb transfer type";
297 transfer
.Complete(ConvertTransferStatus(handle
->status
), actual_length
);
298 libusb_free_transfer(handle
);
300 // Must release interface first before actually delete this.
301 transfer
.claimed_interface
= NULL
;
304 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number
) {
305 DCHECK(thread_checker_
.CalledOnValidThread());
308 if (ContainsKey(claimed_interfaces_
, interface_number
))
311 scoped_refptr
<InterfaceClaimer
> claimer
=
312 new InterfaceClaimer(this, interface_number
);
314 if (claimer
->Claim()) {
315 claimed_interfaces_
[interface_number
] = claimer
;
316 RefreshEndpointMap();
322 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number
) {
323 DCHECK(thread_checker_
.CalledOnValidThread());
326 if (!ContainsKey(claimed_interfaces_
, interface_number
))
329 // Cancel all the transfers on that interface.
330 InterfaceClaimer
* interface_claimer
=
331 claimed_interfaces_
[interface_number
].get();
332 for (TransferMap::iterator it
= transfers_
.begin(); it
!= transfers_
.end();
334 if (it
->second
.claimed_interface
.get() == interface_claimer
)
335 libusb_cancel_transfer(it
->first
);
337 claimed_interfaces_
.erase(interface_number
);
339 RefreshEndpointMap();
343 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
344 const int interface_number
,
345 const int alternate_setting
) {
346 DCHECK(thread_checker_
.CalledOnValidThread());
349 if (!ContainsKey(claimed_interfaces_
, interface_number
))
351 const int rv
= libusb_set_interface_alt_setting(
352 handle_
, interface_number
, alternate_setting
);
353 if (rv
== LIBUSB_SUCCESS
) {
354 claimed_interfaces_
[interface_number
]->set_alternate_setting(
356 RefreshEndpointMap();
358 VLOG(1) << "Failed to set interface (" << interface_number
<< ", "
360 << "): " << ConvertPlatformUsbErrorToString(rv
);
362 return rv
== LIBUSB_SUCCESS
;
365 bool UsbDeviceHandleImpl::ResetDevice() {
366 DCHECK(thread_checker_
.CalledOnValidThread());
370 const int rv
= libusb_reset_device(handle_
);
371 if (rv
!= LIBUSB_SUCCESS
) {
372 VLOG(1) << "Failed to reset device: "
373 << ConvertPlatformUsbErrorToString(rv
);
375 return rv
== LIBUSB_SUCCESS
;
378 bool UsbDeviceHandleImpl::GetSupportedLanguages() {
379 if (!languages_
.empty()) {
383 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
384 uint16 languages
[128];
385 int size
= libusb_get_string_descriptor(
389 reinterpret_cast<unsigned char*>(&languages
[0]),
392 VLOG(1) << "Failed to get list of supported languages: "
393 << ConvertPlatformUsbErrorToString(size
);
395 } else if (size
< 2) {
396 VLOG(1) << "String descriptor zero has no header.";
398 // The first 2 bytes of the descriptor are the total length and type tag.
399 } else if ((languages
[0] & 0xff) != size
) {
400 VLOG(1) << "String descriptor zero size mismatch: " << (languages
[0] & 0xff)
403 } else if ((languages
[0] >> 8) != LIBUSB_DT_STRING
) {
404 VLOG(1) << "String descriptor zero is not a string descriptor.";
408 languages_
.assign(languages
[1], languages
[(size
- 2) / 2]);
412 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id
,
413 base::string16
* string
) {
414 if (!GetSupportedLanguages()) {
418 std::map
<uint8
, base::string16
>::const_iterator it
= strings_
.find(string_id
);
419 if (it
!= strings_
.end()) {
420 *string
= it
->second
;
424 for (size_t i
= 0; i
< languages_
.size(); ++i
) {
425 // Get the string using language ID.
426 uint16 language_id
= languages_
[i
];
427 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
428 base::char16 text
[128];
430 libusb_get_string_descriptor(handle_
,
433 reinterpret_cast<unsigned char*>(&text
[0]),
436 VLOG(1) << "Failed to get string descriptor " << string_id
<< " (langid "
437 << language_id
<< "): " << ConvertPlatformUsbErrorToString(size
);
439 } else if (size
< 2) {
440 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
441 << ") has no header.";
443 // The first 2 bytes of the descriptor are the total length and type tag.
444 } else if ((text
[0] & 0xff) != size
) {
445 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
446 << ") size mismatch: " << (text
[0] & 0xff) << " != " << size
;
448 } else if ((text
[0] >> 8) != LIBUSB_DT_STRING
) {
449 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
450 << ") is not a string descriptor.";
454 *string
= base::string16(text
+ 1, (size
- 2) / 2);
455 strings_
[string_id
] = *string
;
462 bool UsbDeviceHandleImpl::GetManufacturer(base::string16
* manufacturer
) {
463 DCHECK(thread_checker_
.CalledOnValidThread());
464 PlatformUsbDevice device
= libusb_get_device(handle_
);
465 libusb_device_descriptor desc
;
467 // This is a non-blocking call as libusb has the descriptor in memory.
468 const int rv
= libusb_get_device_descriptor(device
, &desc
);
469 if (rv
!= LIBUSB_SUCCESS
) {
470 VLOG(1) << "Failed to read device descriptor: "
471 << ConvertPlatformUsbErrorToString(rv
);
475 if (desc
.iManufacturer
== 0) {
479 return GetStringDescriptor(desc
.iManufacturer
, manufacturer
);
482 bool UsbDeviceHandleImpl::GetProduct(base::string16
* product
) {
483 DCHECK(thread_checker_
.CalledOnValidThread());
484 PlatformUsbDevice device
= libusb_get_device(handle_
);
485 libusb_device_descriptor desc
;
487 // This is a non-blocking call as libusb has the descriptor in memory.
488 const int rv
= libusb_get_device_descriptor(device
, &desc
);
489 if (rv
!= LIBUSB_SUCCESS
) {
490 VLOG(1) << "Failed to read device descriptor: "
491 << ConvertPlatformUsbErrorToString(rv
);
495 if (desc
.iProduct
== 0) {
499 return GetStringDescriptor(desc
.iProduct
, product
);
502 bool UsbDeviceHandleImpl::GetSerial(base::string16
* serial
) {
503 DCHECK(thread_checker_
.CalledOnValidThread());
504 PlatformUsbDevice device
= libusb_get_device(handle_
);
505 libusb_device_descriptor desc
;
507 // This is a non-blocking call as libusb has the descriptor in memory.
508 const int rv
= libusb_get_device_descriptor(device
, &desc
);
509 if (rv
!= LIBUSB_SUCCESS
) {
510 VLOG(1) << "Failed to read device descriptor: "
511 << ConvertPlatformUsbErrorToString(rv
);
515 if (desc
.iSerialNumber
== 0) {
519 return GetStringDescriptor(desc
.iSerialNumber
, serial
);
522 void UsbDeviceHandleImpl::ControlTransfer(
523 const UsbEndpointDirection direction
,
524 const TransferRequestType request_type
,
525 const TransferRecipient recipient
,
529 net::IOBuffer
* buffer
,
531 const unsigned int timeout
,
532 const UsbTransferCallback
& callback
) {
534 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
538 const size_t resized_length
= LIBUSB_CONTROL_SETUP_SIZE
+ length
;
539 scoped_refptr
<net::IOBuffer
> resized_buffer(
540 new net::IOBufferWithSize(static_cast<int>(resized_length
)));
541 if (!resized_buffer
.get()) {
542 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
545 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
,
547 static_cast<int>(length
));
549 PlatformUsbTransferHandle
const transfer
= libusb_alloc_transfer(0);
550 const uint8 converted_type
=
551 CreateRequestType(direction
, request_type
, recipient
);
552 libusb_fill_control_setup(reinterpret_cast<uint8
*>(resized_buffer
->data()),
557 static_cast<int16
>(length
));
558 libusb_fill_control_transfer(transfer
,
560 reinterpret_cast<uint8
*>(resized_buffer
->data()),
561 &UsbDeviceHandleImpl::PlatformTransferCallback
,
565 PostOrSubmitTransfer(transfer
,
566 USB_TRANSFER_CONTROL
,
567 resized_buffer
.get(),
572 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction
,
573 const uint8 endpoint
,
574 net::IOBuffer
* buffer
,
576 const unsigned int timeout
,
577 const UsbTransferCallback
& callback
) {
579 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
583 PlatformUsbTransferHandle
const transfer
= libusb_alloc_transfer(0);
584 const uint8 new_endpoint
= ConvertTransferDirection(direction
) | endpoint
;
585 libusb_fill_bulk_transfer(transfer
,
588 reinterpret_cast<uint8
*>(buffer
->data()),
589 static_cast<int>(length
),
590 &UsbDeviceHandleImpl::PlatformTransferCallback
,
594 PostOrSubmitTransfer(transfer
, USB_TRANSFER_BULK
, buffer
, length
, callback
);
597 void UsbDeviceHandleImpl::InterruptTransfer(
598 const UsbEndpointDirection direction
,
599 const uint8 endpoint
,
600 net::IOBuffer
* buffer
,
602 const unsigned int timeout
,
603 const UsbTransferCallback
& callback
) {
605 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
609 PlatformUsbTransferHandle
const transfer
= libusb_alloc_transfer(0);
610 const uint8 new_endpoint
= ConvertTransferDirection(direction
) | endpoint
;
611 libusb_fill_interrupt_transfer(transfer
,
614 reinterpret_cast<uint8
*>(buffer
->data()),
615 static_cast<int>(length
),
616 &UsbDeviceHandleImpl::PlatformTransferCallback
,
620 PostOrSubmitTransfer(
621 transfer
, USB_TRANSFER_INTERRUPT
, buffer
, length
, callback
);
624 void UsbDeviceHandleImpl::IsochronousTransfer(
625 const UsbEndpointDirection direction
,
626 const uint8 endpoint
,
627 net::IOBuffer
* buffer
,
629 const unsigned int packets
,
630 const unsigned int packet_length
,
631 const unsigned int timeout
,
632 const UsbTransferCallback
& callback
) {
634 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
638 const uint64 total_length
= packets
* packet_length
;
639 CHECK(packets
<= length
&& total_length
<= length
)
640 << "transfer length is too small";
642 PlatformUsbTransferHandle
const transfer
= libusb_alloc_transfer(packets
);
643 const uint8 new_endpoint
= ConvertTransferDirection(direction
) | endpoint
;
644 libusb_fill_iso_transfer(transfer
,
647 reinterpret_cast<uint8
*>(buffer
->data()),
648 static_cast<int>(length
),
650 &UsbDeviceHandleImpl::PlatformTransferCallback
,
653 libusb_set_iso_packet_lengths(transfer
, packet_length
);
655 PostOrSubmitTransfer(
656 transfer
, USB_TRANSFER_ISOCHRONOUS
, buffer
, length
, callback
);
659 void UsbDeviceHandleImpl::RefreshEndpointMap() {
660 DCHECK(thread_checker_
.CalledOnValidThread());
661 endpoint_map_
.clear();
662 for (ClaimedInterfaceMap::iterator claimedIt
= claimed_interfaces_
.begin();
663 claimedIt
!= claimed_interfaces_
.end();
665 for (UsbInterfaceDescriptor::Iterator ifaceIt
= config_
.interfaces
.begin();
666 ifaceIt
!= config_
.interfaces
.end();
668 if (ifaceIt
->interface_number
== claimedIt
->first
&&
669 ifaceIt
->alternate_setting
==
670 claimedIt
->second
->alternate_setting()) {
671 for (UsbEndpointDescriptor::Iterator endpointIt
=
672 ifaceIt
->endpoints
.begin();
673 endpointIt
!= ifaceIt
->endpoints
.end();
675 endpoint_map_
[endpointIt
->address
] = claimedIt
->first
;
683 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
684 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint
) {
685 unsigned char address
= endpoint
& LIBUSB_ENDPOINT_ADDRESS_MASK
;
686 if (ContainsKey(endpoint_map_
, address
))
687 return claimed_interfaces_
[endpoint_map_
[address
]];
691 void UsbDeviceHandleImpl::PostOrSubmitTransfer(
692 PlatformUsbTransferHandle transfer
,
693 UsbTransferType transfer_type
,
694 net::IOBuffer
* buffer
,
696 const UsbTransferCallback
& callback
) {
697 if (task_runner_
->RunsTasksOnCurrentThread()) {
698 SubmitTransfer(transfer
,
702 base::ThreadTaskRunnerHandle::Get(),
705 task_runner_
->PostTask(FROM_HERE
,
706 base::Bind(&UsbDeviceHandleImpl::SubmitTransfer
,
710 make_scoped_refptr(buffer
),
712 base::ThreadTaskRunnerHandle::Get(),
717 void UsbDeviceHandleImpl::SubmitTransfer(
718 PlatformUsbTransferHandle handle
,
719 UsbTransferType transfer_type
,
720 net::IOBuffer
* buffer
,
722 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
723 const UsbTransferCallback
& callback
) {
724 DCHECK(thread_checker_
.CalledOnValidThread());
727 transfer
.transfer_type
= transfer_type
;
728 transfer
.buffer
= buffer
;
729 transfer
.length
= length
;
730 transfer
.callback
= callback
;
731 transfer
.task_runner
= task_runner
;
734 transfer
.Complete(USB_TRANSFER_DISCONNECT
, 0);
738 // It's OK for this method to return NULL. libusb_submit_transfer will fail if
739 // it requires an interface we didn't claim.
740 transfer
.claimed_interface
= GetClaimedInterfaceForEndpoint(handle
->endpoint
);
742 const int rv
= libusb_submit_transfer(handle
);
743 if (rv
== LIBUSB_SUCCESS
) {
744 transfers_
[handle
] = transfer
;
746 VLOG(1) << "Failed to submit transfer: "
747 << ConvertPlatformUsbErrorToString(rv
);
748 transfer
.Complete(USB_TRANSFER_ERROR
, 0);
752 void UsbDeviceHandleImpl::InternalClose() {
753 DCHECK(thread_checker_
.CalledOnValidThread());
757 // Cancel all the transfers.
758 for (TransferMap::iterator it
= transfers_
.begin(); it
!= transfers_
.end();
760 // The callback will be called some time later.
761 libusb_cancel_transfer(it
->first
);
764 // Attempt-release all the interfaces.
765 // It will be retained until the transfer cancellation is finished.
766 claimed_interfaces_
.clear();
768 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
773 } // namespace device