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 // This inner class owns the underlying libusb_transfer and may outlast
155 // the UsbDeviceHandle that created it.
156 class UsbDeviceHandleImpl::Transfer
{
158 static scoped_ptr
<Transfer
> CreateControlTransfer(
164 scoped_refptr
<net::IOBuffer
> buffer
,
165 unsigned int timeout
,
166 const UsbTransferCallback
& callback
);
167 static scoped_ptr
<Transfer
> CreateBulkTransfer(
169 scoped_refptr
<net::IOBuffer
> buffer
,
171 unsigned int timeout
,
172 const UsbTransferCallback
& callback
);
173 static scoped_ptr
<Transfer
> CreateInterruptTransfer(
175 scoped_refptr
<net::IOBuffer
> buffer
,
177 unsigned int timeout
,
178 const UsbTransferCallback
& callback
);
179 static scoped_ptr
<Transfer
> CreateIsochronousTransfer(
181 scoped_refptr
<net::IOBuffer
> buffer
,
183 unsigned int packets
,
184 unsigned int packet_length
,
185 unsigned int timeout
,
186 const UsbTransferCallback
& callback
);
190 bool Submit(base::WeakPtr
<UsbDeviceHandleImpl
> device_handle
);
192 void ProcessCompletion();
193 void Complete(UsbTransferStatus status
, size_t bytes_transferred
);
195 const UsbDeviceHandleImpl::InterfaceClaimer
* claimed_interface() const {
196 return claimed_interface_
.get();
200 Transfer(UsbTransferType transfer_type
,
201 scoped_refptr
<net::IOBuffer
> buffer
,
203 const UsbTransferCallback
& callback
);
205 static void LIBUSB_CALL
PlatformCallback(PlatformUsbTransferHandle handle
);
207 UsbTransferType transfer_type_
;
208 base::WeakPtr
<UsbDeviceHandleImpl
> device_handle_
;
209 PlatformUsbTransferHandle platform_transfer_
;
210 scoped_refptr
<net::IOBuffer
> buffer_
;
211 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
> claimed_interface_
;
212 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner_
;
215 UsbTransferCallback callback_
;
216 scoped_refptr
<base::SingleThreadTaskRunner
> callback_task_runner_
;
220 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
221 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
227 scoped_refptr
<net::IOBuffer
> buffer
,
228 unsigned int timeout
,
229 const UsbTransferCallback
& callback
) {
230 scoped_ptr
<Transfer
> transfer(new Transfer(USB_TRANSFER_CONTROL
, buffer
,
231 length
+ LIBUSB_CONTROL_SETUP_SIZE
,
234 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
235 if (!transfer
->platform_transfer_
) {
236 LOG(ERROR
) << "Failed to allocate control transfer.";
240 libusb_fill_control_setup(reinterpret_cast<uint8
*>(buffer
->data()), type
,
241 request
, value
, index
, length
);
242 libusb_fill_control_transfer(transfer
->platform_transfer_
,
243 nullptr, /* filled in by Submit() */
244 reinterpret_cast<uint8
*>(buffer
->data()),
245 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
246 transfer
.get(), timeout
);
248 return transfer
.Pass();
252 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
253 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
255 scoped_refptr
<net::IOBuffer
> buffer
,
257 unsigned int timeout
,
258 const UsbTransferCallback
& callback
) {
259 scoped_ptr
<Transfer
> transfer(
260 new Transfer(USB_TRANSFER_BULK
, buffer
, length
, callback
));
262 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
263 if (!transfer
->platform_transfer_
) {
264 LOG(ERROR
) << "Failed to allocate bulk transfer.";
268 libusb_fill_bulk_transfer(transfer
->platform_transfer_
,
269 nullptr, /* filled in by Submit() */
270 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
271 static_cast<int>(length
),
272 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
273 transfer
.get(), timeout
);
275 return transfer
.Pass();
279 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
280 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
282 scoped_refptr
<net::IOBuffer
> buffer
,
284 unsigned int timeout
,
285 const UsbTransferCallback
& callback
) {
286 scoped_ptr
<Transfer
> transfer(
287 new Transfer(USB_TRANSFER_INTERRUPT
, buffer
, length
, callback
));
289 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
290 if (!transfer
->platform_transfer_
) {
291 LOG(ERROR
) << "Failed to allocate interrupt transfer.";
295 libusb_fill_interrupt_transfer(
296 transfer
->platform_transfer_
, nullptr, /* filled in by Submit() */
297 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
298 static_cast<int>(length
),
299 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
302 return transfer
.Pass();
306 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
307 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
309 scoped_refptr
<net::IOBuffer
> buffer
,
311 unsigned int packets
,
312 unsigned int packet_length
,
313 unsigned int timeout
,
314 const UsbTransferCallback
& callback
) {
315 DCHECK(packets
<= length
&& (packets
* packet_length
) <= length
)
316 << "transfer length is too small";
318 scoped_ptr
<Transfer
> transfer(
319 new Transfer(USB_TRANSFER_ISOCHRONOUS
, buffer
, length
, callback
));
321 transfer
->platform_transfer_
= libusb_alloc_transfer(packets
);
322 if (!transfer
->platform_transfer_
) {
323 LOG(ERROR
) << "Failed to allocate isochronous transfer.";
327 libusb_fill_iso_transfer(
328 transfer
->platform_transfer_
, nullptr, /* filled in by Submit() */
329 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
330 static_cast<int>(length
), packets
, &Transfer::PlatformCallback
,
331 transfer
.get(), timeout
);
332 libusb_set_iso_packet_lengths(transfer
->platform_transfer_
, packet_length
);
334 return transfer
.Pass();
337 UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type
,
338 scoped_refptr
<net::IOBuffer
> buffer
,
340 const UsbTransferCallback
& callback
)
341 : transfer_type_(transfer_type
),
345 callback_(callback
) {
346 // Remember the thread from which this transfer was created so that |callback|
347 // can be dispatched there.
348 callback_task_runner_
= base::ThreadTaskRunnerHandle::Get();
351 UsbDeviceHandleImpl::Transfer::~Transfer() {
352 if (platform_transfer_
) {
353 libusb_free_transfer(platform_transfer_
);
357 bool UsbDeviceHandleImpl::Transfer::Submit(
358 base::WeakPtr
<UsbDeviceHandleImpl
> device_handle
) {
359 device_handle_
= device_handle
;
360 // Remember the thread from which this transfer was submitted so that it can
361 // be marked complete there.
362 task_runner_
= base::ThreadTaskRunnerHandle::Get();
363 // GetClaimedInterfaceForEndpoint may return nullptr. libusb_submit_transfer
364 // will fail if it requires an interface we didn't claim.
365 claimed_interface_
= device_handle
->GetClaimedInterfaceForEndpoint(
366 platform_transfer_
->endpoint
);
367 platform_transfer_
->dev_handle
= device_handle_
->handle_
;
369 const int rv
= libusb_submit_transfer(platform_transfer_
);
370 if (rv
== LIBUSB_SUCCESS
) {
373 VLOG(1) << "Failed to submit transfer: "
374 << ConvertPlatformUsbErrorToString(rv
);
375 Complete(USB_TRANSFER_ERROR
, 0);
380 void UsbDeviceHandleImpl::Transfer::Cancel() {
382 libusb_cancel_transfer(platform_transfer_
);
383 claimed_interface_
= nullptr;
388 void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
389 DCHECK_GE(platform_transfer_
->actual_length
, 0)
390 << "Negative actual length received";
391 size_t actual_length
=
392 static_cast<size_t>(std::max(platform_transfer_
->actual_length
, 0));
394 DCHECK(length_
>= actual_length
)
395 << "data too big for our buffer (libusb failure?)";
397 switch (transfer_type_
) {
398 case USB_TRANSFER_CONTROL
:
399 // If the transfer is a control transfer we do not expose the control
400 // setup header to the caller. This logic strips off the header if
401 // present before invoking the callback provided with the transfer.
402 if (actual_length
> 0) {
403 CHECK(length_
>= LIBUSB_CONTROL_SETUP_SIZE
)
404 << "buffer was not correctly set: too small for the control header";
406 if (length_
>= (LIBUSB_CONTROL_SETUP_SIZE
+ actual_length
)) {
407 // If the payload is zero bytes long, pad out the allocated buffer
408 // size to one byte so that an IOBuffer of that size can be allocated.
409 scoped_refptr
<net::IOBuffer
> resized_buffer
=
410 new net::IOBuffer(static_cast<int>(
411 std::max(actual_length
, static_cast<size_t>(1))));
412 memcpy(resized_buffer
->data(),
413 buffer_
->data() + LIBUSB_CONTROL_SETUP_SIZE
, actual_length
);
414 buffer_
= resized_buffer
;
419 case USB_TRANSFER_ISOCHRONOUS
:
420 // Isochronous replies might carry data in the different isoc packets even
421 // if the transfer actual_data value is zero. Furthermore, not all of the
422 // received packets might contain data, so we need to calculate how many
423 // data bytes we are effectively providing and pack the results.
424 if (actual_length
== 0) {
425 size_t packet_buffer_start
= 0;
426 for (int i
= 0; i
< platform_transfer_
->num_iso_packets
; ++i
) {
427 PlatformUsbIsoPacketDescriptor packet
=
428 &platform_transfer_
->iso_packet_desc
[i
];
429 if (packet
->actual_length
> 0) {
430 // We don't need to copy as long as all packets until now provide
431 // all the data the packet can hold.
432 if (actual_length
< packet_buffer_start
) {
433 CHECK(packet_buffer_start
+ packet
->actual_length
<= length_
);
434 memmove(buffer_
->data() + actual_length
,
435 buffer_
->data() + packet_buffer_start
,
436 packet
->actual_length
);
438 actual_length
+= packet
->actual_length
;
441 packet_buffer_start
+= packet
->length
;
446 case USB_TRANSFER_BULK
:
447 case USB_TRANSFER_INTERRUPT
:
451 NOTREACHED() << "Invalid usb transfer type";
455 Complete(ConvertTransferStatus(platform_transfer_
->status
), actual_length
);
458 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status
,
459 size_t bytes_transferred
) {
460 if (callback_task_runner_
->RunsTasksOnCurrentThread()) {
461 callback_
.Run(status
, buffer_
, bytes_transferred
);
463 callback_task_runner_
->PostTask(
464 FROM_HERE
, base::Bind(callback_
, status
, buffer_
, bytes_transferred
));
469 void LIBUSB_CALL
UsbDeviceHandleImpl::Transfer::PlatformCallback(
470 PlatformUsbTransferHandle platform_transfer
) {
471 scoped_ptr
<Transfer
> transfer(
472 reinterpret_cast<Transfer
*>(platform_transfer
->user_data
));
473 DCHECK(transfer
->platform_transfer_
== platform_transfer
);
475 // Because device_handle_ is a weak pointer it is guaranteed that the callback
476 // will be discarded if the handle has been freed.
477 Transfer
* tmp_transfer
= transfer
.get(); // base::Passed invalidates transfer
478 tmp_transfer
->task_runner_
->PostTask(
479 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::CompleteTransfer
,
480 tmp_transfer
->device_handle_
,
481 base::Passed(&transfer
)));
484 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr
<UsbContext
> context
,
485 scoped_refptr
<UsbDeviceImpl
> device
,
486 PlatformUsbDeviceHandle handle
)
490 task_runner_(base::ThreadTaskRunnerHandle::Get()),
491 weak_factory_(this) {
492 DCHECK(handle
) << "Cannot create device with NULL handle.";
495 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
496 DCHECK(thread_checker_
.CalledOnValidThread());
498 libusb_close(handle_
);
502 scoped_refptr
<UsbDevice
> UsbDeviceHandleImpl::GetDevice() const {
506 void UsbDeviceHandleImpl::Close() {
507 DCHECK(thread_checker_
.CalledOnValidThread());
509 device_
->Close(this);
512 bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value
) {
513 DCHECK(thread_checker_
.CalledOnValidThread());
518 for (Transfer
* transfer
: transfers_
) {
521 claimed_interfaces_
.clear();
523 int rv
= libusb_set_configuration(handle_
, configuration_value
);
524 if (rv
== LIBUSB_SUCCESS
) {
525 device_
->RefreshConfiguration();
526 RefreshEndpointMap();
528 VLOG(1) << "Failed to set configuration " << configuration_value
<< ": "
529 << ConvertPlatformUsbErrorToString(rv
);
531 return rv
== LIBUSB_SUCCESS
;
534 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number
) {
535 DCHECK(thread_checker_
.CalledOnValidThread());
538 if (ContainsKey(claimed_interfaces_
, interface_number
))
541 scoped_refptr
<InterfaceClaimer
> claimer
=
542 new InterfaceClaimer(this, interface_number
);
544 if (claimer
->Claim()) {
545 claimed_interfaces_
[interface_number
] = claimer
;
546 RefreshEndpointMap();
552 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number
) {
553 DCHECK(thread_checker_
.CalledOnValidThread());
556 if (!ContainsKey(claimed_interfaces_
, interface_number
))
559 // Cancel all the transfers on that interface.
560 InterfaceClaimer
* interface_claimer
=
561 claimed_interfaces_
[interface_number
].get();
562 for (Transfer
* transfer
: transfers_
) {
563 if (transfer
->claimed_interface() == interface_claimer
) {
567 claimed_interfaces_
.erase(interface_number
);
569 RefreshEndpointMap();
573 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
574 const int interface_number
,
575 const int alternate_setting
) {
576 DCHECK(thread_checker_
.CalledOnValidThread());
579 if (!ContainsKey(claimed_interfaces_
, interface_number
))
581 const int rv
= libusb_set_interface_alt_setting(
582 handle_
, interface_number
, alternate_setting
);
583 if (rv
== LIBUSB_SUCCESS
) {
584 claimed_interfaces_
[interface_number
]->set_alternate_setting(
586 RefreshEndpointMap();
588 VLOG(1) << "Failed to set interface (" << interface_number
<< ", "
590 << "): " << ConvertPlatformUsbErrorToString(rv
);
592 return rv
== LIBUSB_SUCCESS
;
595 bool UsbDeviceHandleImpl::ResetDevice() {
596 DCHECK(thread_checker_
.CalledOnValidThread());
600 const int rv
= libusb_reset_device(handle_
);
601 if (rv
!= LIBUSB_SUCCESS
) {
602 VLOG(1) << "Failed to reset device: "
603 << ConvertPlatformUsbErrorToString(rv
);
605 return rv
== LIBUSB_SUCCESS
;
608 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id
,
609 base::string16
* string
) {
610 if (!GetSupportedLanguages()) {
614 std::map
<uint8
, base::string16
>::const_iterator it
= strings_
.find(string_id
);
615 if (it
!= strings_
.end()) {
616 *string
= it
->second
;
620 for (size_t i
= 0; i
< languages_
.size(); ++i
) {
621 // Get the string using language ID.
622 uint16 language_id
= languages_
[i
];
623 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
624 base::char16 text
[128];
626 libusb_get_string_descriptor(handle_
,
629 reinterpret_cast<unsigned char*>(&text
[0]),
632 VLOG(1) << "Failed to get string descriptor " << string_id
<< " (langid "
633 << language_id
<< "): " << ConvertPlatformUsbErrorToString(size
);
635 } else if (size
< 2) {
636 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
637 << ") has no header.";
639 // The first 2 bytes of the descriptor are the total length and type tag.
640 } else if ((text
[0] & 0xff) != size
) {
641 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
642 << ") size mismatch: " << (text
[0] & 0xff) << " != " << size
;
644 } else if ((text
[0] >> 8) != LIBUSB_DT_STRING
) {
645 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
646 << ") is not a string descriptor.";
650 *string
= base::string16(text
+ 1, (size
- 2) / 2);
651 strings_
[string_id
] = *string
;
658 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction
,
659 TransferRequestType request_type
,
660 TransferRecipient recipient
,
664 net::IOBuffer
* buffer
,
666 unsigned int timeout
,
667 const UsbTransferCallback
& callback
) {
668 if (length
> UINT16_MAX
) {
669 LOG(ERROR
) << "Transfer too long.";
670 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
674 const size_t resized_length
= LIBUSB_CONTROL_SETUP_SIZE
+ length
;
675 scoped_refptr
<net::IOBuffer
> resized_buffer(
676 new net::IOBufferWithSize(static_cast<int>(resized_length
)));
677 if (!resized_buffer
.get()) {
678 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
681 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
, buffer
->data(),
684 scoped_ptr
<Transfer
> transfer
= Transfer::CreateControlTransfer(
685 CreateRequestType(direction
, request_type
, recipient
), request
, value
,
686 index
, static_cast<uint16
>(length
), resized_buffer
, timeout
, callback
);
688 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
692 PostOrSubmitTransfer(transfer
.Pass());
695 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction
,
696 const uint8 endpoint
,
697 net::IOBuffer
* buffer
,
699 const unsigned int timeout
,
700 const UsbTransferCallback
& callback
) {
701 if (length
> INT_MAX
) {
702 LOG(ERROR
) << "Transfer too long.";
703 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
707 scoped_ptr
<Transfer
> transfer
= Transfer::CreateBulkTransfer(
708 ConvertTransferDirection(direction
) | endpoint
, buffer
,
709 static_cast<int>(length
), timeout
, callback
);
711 PostOrSubmitTransfer(transfer
.Pass());
714 void UsbDeviceHandleImpl::InterruptTransfer(
715 UsbEndpointDirection direction
,
717 net::IOBuffer
* buffer
,
719 unsigned int timeout
,
720 const UsbTransferCallback
& callback
) {
721 if (length
> INT_MAX
) {
722 LOG(ERROR
) << "Transfer too long.";
723 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
727 scoped_ptr
<Transfer
> transfer
= Transfer::CreateInterruptTransfer(
728 ConvertTransferDirection(direction
) | endpoint
, buffer
,
729 static_cast<int>(length
), timeout
, callback
);
731 PostOrSubmitTransfer(transfer
.Pass());
734 void UsbDeviceHandleImpl::IsochronousTransfer(
735 const UsbEndpointDirection direction
,
736 const uint8 endpoint
,
737 net::IOBuffer
* buffer
,
739 const unsigned int packets
,
740 const unsigned int packet_length
,
741 const unsigned int timeout
,
742 const UsbTransferCallback
& callback
) {
743 if (length
> INT_MAX
) {
744 LOG(ERROR
) << "Transfer too long.";
745 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
749 scoped_ptr
<Transfer
> transfer
= Transfer::CreateIsochronousTransfer(
750 ConvertTransferDirection(direction
) | endpoint
, buffer
,
751 static_cast<int>(length
), packets
, packet_length
, timeout
, callback
);
753 PostOrSubmitTransfer(transfer
.Pass());
756 void UsbDeviceHandleImpl::RefreshEndpointMap() {
757 DCHECK(thread_checker_
.CalledOnValidThread());
758 endpoint_map_
.clear();
759 const UsbConfigDescriptor
* config
= device_
->GetConfiguration();
761 for (const auto& map_entry
: claimed_interfaces_
) {
762 int interface_number
= map_entry
.first
;
763 const scoped_refptr
<InterfaceClaimer
>& claimed_iface
= map_entry
.second
;
765 for (const UsbInterfaceDescriptor
& iface
: config
->interfaces
) {
766 if (iface
.interface_number
== interface_number
&&
767 iface
.alternate_setting
== claimed_iface
->alternate_setting()) {
768 for (const UsbEndpointDescriptor
& endpoint
: iface
.endpoints
) {
769 endpoint_map_
[endpoint
.address
] = interface_number
;
778 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
779 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint
) {
780 if (ContainsKey(endpoint_map_
, endpoint
))
781 return claimed_interfaces_
[endpoint_map_
[endpoint
]];
785 void UsbDeviceHandleImpl::PostOrSubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
786 if (task_runner_
->RunsTasksOnCurrentThread()) {
787 SubmitTransfer(transfer
.Pass());
789 task_runner_
->PostTask(
790 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::SubmitTransfer
, this,
791 base::Passed(&transfer
)));
795 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
796 DCHECK(thread_checker_
.CalledOnValidThread());
799 if (transfer
->Submit(weak_factory_
.GetWeakPtr())) {
800 // Transfer is now owned by libusb until its completion callback is run.
801 // This object holds a weak reference.
802 transfers_
.insert(transfer
.release());
805 transfer
->Complete(USB_TRANSFER_DISCONNECT
, 0);
809 void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr
<Transfer
> transfer
) {
810 DCHECK(ContainsKey(transfers_
, transfer
.get()))
811 << "Missing transfer completed";
812 transfers_
.erase(transfer
.get());
813 transfer
->ProcessCompletion();
816 bool UsbDeviceHandleImpl::GetSupportedLanguages() {
817 if (!languages_
.empty()) {
821 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
822 uint16 languages
[128];
823 int size
= libusb_get_string_descriptor(
827 reinterpret_cast<unsigned char*>(&languages
[0]),
830 VLOG(1) << "Failed to get list of supported languages: "
831 << ConvertPlatformUsbErrorToString(size
);
833 } else if (size
< 2) {
834 VLOG(1) << "String descriptor zero has no header.";
836 // The first 2 bytes of the descriptor are the total length and type tag.
837 } else if ((languages
[0] & 0xff) != size
) {
838 VLOG(1) << "String descriptor zero size mismatch: " << (languages
[0] & 0xff)
841 } else if ((languages
[0] >> 8) != LIBUSB_DT_STRING
) {
842 VLOG(1) << "String descriptor zero is not a string descriptor.";
846 languages_
.assign(languages
[1], languages
[(size
- 2) / 2]);
850 void UsbDeviceHandleImpl::InternalClose() {
851 DCHECK(thread_checker_
.CalledOnValidThread());
855 // Cancel all the transfers.
856 for (Transfer
* transfer
: transfers_
) {
857 // The callback will be called some time later.
861 // Attempt-release all the interfaces.
862 // It will be retained until the transfer cancellation is finished.
863 claimed_interfaces_
.clear();
865 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
870 } // namespace device