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 "components/device_event_log/device_event_log.h"
18 #include "device/usb/usb_context.h"
19 #include "device/usb/usb_descriptors.h"
20 #include "device/usb/usb_device_impl.h"
21 #include "device/usb/usb_error.h"
22 #include "device/usb/usb_service.h"
23 #include "third_party/libusb/src/libusb/libusb.h"
27 typedef libusb_device
* PlatformUsbDevice
;
29 void HandleTransferCompletion(PlatformUsbTransferHandle transfer
);
33 static uint8
ConvertTransferDirection(const UsbEndpointDirection direction
) {
35 case USB_DIRECTION_INBOUND
:
36 return LIBUSB_ENDPOINT_IN
;
37 case USB_DIRECTION_OUTBOUND
:
38 return LIBUSB_ENDPOINT_OUT
;
41 return LIBUSB_ENDPOINT_IN
;
45 static uint8
CreateRequestType(
46 const UsbEndpointDirection direction
,
47 const UsbDeviceHandle::TransferRequestType request_type
,
48 const UsbDeviceHandle::TransferRecipient recipient
) {
49 uint8 result
= ConvertTransferDirection(direction
);
51 switch (request_type
) {
52 case UsbDeviceHandle::STANDARD
:
53 result
|= LIBUSB_REQUEST_TYPE_STANDARD
;
55 case UsbDeviceHandle::CLASS
:
56 result
|= LIBUSB_REQUEST_TYPE_CLASS
;
58 case UsbDeviceHandle::VENDOR
:
59 result
|= LIBUSB_REQUEST_TYPE_VENDOR
;
61 case UsbDeviceHandle::RESERVED
:
62 result
|= LIBUSB_REQUEST_TYPE_RESERVED
;
67 case UsbDeviceHandle::DEVICE
:
68 result
|= LIBUSB_RECIPIENT_DEVICE
;
70 case UsbDeviceHandle::INTERFACE
:
71 result
|= LIBUSB_RECIPIENT_INTERFACE
;
73 case UsbDeviceHandle::ENDPOINT
:
74 result
|= LIBUSB_RECIPIENT_ENDPOINT
;
76 case UsbDeviceHandle::OTHER
:
77 result
|= LIBUSB_RECIPIENT_OTHER
;
84 static UsbTransferStatus
ConvertTransferStatus(
85 const libusb_transfer_status status
) {
87 case LIBUSB_TRANSFER_COMPLETED
:
88 return USB_TRANSFER_COMPLETED
;
89 case LIBUSB_TRANSFER_ERROR
:
90 return USB_TRANSFER_ERROR
;
91 case LIBUSB_TRANSFER_TIMED_OUT
:
92 return USB_TRANSFER_TIMEOUT
;
93 case LIBUSB_TRANSFER_STALL
:
94 return USB_TRANSFER_STALLED
;
95 case LIBUSB_TRANSFER_NO_DEVICE
:
96 return USB_TRANSFER_DISCONNECT
;
97 case LIBUSB_TRANSFER_OVERFLOW
:
98 return USB_TRANSFER_OVERFLOW
;
99 case LIBUSB_TRANSFER_CANCELLED
:
100 return USB_TRANSFER_CANCELLED
;
103 return USB_TRANSFER_ERROR
;
107 static void RunTransferCallback(
108 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
109 const UsbDeviceHandle::TransferCallback
& callback
,
110 UsbTransferStatus status
,
111 scoped_refptr
<net::IOBuffer
> buffer
,
113 if (callback_task_runner
->RunsTasksOnCurrentThread()) {
114 callback
.Run(status
, buffer
, result
);
116 callback_task_runner
->PostTask(
117 FROM_HERE
, base::Bind(callback
, status
, buffer
, result
));
123 class UsbDeviceHandleImpl::InterfaceClaimer
124 : public base::RefCountedThreadSafe
<UsbDeviceHandleImpl::InterfaceClaimer
> {
126 InterfaceClaimer(const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
127 const int interface_number
);
131 int alternate_setting() const { return alternate_setting_
; }
132 void set_alternate_setting(const int alternate_setting
) {
133 alternate_setting_
= alternate_setting
;
137 friend class UsbDevice
;
138 friend class base::RefCountedThreadSafe
<InterfaceClaimer
>;
141 const scoped_refptr
<UsbDeviceHandleImpl
> handle_
;
142 const int interface_number_
;
143 int alternate_setting_
;
145 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer
);
148 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
149 const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
150 const int interface_number
)
152 interface_number_(interface_number
),
153 alternate_setting_(0) {
156 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
157 libusb_release_interface(handle_
->handle(), interface_number_
);
160 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const {
161 const int rv
= libusb_claim_interface(handle_
->handle(), interface_number_
);
162 if (rv
!= LIBUSB_SUCCESS
) {
163 USB_LOG(EVENT
) << "Failed to claim interface " << interface_number_
<< ": "
164 << ConvertPlatformUsbErrorToString(rv
);
166 return rv
== LIBUSB_SUCCESS
;
169 // This inner class owns the underlying libusb_transfer and may outlast
170 // the UsbDeviceHandle that created it.
171 class UsbDeviceHandleImpl::Transfer
{
173 static scoped_ptr
<Transfer
> CreateControlTransfer(
174 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
180 scoped_refptr
<net::IOBuffer
> buffer
,
181 unsigned int timeout
,
182 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
183 const TransferCallback
& callback
);
184 static scoped_ptr
<Transfer
> CreateBulkTransfer(
185 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
187 scoped_refptr
<net::IOBuffer
> buffer
,
189 unsigned int timeout
,
190 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
191 const TransferCallback
& callback
);
192 static scoped_ptr
<Transfer
> CreateInterruptTransfer(
193 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
195 scoped_refptr
<net::IOBuffer
> buffer
,
197 unsigned int timeout
,
198 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
199 const TransferCallback
& callback
);
200 static scoped_ptr
<Transfer
> CreateIsochronousTransfer(
201 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
203 scoped_refptr
<net::IOBuffer
> buffer
,
205 unsigned int packets
,
206 unsigned int packet_length
,
207 unsigned int timeout
,
208 scoped_refptr
<base::TaskRunner
> task_runner
,
209 const TransferCallback
& callback
);
215 void ProcessCompletion();
216 void TransferComplete(UsbTransferStatus status
, size_t bytes_transferred
);
218 const UsbDeviceHandleImpl::InterfaceClaimer
* claimed_interface() const {
219 return claimed_interface_
.get();
222 scoped_refptr
<base::TaskRunner
> callback_task_runner() const {
223 return callback_task_runner_
;
227 Transfer(scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
228 scoped_refptr
<InterfaceClaimer
> claimed_interface
,
229 UsbTransferType transfer_type
,
230 scoped_refptr
<net::IOBuffer
> buffer
,
232 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
233 const TransferCallback
& callback
);
235 static void LIBUSB_CALL
PlatformCallback(PlatformUsbTransferHandle handle
);
237 UsbTransferType transfer_type_
;
238 scoped_refptr
<UsbDeviceHandleImpl
> device_handle_
;
239 PlatformUsbTransferHandle platform_transfer_
= nullptr;
240 scoped_refptr
<net::IOBuffer
> buffer_
;
241 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
> claimed_interface_
;
243 bool cancelled_
= false;
244 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
245 scoped_refptr
<base::TaskRunner
> callback_task_runner_
;
246 TransferCallback callback_
;
250 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
251 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
252 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
258 scoped_refptr
<net::IOBuffer
> buffer
,
259 unsigned int timeout
,
260 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
261 const TransferCallback
& callback
) {
262 scoped_ptr
<Transfer
> transfer(new Transfer(
263 device_handle
, nullptr, USB_TRANSFER_CONTROL
, buffer
,
264 length
+ LIBUSB_CONTROL_SETUP_SIZE
, callback_task_runner
, callback
));
266 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
267 if (!transfer
->platform_transfer_
) {
268 USB_LOG(ERROR
) << "Failed to allocate control transfer.";
272 libusb_fill_control_setup(reinterpret_cast<uint8
*>(buffer
->data()), type
,
273 request
, value
, index
, length
);
274 libusb_fill_control_transfer(transfer
->platform_transfer_
,
275 device_handle
->handle_
,
276 reinterpret_cast<uint8
*>(buffer
->data()),
277 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
278 transfer
.get(), timeout
);
280 return transfer
.Pass();
284 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
285 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
286 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
288 scoped_refptr
<net::IOBuffer
> buffer
,
290 unsigned int timeout
,
291 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
292 const TransferCallback
& callback
) {
293 scoped_ptr
<Transfer
> transfer(new Transfer(
294 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
295 USB_TRANSFER_BULK
, buffer
, length
, callback_task_runner
, callback
));
297 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
298 if (!transfer
->platform_transfer_
) {
299 USB_LOG(ERROR
) << "Failed to allocate bulk transfer.";
303 libusb_fill_bulk_transfer(
304 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
305 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
306 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
309 return transfer
.Pass();
313 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
314 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
315 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
317 scoped_refptr
<net::IOBuffer
> buffer
,
319 unsigned int timeout
,
320 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
321 const TransferCallback
& callback
) {
322 scoped_ptr
<Transfer
> transfer(new Transfer(
323 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
324 USB_TRANSFER_INTERRUPT
, buffer
, length
, callback_task_runner
, callback
));
326 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
327 if (!transfer
->platform_transfer_
) {
328 USB_LOG(ERROR
) << "Failed to allocate interrupt transfer.";
332 libusb_fill_interrupt_transfer(
333 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
334 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
335 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
338 return transfer
.Pass();
342 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
343 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
344 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
346 scoped_refptr
<net::IOBuffer
> buffer
,
348 unsigned int packets
,
349 unsigned int packet_length
,
350 unsigned int timeout
,
351 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
352 const TransferCallback
& callback
) {
353 DCHECK(packets
<= length
&& (packets
* packet_length
) <= length
)
354 << "transfer length is too small";
356 scoped_ptr
<Transfer
> transfer(new Transfer(
357 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
358 USB_TRANSFER_ISOCHRONOUS
, buffer
, length
, callback_task_runner
,
361 transfer
->platform_transfer_
= libusb_alloc_transfer(packets
);
362 if (!transfer
->platform_transfer_
) {
363 USB_LOG(ERROR
) << "Failed to allocate isochronous transfer.";
367 libusb_fill_iso_transfer(
368 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
369 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
370 packets
, &Transfer::PlatformCallback
, transfer
.get(), timeout
);
371 libusb_set_iso_packet_lengths(transfer
->platform_transfer_
, packet_length
);
373 return transfer
.Pass();
376 UsbDeviceHandleImpl::Transfer::Transfer(
377 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
378 scoped_refptr
<InterfaceClaimer
> claimed_interface
,
379 UsbTransferType transfer_type
,
380 scoped_refptr
<net::IOBuffer
> buffer
,
382 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
383 const TransferCallback
& callback
)
384 : transfer_type_(transfer_type
),
385 device_handle_(device_handle
),
387 claimed_interface_(claimed_interface
),
389 callback_task_runner_(callback_task_runner
),
390 callback_(callback
) {
391 task_runner_
= base::ThreadTaskRunnerHandle::Get();
394 UsbDeviceHandleImpl::Transfer::~Transfer() {
395 if (platform_transfer_
) {
396 libusb_free_transfer(platform_transfer_
);
400 void UsbDeviceHandleImpl::Transfer::Submit() {
401 const int rv
= libusb_submit_transfer(platform_transfer_
);
402 if (rv
!= LIBUSB_SUCCESS
) {
403 USB_LOG(EVENT
) << "Failed to submit transfer: "
404 << ConvertPlatformUsbErrorToString(rv
);
405 TransferComplete(USB_TRANSFER_ERROR
, 0);
409 void UsbDeviceHandleImpl::Transfer::Cancel() {
411 libusb_cancel_transfer(platform_transfer_
);
412 claimed_interface_
= nullptr;
417 void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
418 DCHECK_GE(platform_transfer_
->actual_length
, 0)
419 << "Negative actual length received";
420 size_t actual_length
=
421 static_cast<size_t>(std::max(platform_transfer_
->actual_length
, 0));
423 DCHECK(length_
>= actual_length
)
424 << "data too big for our buffer (libusb failure?)";
426 switch (transfer_type_
) {
427 case USB_TRANSFER_CONTROL
:
428 // If the transfer is a control transfer we do not expose the control
429 // setup header to the caller. This logic strips off the header if
430 // present before invoking the callback provided with the transfer.
431 if (actual_length
> 0) {
432 CHECK(length_
>= LIBUSB_CONTROL_SETUP_SIZE
)
433 << "buffer was not correctly set: too small for the control header";
435 if (length_
>= (LIBUSB_CONTROL_SETUP_SIZE
+ actual_length
)) {
436 // If the payload is zero bytes long, pad out the allocated buffer
437 // size to one byte so that an IOBuffer of that size can be allocated.
438 scoped_refptr
<net::IOBuffer
> resized_buffer
=
439 new net::IOBuffer(static_cast<int>(
440 std::max(actual_length
, static_cast<size_t>(1))));
441 memcpy(resized_buffer
->data(),
442 buffer_
->data() + LIBUSB_CONTROL_SETUP_SIZE
, actual_length
);
443 buffer_
= resized_buffer
;
448 case USB_TRANSFER_ISOCHRONOUS
:
449 // Isochronous replies might carry data in the different isoc packets even
450 // if the transfer actual_data value is zero. Furthermore, not all of the
451 // received packets might contain data, so we need to calculate how many
452 // data bytes we are effectively providing and pack the results.
453 if (actual_length
== 0) {
454 size_t packet_buffer_start
= 0;
455 for (int i
= 0; i
< platform_transfer_
->num_iso_packets
; ++i
) {
456 PlatformUsbIsoPacketDescriptor packet
=
457 &platform_transfer_
->iso_packet_desc
[i
];
458 if (packet
->actual_length
> 0) {
459 // We don't need to copy as long as all packets until now provide
460 // all the data the packet can hold.
461 if (actual_length
< packet_buffer_start
) {
462 CHECK(packet_buffer_start
+ packet
->actual_length
<= length_
);
463 memmove(buffer_
->data() + actual_length
,
464 buffer_
->data() + packet_buffer_start
,
465 packet
->actual_length
);
467 actual_length
+= packet
->actual_length
;
470 packet_buffer_start
+= packet
->length
;
475 case USB_TRANSFER_BULK
:
476 case USB_TRANSFER_INTERRUPT
:
480 NOTREACHED() << "Invalid usb transfer type";
484 TransferComplete(ConvertTransferStatus(platform_transfer_
->status
),
489 void LIBUSB_CALL
UsbDeviceHandleImpl::Transfer::PlatformCallback(
490 PlatformUsbTransferHandle platform_transfer
) {
492 reinterpret_cast<Transfer
*>(platform_transfer
->user_data
);
493 DCHECK(transfer
->platform_transfer_
== platform_transfer
);
494 transfer
->ProcessCompletion();
497 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status
,
498 size_t bytes_transferred
) {
499 task_runner_
->PostTask(
501 base::Bind(&UsbDeviceHandleImpl::TransferComplete
, device_handle_
,
502 base::Unretained(this),
503 base::Bind(callback_
, status
, buffer_
, bytes_transferred
)));
506 scoped_refptr
<UsbDevice
> UsbDeviceHandleImpl::GetDevice() const {
510 void UsbDeviceHandleImpl::Close() {
511 DCHECK(thread_checker_
.CalledOnValidThread());
513 device_
->Close(this);
516 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value
,
517 const ResultCallback
& callback
) {
518 DCHECK(thread_checker_
.CalledOnValidThread());
524 for (Transfer
* transfer
: transfers_
) {
527 claimed_interfaces_
.clear();
529 blocking_task_runner_
->PostTask(
531 base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread
, this,
532 configuration_value
, callback
));
535 void UsbDeviceHandleImpl::ClaimInterface(int interface_number
,
536 const ResultCallback
& callback
) {
537 DCHECK(thread_checker_
.CalledOnValidThread());
542 if (ContainsKey(claimed_interfaces_
, interface_number
)) {
547 blocking_task_runner_
->PostTask(
549 base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread
, this,
550 interface_number
, callback
));
553 bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number
) {
554 DCHECK(thread_checker_
.CalledOnValidThread());
557 if (!ContainsKey(claimed_interfaces_
, interface_number
))
560 // Cancel all the transfers on that interface.
561 InterfaceClaimer
* interface_claimer
=
562 claimed_interfaces_
[interface_number
].get();
563 for (Transfer
* transfer
: transfers_
) {
564 if (transfer
->claimed_interface() == interface_claimer
) {
568 claimed_interfaces_
.erase(interface_number
);
570 RefreshEndpointMap();
574 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
575 int interface_number
,
576 int alternate_setting
,
577 const ResultCallback
& callback
) {
578 DCHECK(thread_checker_
.CalledOnValidThread());
579 if (!device_
|| !ContainsKey(claimed_interfaces_
, interface_number
)) {
584 blocking_task_runner_
->PostTask(
587 &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread
,
588 this, interface_number
, alternate_setting
, callback
));
591 void UsbDeviceHandleImpl::ResetDevice(const ResultCallback
& callback
) {
592 DCHECK(thread_checker_
.CalledOnValidThread());
598 blocking_task_runner_
->PostTask(
599 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread
,
603 void UsbDeviceHandleImpl::ClearHalt(uint8 endpoint
,
604 const ResultCallback
& callback
) {
605 DCHECK(thread_checker_
.CalledOnValidThread());
611 InterfaceClaimer
* interface_claimer
=
612 GetClaimedInterfaceForEndpoint(endpoint
).get();
613 for (Transfer
* transfer
: transfers_
) {
614 if (transfer
->claimed_interface() == interface_claimer
) {
619 blocking_task_runner_
->PostTask(
620 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ClearHaltOnBlockingThread
,
621 this, endpoint
, callback
));
624 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction
,
625 TransferRequestType request_type
,
626 TransferRecipient recipient
,
630 scoped_refptr
<net::IOBuffer
> buffer
,
632 unsigned int timeout
,
633 const TransferCallback
& callback
) {
634 if (task_runner_
->BelongsToCurrentThread()) {
635 ControlTransferInternal(direction
, request_type
, recipient
, request
, value
,
636 index
, buffer
, length
, timeout
, task_runner_
,
639 task_runner_
->PostTask(
640 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal
,
641 this, direction
, request_type
, recipient
, request
,
642 value
, index
, buffer
, length
, timeout
,
643 base::ThreadTaskRunnerHandle::Get(), callback
));
647 void UsbDeviceHandleImpl::IsochronousTransfer(
648 UsbEndpointDirection direction
,
650 scoped_refptr
<net::IOBuffer
> buffer
,
652 unsigned int packets
,
653 unsigned int packet_length
,
654 unsigned int timeout
,
655 const TransferCallback
& callback
) {
656 if (task_runner_
->BelongsToCurrentThread()) {
657 IsochronousTransferInternal(direction
, endpoint
, buffer
, length
, packets
,
658 packet_length
, timeout
, task_runner_
, callback
);
660 task_runner_
->PostTask(
662 base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal
, this,
663 direction
, endpoint
, buffer
, length
, packets
, packet_length
,
664 timeout
, base::ThreadTaskRunnerHandle::Get(), callback
));
668 void UsbDeviceHandleImpl::GenericTransfer(UsbEndpointDirection direction
,
670 scoped_refptr
<net::IOBuffer
> buffer
,
672 unsigned int timeout
,
673 const TransferCallback
& callback
) {
674 if (task_runner_
->BelongsToCurrentThread()) {
675 GenericTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
676 task_runner_
, callback
);
678 task_runner_
->PostTask(
680 base::Bind(&UsbDeviceHandleImpl::GenericTransferInternal
, this,
681 direction
, endpoint
, buffer
, length
, timeout
,
682 base::ThreadTaskRunnerHandle::Get(), callback
));
686 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
687 scoped_refptr
<UsbContext
> context
,
688 scoped_refptr
<UsbDeviceImpl
> device
,
689 PlatformUsbDeviceHandle handle
,
690 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
)
694 task_runner_(base::ThreadTaskRunnerHandle::Get()),
695 blocking_task_runner_(blocking_task_runner
) {
696 DCHECK(handle
) << "Cannot create device with NULL handle.";
699 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
700 // This class is RefCountedThreadSafe and so the destructor may be called on
702 libusb_close(handle_
);
705 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
706 int configuration_value
,
707 const ResultCallback
& callback
) {
708 int rv
= libusb_set_configuration(handle_
, configuration_value
);
709 if (rv
!= LIBUSB_SUCCESS
) {
710 USB_LOG(EVENT
) << "Failed to set configuration " << configuration_value
711 << ": " << ConvertPlatformUsbErrorToString(rv
);
713 task_runner_
->PostTask(
714 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete
,
715 this, rv
== LIBUSB_SUCCESS
, callback
));
718 void UsbDeviceHandleImpl::SetConfigurationComplete(
720 const ResultCallback
& callback
) {
722 device_
->RefreshActiveConfiguration();
723 RefreshEndpointMap();
725 callback
.Run(success
);
728 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
729 int interface_number
,
730 const ResultCallback
& callback
) {
731 int rv
= libusb_claim_interface(handle_
, interface_number
);
732 if (rv
!= LIBUSB_SUCCESS
) {
733 VLOG(1) << "Failed to claim interface: "
734 << ConvertPlatformUsbErrorToString(rv
);
736 task_runner_
->PostTask(
737 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete
, this,
738 interface_number
, rv
== LIBUSB_SUCCESS
, callback
));
741 void UsbDeviceHandleImpl::ClaimInterfaceComplete(
742 int interface_number
,
744 const ResultCallback
& callback
) {
746 claimed_interfaces_
[interface_number
] =
747 new InterfaceClaimer(this, interface_number
);
748 RefreshEndpointMap();
750 callback
.Run(success
);
753 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
754 int interface_number
,
755 int alternate_setting
,
756 const ResultCallback
& callback
) {
757 int rv
= libusb_set_interface_alt_setting(handle_
, interface_number
,
759 if (rv
!= LIBUSB_SUCCESS
) {
760 USB_LOG(EVENT
) << "Failed to set interface " << interface_number
761 << " to alternate setting " << alternate_setting
<< ": "
762 << ConvertPlatformUsbErrorToString(rv
);
764 task_runner_
->PostTask(
766 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete
,
767 this, interface_number
, alternate_setting
,
768 rv
== LIBUSB_SUCCESS
, callback
));
771 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
772 int interface_number
,
773 int alternate_setting
,
775 const ResultCallback
& callback
) {
777 claimed_interfaces_
[interface_number
]->set_alternate_setting(
779 RefreshEndpointMap();
781 callback
.Run(success
);
784 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
785 const ResultCallback
& callback
) {
786 int rv
= libusb_reset_device(handle_
);
787 if (rv
!= LIBUSB_SUCCESS
) {
788 USB_LOG(EVENT
) << "Failed to reset device: "
789 << ConvertPlatformUsbErrorToString(rv
);
791 task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, rv
== LIBUSB_SUCCESS
));
794 void UsbDeviceHandleImpl::ClearHaltOnBlockingThread(
796 const ResultCallback
& callback
) {
797 int rv
= libusb_clear_halt(handle_
, endpoint
);
798 if (rv
!= LIBUSB_SUCCESS
) {
799 USB_LOG(EVENT
) << "Failed to clear halt: "
800 << ConvertPlatformUsbErrorToString(rv
);
802 task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, rv
== LIBUSB_SUCCESS
));
805 void UsbDeviceHandleImpl::RefreshEndpointMap() {
806 DCHECK(thread_checker_
.CalledOnValidThread());
807 endpoint_map_
.clear();
808 const UsbConfigDescriptor
* config
= device_
->GetActiveConfiguration();
810 for (const auto& map_entry
: claimed_interfaces_
) {
811 int interface_number
= map_entry
.first
;
812 const scoped_refptr
<InterfaceClaimer
>& claimed_iface
= map_entry
.second
;
814 for (const UsbInterfaceDescriptor
& iface
: config
->interfaces
) {
815 if (iface
.interface_number
== interface_number
&&
816 iface
.alternate_setting
== claimed_iface
->alternate_setting()) {
817 for (const UsbEndpointDescriptor
& endpoint
: iface
.endpoints
) {
818 endpoint_map_
[endpoint
.address
] = {interface_number
,
819 endpoint
.transfer_type
};
828 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
829 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8 endpoint
) {
830 if (ContainsKey(endpoint_map_
, endpoint
))
831 return claimed_interfaces_
[endpoint_map_
[endpoint
].interface_number
];
835 void UsbDeviceHandleImpl::ControlTransferInternal(
836 UsbEndpointDirection direction
,
837 TransferRequestType request_type
,
838 TransferRecipient recipient
,
842 scoped_refptr
<net::IOBuffer
> buffer
,
844 unsigned int timeout
,
845 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
846 const TransferCallback
& callback
) {
847 DCHECK(thread_checker_
.CalledOnValidThread());
850 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_DISCONNECT
,
855 if (length
> UINT16_MAX
) {
856 USB_LOG(USER
) << "Transfer too long.";
857 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
862 const size_t resized_length
= LIBUSB_CONTROL_SETUP_SIZE
+ length
;
863 scoped_refptr
<net::IOBuffer
> resized_buffer(
864 new net::IOBufferWithSize(static_cast<int>(resized_length
)));
865 if (!resized_buffer
.get()) {
866 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
870 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
, buffer
->data(),
873 scoped_ptr
<Transfer
> transfer
= Transfer::CreateControlTransfer(
874 this, CreateRequestType(direction
, request_type
, recipient
), request
,
875 value
, index
, static_cast<uint16
>(length
), resized_buffer
, timeout
,
876 callback_task_runner
, callback
);
878 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
883 SubmitTransfer(transfer
.Pass());
886 void UsbDeviceHandleImpl::BulkTransferInternal(
887 const UsbEndpointDirection direction
,
888 const uint8 endpoint
,
889 scoped_refptr
<net::IOBuffer
> buffer
,
891 const unsigned int timeout
,
892 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
893 const TransferCallback
& callback
) {
894 DCHECK(thread_checker_
.CalledOnValidThread());
897 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_DISCONNECT
,
902 if (length
> INT_MAX
) {
903 USB_LOG(USER
) << "Transfer too long.";
904 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
909 scoped_ptr
<Transfer
> transfer
= Transfer::CreateBulkTransfer(
910 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
911 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
913 SubmitTransfer(transfer
.Pass());
916 void UsbDeviceHandleImpl::InterruptTransferInternal(
917 UsbEndpointDirection direction
,
919 scoped_refptr
<net::IOBuffer
> buffer
,
921 unsigned int timeout
,
922 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
923 const TransferCallback
& callback
) {
924 DCHECK(thread_checker_
.CalledOnValidThread());
927 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_DISCONNECT
,
932 if (length
> INT_MAX
) {
933 USB_LOG(USER
) << "Transfer too long.";
934 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
939 scoped_ptr
<Transfer
> transfer
= Transfer::CreateInterruptTransfer(
940 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
941 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
943 SubmitTransfer(transfer
.Pass());
946 void UsbDeviceHandleImpl::IsochronousTransferInternal(
947 const UsbEndpointDirection direction
,
949 scoped_refptr
<net::IOBuffer
> buffer
,
951 unsigned int packets
,
952 unsigned int packet_length
,
953 unsigned int timeout
,
954 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
955 const TransferCallback
& callback
) {
956 DCHECK(thread_checker_
.CalledOnValidThread());
959 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_DISCONNECT
,
964 if (length
> INT_MAX
) {
965 USB_LOG(USER
) << "Transfer too long.";
966 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
971 scoped_ptr
<Transfer
> transfer
= Transfer::CreateIsochronousTransfer(
972 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
973 static_cast<int>(length
), packets
, packet_length
, timeout
,
974 callback_task_runner
, callback
);
976 SubmitTransfer(transfer
.Pass());
979 void UsbDeviceHandleImpl::GenericTransferInternal(
980 UsbEndpointDirection direction
,
982 scoped_refptr
<net::IOBuffer
> buffer
,
984 unsigned int timeout
,
985 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
986 const TransferCallback
& callback
) {
987 if (!ContainsKey(endpoint_map_
, endpoint
)) {
989 << "Failed to do generic transfer since endpoint not in endpoint_map_.";
990 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
995 UsbTransferType transfer_type
= endpoint_map_
[endpoint
].transfer_type
;
996 if (transfer_type
== USB_TRANSFER_BULK
) {
997 BulkTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
998 callback_task_runner
, callback
);
999 } else if (transfer_type
== USB_TRANSFER_INTERRUPT
) {
1000 InterruptTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
1001 callback_task_runner
, callback
);
1004 << "Failed to do generic transfer since transfer_type is not "
1005 "bulk or interrupt.";
1006 RunTransferCallback(callback_task_runner
, callback
, USB_TRANSFER_ERROR
,
1011 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
1012 DCHECK(thread_checker_
.CalledOnValidThread());
1014 // Transfer is owned by libusb until its completion callback is run. This
1015 // object holds a weak reference.
1016 transfers_
.insert(transfer
.get());
1017 blocking_task_runner_
->PostTask(
1019 base::Bind(&Transfer::Submit
, base::Unretained(transfer
.release())));
1022 void UsbDeviceHandleImpl::TransferComplete(Transfer
* transfer
,
1023 const base::Closure
& callback
) {
1024 DCHECK(thread_checker_
.CalledOnValidThread());
1025 DCHECK(ContainsKey(transfers_
, transfer
)) << "Missing transfer completed";
1026 transfers_
.erase(transfer
);
1028 if (transfer
->callback_task_runner()->RunsTasksOnCurrentThread()) {
1031 transfer
->callback_task_runner()->PostTask(FROM_HERE
, callback
);
1034 // libusb_free_transfer races with libusb_submit_transfer and only work-
1035 // around is to make sure to call them on the same thread.
1036 blocking_task_runner_
->DeleteSoon(FROM_HERE
, transfer
);
1039 void UsbDeviceHandleImpl::InternalClose() {
1040 DCHECK(thread_checker_
.CalledOnValidThread());
1044 // Cancel all the transfers.
1045 for (Transfer
* transfer
: transfers_
) {
1046 // The callback will be called some time later.
1050 // Attempt-release all the interfaces.
1051 // It will be retained until the transfer cancellation is finished.
1052 claimed_interfaces_
.clear();
1054 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
1059 } // namespace device