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_
;
214 UsbTransferCallback callback_
;
215 scoped_refptr
<base::SingleThreadTaskRunner
> callback_task_runner_
;
219 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
220 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
226 scoped_refptr
<net::IOBuffer
> buffer
,
227 unsigned int timeout
,
228 const UsbTransferCallback
& callback
) {
229 scoped_ptr
<Transfer
> transfer(new Transfer(USB_TRANSFER_CONTROL
, buffer
,
230 length
+ LIBUSB_CONTROL_SETUP_SIZE
,
233 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
234 if (!transfer
->platform_transfer_
) {
235 LOG(ERROR
) << "Failed to allocate control transfer.";
239 libusb_fill_control_setup(reinterpret_cast<uint8
*>(buffer
->data()), type
,
240 request
, value
, index
, length
);
241 libusb_fill_control_transfer(transfer
->platform_transfer_
,
242 nullptr, /* filled in by Submit() */
243 reinterpret_cast<uint8
*>(buffer
->data()),
244 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
245 transfer
.get(), timeout
);
247 return transfer
.Pass();
251 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
252 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
254 scoped_refptr
<net::IOBuffer
> buffer
,
256 unsigned int timeout
,
257 const UsbTransferCallback
& callback
) {
258 scoped_ptr
<Transfer
> transfer(
259 new Transfer(USB_TRANSFER_BULK
, buffer
, length
, callback
));
261 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
262 if (!transfer
->platform_transfer_
) {
263 LOG(ERROR
) << "Failed to allocate bulk transfer.";
267 libusb_fill_bulk_transfer(transfer
->platform_transfer_
,
268 nullptr, /* filled in by Submit() */
269 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
270 static_cast<int>(length
),
271 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
272 transfer
.get(), timeout
);
274 return transfer
.Pass();
278 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
279 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
281 scoped_refptr
<net::IOBuffer
> buffer
,
283 unsigned int timeout
,
284 const UsbTransferCallback
& callback
) {
285 scoped_ptr
<Transfer
> transfer(
286 new Transfer(USB_TRANSFER_INTERRUPT
, buffer
, length
, callback
));
288 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
289 if (!transfer
->platform_transfer_
) {
290 LOG(ERROR
) << "Failed to allocate interrupt transfer.";
294 libusb_fill_interrupt_transfer(
295 transfer
->platform_transfer_
, nullptr, /* filled in by Submit() */
296 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
297 static_cast<int>(length
),
298 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
301 return transfer
.Pass();
305 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
306 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
308 scoped_refptr
<net::IOBuffer
> buffer
,
310 unsigned int packets
,
311 unsigned int packet_length
,
312 unsigned int timeout
,
313 const UsbTransferCallback
& callback
) {
314 DCHECK(packets
<= length
&& (packets
* packet_length
) <= length
)
315 << "transfer length is too small";
317 scoped_ptr
<Transfer
> transfer(
318 new Transfer(USB_TRANSFER_ISOCHRONOUS
, buffer
, length
, callback
));
320 transfer
->platform_transfer_
= libusb_alloc_transfer(packets
);
321 if (!transfer
->platform_transfer_
) {
322 LOG(ERROR
) << "Failed to allocate isochronous transfer.";
326 libusb_fill_iso_transfer(
327 transfer
->platform_transfer_
, nullptr, /* filled in by Submit() */
328 endpoint
, reinterpret_cast<uint8
*>(buffer
->data()),
329 static_cast<int>(length
), packets
, &Transfer::PlatformCallback
,
330 transfer
.get(), timeout
);
331 libusb_set_iso_packet_lengths(transfer
->platform_transfer_
, packet_length
);
333 return transfer
.Pass();
336 UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type
,
337 scoped_refptr
<net::IOBuffer
> buffer
,
339 const UsbTransferCallback
& callback
)
340 : transfer_type_(transfer_type
),
343 callback_(callback
) {
344 // Remember the thread from which this transfer was created so that |callback|
345 // can be dispatched there.
346 callback_task_runner_
= base::ThreadTaskRunnerHandle::Get();
349 UsbDeviceHandleImpl::Transfer::~Transfer() {
350 if (platform_transfer_
) {
351 libusb_free_transfer(platform_transfer_
);
355 bool UsbDeviceHandleImpl::Transfer::Submit(
356 base::WeakPtr
<UsbDeviceHandleImpl
> device_handle
) {
357 device_handle_
= device_handle
;
358 // Remember the thread from which this transfer was submitted so that it can
359 // be marked complete there.
360 task_runner_
= base::ThreadTaskRunnerHandle::Get();
361 // GetClaimedInterfaceForEndpoint may return nullptr. libusb_submit_transfer
362 // will fail if it requires an interface we didn't claim.
363 claimed_interface_
= device_handle
->GetClaimedInterfaceForEndpoint(
364 platform_transfer_
->endpoint
);
365 platform_transfer_
->dev_handle
= device_handle_
->handle_
;
367 const int rv
= libusb_submit_transfer(platform_transfer_
);
368 if (rv
== LIBUSB_SUCCESS
) {
371 VLOG(1) << "Failed to submit transfer: "
372 << ConvertPlatformUsbErrorToString(rv
);
373 Complete(USB_TRANSFER_ERROR
, 0);
378 void UsbDeviceHandleImpl::Transfer::Cancel() {
379 libusb_cancel_transfer(platform_transfer_
);
380 claimed_interface_
= nullptr;
383 void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
384 DCHECK_GE(platform_transfer_
->actual_length
, 0)
385 << "Negative actual length received";
386 size_t actual_length
=
387 static_cast<size_t>(std::max(platform_transfer_
->actual_length
, 0));
389 DCHECK(length_
>= actual_length
)
390 << "data too big for our buffer (libusb failure?)";
392 switch (transfer_type_
) {
393 case USB_TRANSFER_CONTROL
:
394 // If the transfer is a control transfer we do not expose the control
395 // setup header to the caller. This logic strips off the header if
396 // present before invoking the callback provided with the transfer.
397 if (actual_length
> 0) {
398 CHECK(length_
>= LIBUSB_CONTROL_SETUP_SIZE
)
399 << "buffer was not correctly set: too small for the control header";
401 if (length_
>= (LIBUSB_CONTROL_SETUP_SIZE
+ actual_length
)) {
402 // If the payload is zero bytes long, pad out the allocated buffer
403 // size to one byte so that an IOBuffer of that size can be allocated.
404 scoped_refptr
<net::IOBuffer
> resized_buffer
=
405 new net::IOBuffer(static_cast<int>(
406 std::max(actual_length
, static_cast<size_t>(1))));
407 memcpy(resized_buffer
->data(),
408 buffer_
->data() + LIBUSB_CONTROL_SETUP_SIZE
, actual_length
);
409 buffer_
= resized_buffer
;
414 case USB_TRANSFER_ISOCHRONOUS
:
415 // Isochronous replies might carry data in the different isoc packets even
416 // if the transfer actual_data value is zero. Furthermore, not all of the
417 // received packets might contain data, so we need to calculate how many
418 // data bytes we are effectively providing and pack the results.
419 if (actual_length
== 0) {
420 size_t packet_buffer_start
= 0;
421 for (int i
= 0; i
< platform_transfer_
->num_iso_packets
; ++i
) {
422 PlatformUsbIsoPacketDescriptor packet
=
423 &platform_transfer_
->iso_packet_desc
[i
];
424 if (packet
->actual_length
> 0) {
425 // We don't need to copy as long as all packets until now provide
426 // all the data the packet can hold.
427 if (actual_length
< packet_buffer_start
) {
428 CHECK(packet_buffer_start
+ packet
->actual_length
<= length_
);
429 memmove(buffer_
->data() + actual_length
,
430 buffer_
->data() + packet_buffer_start
,
431 packet
->actual_length
);
433 actual_length
+= packet
->actual_length
;
436 packet_buffer_start
+= packet
->length
;
441 case USB_TRANSFER_BULK
:
442 case USB_TRANSFER_INTERRUPT
:
446 NOTREACHED() << "Invalid usb transfer type";
450 Complete(ConvertTransferStatus(platform_transfer_
->status
), actual_length
);
453 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status
,
454 size_t bytes_transferred
) {
455 if (callback_task_runner_
->RunsTasksOnCurrentThread()) {
456 callback_
.Run(status
, buffer_
, bytes_transferred
);
458 callback_task_runner_
->PostTask(
459 FROM_HERE
, base::Bind(callback_
, status
, buffer_
, bytes_transferred
));
464 void LIBUSB_CALL
UsbDeviceHandleImpl::Transfer::PlatformCallback(
465 PlatformUsbTransferHandle platform_transfer
) {
466 scoped_ptr
<Transfer
> transfer(
467 reinterpret_cast<Transfer
*>(platform_transfer
->user_data
));
468 DCHECK(transfer
->platform_transfer_
== platform_transfer
);
470 // Because device_handle_ is a weak pointer it is guaranteed that the callback
471 // will be discarded if the handle has been freed.
472 Transfer
* tmp_transfer
= transfer
.get(); // base::Passed invalidates transfer
473 tmp_transfer
->task_runner_
->PostTask(
474 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::CompleteTransfer
,
475 tmp_transfer
->device_handle_
,
476 base::Passed(&transfer
)));
479 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr
<UsbContext
> context
,
480 scoped_refptr
<UsbDeviceImpl
> device
,
481 PlatformUsbDeviceHandle handle
)
485 task_runner_(base::ThreadTaskRunnerHandle::Get()),
486 weak_factory_(this) {
487 DCHECK(handle
) << "Cannot create device with NULL handle.";
490 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
491 DCHECK(thread_checker_
.CalledOnValidThread());
493 libusb_close(handle_
);
497 scoped_refptr
<UsbDevice
> UsbDeviceHandleImpl::GetDevice() const {
501 void UsbDeviceHandleImpl::Close() {
502 DCHECK(thread_checker_
.CalledOnValidThread());
504 device_
->Close(this);
507 bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value
) {
508 DCHECK(thread_checker_
.CalledOnValidThread());
513 for (Transfer
* transfer
: transfers_
) {
516 claimed_interfaces_
.clear();
518 int rv
= libusb_set_configuration(handle_
, configuration_value
);
519 if (rv
== LIBUSB_SUCCESS
) {
520 device_
->RefreshConfiguration();
521 RefreshEndpointMap();
523 VLOG(1) << "Failed to set configuration " << configuration_value
<< ": "
524 << ConvertPlatformUsbErrorToString(rv
);
526 return rv
== LIBUSB_SUCCESS
;
529 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number
) {
530 DCHECK(thread_checker_
.CalledOnValidThread());
533 if (ContainsKey(claimed_interfaces_
, interface_number
))
536 scoped_refptr
<InterfaceClaimer
> claimer
=
537 new InterfaceClaimer(this, interface_number
);
539 if (claimer
->Claim()) {
540 claimed_interfaces_
[interface_number
] = claimer
;
541 RefreshEndpointMap();
547 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number
) {
548 DCHECK(thread_checker_
.CalledOnValidThread());
551 if (!ContainsKey(claimed_interfaces_
, interface_number
))
554 // Cancel all the transfers on that interface.
555 InterfaceClaimer
* interface_claimer
=
556 claimed_interfaces_
[interface_number
].get();
557 for (Transfer
* transfer
: transfers_
) {
558 if (transfer
->claimed_interface() == interface_claimer
) {
562 claimed_interfaces_
.erase(interface_number
);
564 RefreshEndpointMap();
568 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
569 const int interface_number
,
570 const int alternate_setting
) {
571 DCHECK(thread_checker_
.CalledOnValidThread());
574 if (!ContainsKey(claimed_interfaces_
, interface_number
))
576 const int rv
= libusb_set_interface_alt_setting(
577 handle_
, interface_number
, alternate_setting
);
578 if (rv
== LIBUSB_SUCCESS
) {
579 claimed_interfaces_
[interface_number
]->set_alternate_setting(
581 RefreshEndpointMap();
583 VLOG(1) << "Failed to set interface (" << interface_number
<< ", "
585 << "): " << ConvertPlatformUsbErrorToString(rv
);
587 return rv
== LIBUSB_SUCCESS
;
590 bool UsbDeviceHandleImpl::ResetDevice() {
591 DCHECK(thread_checker_
.CalledOnValidThread());
595 const int rv
= libusb_reset_device(handle_
);
596 if (rv
!= LIBUSB_SUCCESS
) {
597 VLOG(1) << "Failed to reset device: "
598 << ConvertPlatformUsbErrorToString(rv
);
600 return rv
== LIBUSB_SUCCESS
;
603 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id
,
604 base::string16
* string
) {
605 if (!GetSupportedLanguages()) {
609 std::map
<uint8
, base::string16
>::const_iterator it
= strings_
.find(string_id
);
610 if (it
!= strings_
.end()) {
611 *string
= it
->second
;
615 for (size_t i
= 0; i
< languages_
.size(); ++i
) {
616 // Get the string using language ID.
617 uint16 language_id
= languages_
[i
];
618 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
619 base::char16 text
[128];
621 libusb_get_string_descriptor(handle_
,
624 reinterpret_cast<unsigned char*>(&text
[0]),
627 VLOG(1) << "Failed to get string descriptor " << string_id
<< " (langid "
628 << language_id
<< "): " << ConvertPlatformUsbErrorToString(size
);
630 } else if (size
< 2) {
631 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
632 << ") has no header.";
634 // The first 2 bytes of the descriptor are the total length and type tag.
635 } else if ((text
[0] & 0xff) != size
) {
636 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
637 << ") size mismatch: " << (text
[0] & 0xff) << " != " << size
;
639 } else if ((text
[0] >> 8) != LIBUSB_DT_STRING
) {
640 VLOG(1) << "String descriptor " << string_id
<< " (langid " << language_id
641 << ") is not a string descriptor.";
645 *string
= base::string16(text
+ 1, (size
- 2) / 2);
646 strings_
[string_id
] = *string
;
653 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction
,
654 TransferRequestType request_type
,
655 TransferRecipient recipient
,
659 net::IOBuffer
* buffer
,
661 unsigned int timeout
,
662 const UsbTransferCallback
& callback
) {
663 if (length
> UINT16_MAX
) {
664 LOG(ERROR
) << "Transfer too long.";
665 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
669 const size_t resized_length
= LIBUSB_CONTROL_SETUP_SIZE
+ length
;
670 scoped_refptr
<net::IOBuffer
> resized_buffer(
671 new net::IOBufferWithSize(static_cast<int>(resized_length
)));
672 if (!resized_buffer
.get()) {
673 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
676 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
, buffer
->data(),
679 scoped_ptr
<Transfer
> transfer
= Transfer::CreateControlTransfer(
680 CreateRequestType(direction
, request_type
, recipient
), request
, value
,
681 index
, static_cast<uint16
>(length
), resized_buffer
, timeout
, callback
);
683 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
687 PostOrSubmitTransfer(transfer
.Pass());
690 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction
,
691 const uint8 endpoint
,
692 net::IOBuffer
* buffer
,
694 const unsigned int timeout
,
695 const UsbTransferCallback
& callback
) {
696 if (length
> INT_MAX
) {
697 LOG(ERROR
) << "Transfer too long.";
698 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
702 scoped_ptr
<Transfer
> transfer
= Transfer::CreateBulkTransfer(
703 ConvertTransferDirection(direction
) | endpoint
, buffer
,
704 static_cast<int>(length
), timeout
, callback
);
706 PostOrSubmitTransfer(transfer
.Pass());
709 void UsbDeviceHandleImpl::InterruptTransfer(
710 UsbEndpointDirection direction
,
712 net::IOBuffer
* buffer
,
714 unsigned int timeout
,
715 const UsbTransferCallback
& callback
) {
716 if (length
> INT_MAX
) {
717 LOG(ERROR
) << "Transfer too long.";
718 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
722 scoped_ptr
<Transfer
> transfer
= Transfer::CreateInterruptTransfer(
723 ConvertTransferDirection(direction
) | endpoint
, buffer
,
724 static_cast<int>(length
), timeout
, callback
);
726 PostOrSubmitTransfer(transfer
.Pass());
729 void UsbDeviceHandleImpl::IsochronousTransfer(
730 const UsbEndpointDirection direction
,
731 const uint8 endpoint
,
732 net::IOBuffer
* buffer
,
734 const unsigned int packets
,
735 const unsigned int packet_length
,
736 const unsigned int timeout
,
737 const UsbTransferCallback
& callback
) {
738 if (length
> INT_MAX
) {
739 LOG(ERROR
) << "Transfer too long.";
740 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
744 scoped_ptr
<Transfer
> transfer
= Transfer::CreateIsochronousTransfer(
745 ConvertTransferDirection(direction
) | endpoint
, buffer
,
746 static_cast<int>(length
), packets
, packet_length
, timeout
, callback
);
748 PostOrSubmitTransfer(transfer
.Pass());
751 void UsbDeviceHandleImpl::RefreshEndpointMap() {
752 DCHECK(thread_checker_
.CalledOnValidThread());
753 endpoint_map_
.clear();
754 const UsbConfigDescriptor
* config
= device_
->GetConfiguration();
756 for (const auto& map_entry
: claimed_interfaces_
) {
757 int interface_number
= map_entry
.first
;
758 const scoped_refptr
<InterfaceClaimer
>& claimed_iface
= map_entry
.second
;
760 for (const UsbInterfaceDescriptor
& iface
: config
->interfaces
) {
761 if (iface
.interface_number
== interface_number
&&
762 iface
.alternate_setting
== claimed_iface
->alternate_setting()) {
763 for (const UsbEndpointDescriptor
& endpoint
: iface
.endpoints
) {
764 endpoint_map_
[endpoint
.address
] = interface_number
;
773 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
774 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint
) {
775 if (ContainsKey(endpoint_map_
, endpoint
))
776 return claimed_interfaces_
[endpoint_map_
[endpoint
]];
780 void UsbDeviceHandleImpl::PostOrSubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
781 if (task_runner_
->RunsTasksOnCurrentThread()) {
782 SubmitTransfer(transfer
.Pass());
784 task_runner_
->PostTask(
785 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::SubmitTransfer
, this,
786 base::Passed(&transfer
)));
790 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
791 DCHECK(thread_checker_
.CalledOnValidThread());
794 if (transfer
->Submit(weak_factory_
.GetWeakPtr())) {
795 // Transfer is now owned by libusb until its completion callback is run.
796 // This object holds a weak reference.
797 transfers_
.insert(transfer
.release());
800 transfer
->Complete(USB_TRANSFER_DISCONNECT
, 0);
804 void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr
<Transfer
> transfer
) {
805 DCHECK(ContainsKey(transfers_
, transfer
.get()))
806 << "Missing transfer completed";
807 transfers_
.erase(transfer
.get());
808 transfer
->ProcessCompletion();
811 bool UsbDeviceHandleImpl::GetSupportedLanguages() {
812 if (!languages_
.empty()) {
816 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
817 uint16 languages
[128];
818 int size
= libusb_get_string_descriptor(
822 reinterpret_cast<unsigned char*>(&languages
[0]),
825 VLOG(1) << "Failed to get list of supported languages: "
826 << ConvertPlatformUsbErrorToString(size
);
828 } else if (size
< 2) {
829 VLOG(1) << "String descriptor zero has no header.";
831 // The first 2 bytes of the descriptor are the total length and type tag.
832 } else if ((languages
[0] & 0xff) != size
) {
833 VLOG(1) << "String descriptor zero size mismatch: " << (languages
[0] & 0xff)
836 } else if ((languages
[0] >> 8) != LIBUSB_DT_STRING
) {
837 VLOG(1) << "String descriptor zero is not a string descriptor.";
841 languages_
.assign(languages
[1], languages
[(size
- 2) / 2]);
845 void UsbDeviceHandleImpl::InternalClose() {
846 DCHECK(thread_checker_
.CalledOnValidThread());
850 // Cancel all the transfers.
851 for (Transfer
* transfer
: transfers_
) {
852 // The callback will be called some time later.
856 // Attempt-release all the interfaces.
857 // It will be retained until the transfer cancellation is finished.
858 claimed_interfaces_
.clear();
860 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
865 } // namespace device