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
;
109 class UsbDeviceHandleImpl::InterfaceClaimer
110 : public base::RefCountedThreadSafe
<UsbDeviceHandleImpl::InterfaceClaimer
> {
112 InterfaceClaimer(const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
113 const int interface_number
);
117 int alternate_setting() const { return alternate_setting_
; }
118 void set_alternate_setting(const int alternate_setting
) {
119 alternate_setting_
= alternate_setting
;
123 friend class UsbDevice
;
124 friend class base::RefCountedThreadSafe
<InterfaceClaimer
>;
127 const scoped_refptr
<UsbDeviceHandleImpl
> handle_
;
128 const int interface_number_
;
129 int alternate_setting_
;
131 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer
);
134 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
135 const scoped_refptr
<UsbDeviceHandleImpl
> handle
,
136 const int interface_number
)
138 interface_number_(interface_number
),
139 alternate_setting_(0) {
142 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
143 libusb_release_interface(handle_
->handle(), interface_number_
);
146 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const {
147 const int rv
= libusb_claim_interface(handle_
->handle(), interface_number_
);
148 if (rv
!= LIBUSB_SUCCESS
) {
149 USB_LOG(EVENT
) << "Failed to claim interface " << interface_number_
<< ": "
150 << ConvertPlatformUsbErrorToString(rv
);
152 return rv
== LIBUSB_SUCCESS
;
155 // This inner class owns the underlying libusb_transfer and may outlast
156 // the UsbDeviceHandle that created it.
157 class UsbDeviceHandleImpl::Transfer
{
159 static scoped_ptr
<Transfer
> CreateControlTransfer(
160 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
166 scoped_refptr
<net::IOBuffer
> buffer
,
167 unsigned int timeout
,
168 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
169 const TransferCallback
& callback
);
170 static scoped_ptr
<Transfer
> CreateBulkTransfer(
171 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
173 scoped_refptr
<net::IOBuffer
> buffer
,
175 unsigned int timeout
,
176 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
177 const TransferCallback
& callback
);
178 static scoped_ptr
<Transfer
> CreateInterruptTransfer(
179 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
181 scoped_refptr
<net::IOBuffer
> buffer
,
183 unsigned int timeout
,
184 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
185 const TransferCallback
& callback
);
186 static scoped_ptr
<Transfer
> CreateIsochronousTransfer(
187 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
189 scoped_refptr
<net::IOBuffer
> buffer
,
191 unsigned int packets
,
192 unsigned int packet_length
,
193 unsigned int timeout
,
194 scoped_refptr
<base::TaskRunner
> task_runner
,
195 const TransferCallback
& callback
);
201 void ProcessCompletion();
202 void TransferComplete(UsbTransferStatus status
, size_t bytes_transferred
);
204 const UsbDeviceHandleImpl::InterfaceClaimer
* claimed_interface() const {
205 return claimed_interface_
.get();
208 scoped_refptr
<base::TaskRunner
> callback_task_runner() const {
209 return callback_task_runner_
;
213 Transfer(scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
214 scoped_refptr
<InterfaceClaimer
> claimed_interface
,
215 UsbTransferType transfer_type
,
216 scoped_refptr
<net::IOBuffer
> buffer
,
218 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
219 const TransferCallback
& callback
);
221 static void LIBUSB_CALL
PlatformCallback(PlatformUsbTransferHandle handle
);
223 UsbTransferType transfer_type_
;
224 scoped_refptr
<UsbDeviceHandleImpl
> device_handle_
;
225 PlatformUsbTransferHandle platform_transfer_
= nullptr;
226 scoped_refptr
<net::IOBuffer
> buffer_
;
227 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
> claimed_interface_
;
229 bool cancelled_
= false;
230 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
231 scoped_refptr
<base::TaskRunner
> callback_task_runner_
;
232 TransferCallback callback_
;
236 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
237 UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
238 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
244 scoped_refptr
<net::IOBuffer
> buffer
,
245 unsigned int timeout
,
246 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
247 const TransferCallback
& callback
) {
248 scoped_ptr
<Transfer
> transfer(new Transfer(
249 device_handle
, nullptr, USB_TRANSFER_CONTROL
, buffer
,
250 length
+ LIBUSB_CONTROL_SETUP_SIZE
, callback_task_runner
, callback
));
252 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
253 if (!transfer
->platform_transfer_
) {
254 USB_LOG(ERROR
) << "Failed to allocate control transfer.";
258 libusb_fill_control_setup(reinterpret_cast<uint8
*>(buffer
->data()), type
,
259 request
, value
, index
, length
);
260 libusb_fill_control_transfer(transfer
->platform_transfer_
,
261 device_handle
->handle_
,
262 reinterpret_cast<uint8
*>(buffer
->data()),
263 &UsbDeviceHandleImpl::Transfer::PlatformCallback
,
264 transfer
.get(), timeout
);
266 return transfer
.Pass();
270 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
271 UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
272 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
274 scoped_refptr
<net::IOBuffer
> buffer
,
276 unsigned int timeout
,
277 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
278 const TransferCallback
& callback
) {
279 scoped_ptr
<Transfer
> transfer(new Transfer(
280 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
281 USB_TRANSFER_BULK
, buffer
, length
, callback_task_runner
, callback
));
283 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
284 if (!transfer
->platform_transfer_
) {
285 USB_LOG(ERROR
) << "Failed to allocate bulk transfer.";
289 libusb_fill_bulk_transfer(
290 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
291 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
292 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
295 return transfer
.Pass();
299 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
300 UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
301 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
303 scoped_refptr
<net::IOBuffer
> buffer
,
305 unsigned int timeout
,
306 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
307 const TransferCallback
& callback
) {
308 scoped_ptr
<Transfer
> transfer(new Transfer(
309 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
310 USB_TRANSFER_INTERRUPT
, buffer
, length
, callback_task_runner
, callback
));
312 transfer
->platform_transfer_
= libusb_alloc_transfer(0);
313 if (!transfer
->platform_transfer_
) {
314 USB_LOG(ERROR
) << "Failed to allocate interrupt transfer.";
318 libusb_fill_interrupt_transfer(
319 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
320 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
321 &UsbDeviceHandleImpl::Transfer::PlatformCallback
, transfer
.get(),
324 return transfer
.Pass();
328 scoped_ptr
<UsbDeviceHandleImpl::Transfer
>
329 UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
330 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
332 scoped_refptr
<net::IOBuffer
> buffer
,
334 unsigned int packets
,
335 unsigned int packet_length
,
336 unsigned int timeout
,
337 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
338 const TransferCallback
& callback
) {
339 DCHECK(packets
<= length
&& (packets
* packet_length
) <= length
)
340 << "transfer length is too small";
342 scoped_ptr
<Transfer
> transfer(new Transfer(
343 device_handle
, device_handle
->GetClaimedInterfaceForEndpoint(endpoint
),
344 USB_TRANSFER_ISOCHRONOUS
, buffer
, length
, callback_task_runner
,
347 transfer
->platform_transfer_
= libusb_alloc_transfer(packets
);
348 if (!transfer
->platform_transfer_
) {
349 USB_LOG(ERROR
) << "Failed to allocate isochronous transfer.";
353 libusb_fill_iso_transfer(
354 transfer
->platform_transfer_
, device_handle
->handle_
, endpoint
,
355 reinterpret_cast<uint8
*>(buffer
->data()), static_cast<int>(length
),
356 packets
, &Transfer::PlatformCallback
, transfer
.get(), timeout
);
357 libusb_set_iso_packet_lengths(transfer
->platform_transfer_
, packet_length
);
359 return transfer
.Pass();
362 UsbDeviceHandleImpl::Transfer::Transfer(
363 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
,
364 scoped_refptr
<InterfaceClaimer
> claimed_interface
,
365 UsbTransferType transfer_type
,
366 scoped_refptr
<net::IOBuffer
> buffer
,
368 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
369 const TransferCallback
& callback
)
370 : transfer_type_(transfer_type
),
371 device_handle_(device_handle
),
373 claimed_interface_(claimed_interface
),
375 callback_task_runner_(callback_task_runner
),
376 callback_(callback
) {
377 task_runner_
= base::ThreadTaskRunnerHandle::Get();
380 UsbDeviceHandleImpl::Transfer::~Transfer() {
381 if (platform_transfer_
) {
382 libusb_free_transfer(platform_transfer_
);
386 void UsbDeviceHandleImpl::Transfer::Submit() {
387 const int rv
= libusb_submit_transfer(platform_transfer_
);
388 if (rv
!= LIBUSB_SUCCESS
) {
389 USB_LOG(EVENT
) << "Failed to submit transfer: "
390 << ConvertPlatformUsbErrorToString(rv
);
391 TransferComplete(USB_TRANSFER_ERROR
, 0);
395 void UsbDeviceHandleImpl::Transfer::Cancel() {
397 libusb_cancel_transfer(platform_transfer_
);
398 claimed_interface_
= nullptr;
403 void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
404 DCHECK_GE(platform_transfer_
->actual_length
, 0)
405 << "Negative actual length received";
406 size_t actual_length
=
407 static_cast<size_t>(std::max(platform_transfer_
->actual_length
, 0));
409 DCHECK(length_
>= actual_length
)
410 << "data too big for our buffer (libusb failure?)";
412 switch (transfer_type_
) {
413 case USB_TRANSFER_CONTROL
:
414 // If the transfer is a control transfer we do not expose the control
415 // setup header to the caller. This logic strips off the header if
416 // present before invoking the callback provided with the transfer.
417 if (actual_length
> 0) {
418 CHECK(length_
>= LIBUSB_CONTROL_SETUP_SIZE
)
419 << "buffer was not correctly set: too small for the control header";
421 if (length_
>= (LIBUSB_CONTROL_SETUP_SIZE
+ actual_length
)) {
422 // If the payload is zero bytes long, pad out the allocated buffer
423 // size to one byte so that an IOBuffer of that size can be allocated.
424 scoped_refptr
<net::IOBuffer
> resized_buffer
=
425 new net::IOBuffer(static_cast<int>(
426 std::max(actual_length
, static_cast<size_t>(1))));
427 memcpy(resized_buffer
->data(),
428 buffer_
->data() + LIBUSB_CONTROL_SETUP_SIZE
, actual_length
);
429 buffer_
= resized_buffer
;
434 case USB_TRANSFER_ISOCHRONOUS
:
435 // Isochronous replies might carry data in the different isoc packets even
436 // if the transfer actual_data value is zero. Furthermore, not all of the
437 // received packets might contain data, so we need to calculate how many
438 // data bytes we are effectively providing and pack the results.
439 if (actual_length
== 0) {
440 size_t packet_buffer_start
= 0;
441 for (int i
= 0; i
< platform_transfer_
->num_iso_packets
; ++i
) {
442 PlatformUsbIsoPacketDescriptor packet
=
443 &platform_transfer_
->iso_packet_desc
[i
];
444 if (packet
->actual_length
> 0) {
445 // We don't need to copy as long as all packets until now provide
446 // all the data the packet can hold.
447 if (actual_length
< packet_buffer_start
) {
448 CHECK(packet_buffer_start
+ packet
->actual_length
<= length_
);
449 memmove(buffer_
->data() + actual_length
,
450 buffer_
->data() + packet_buffer_start
,
451 packet
->actual_length
);
453 actual_length
+= packet
->actual_length
;
456 packet_buffer_start
+= packet
->length
;
461 case USB_TRANSFER_BULK
:
462 case USB_TRANSFER_INTERRUPT
:
466 NOTREACHED() << "Invalid usb transfer type";
470 TransferComplete(ConvertTransferStatus(platform_transfer_
->status
),
475 void LIBUSB_CALL
UsbDeviceHandleImpl::Transfer::PlatformCallback(
476 PlatformUsbTransferHandle platform_transfer
) {
478 reinterpret_cast<Transfer
*>(platform_transfer
->user_data
);
479 DCHECK(transfer
->platform_transfer_
== platform_transfer
);
480 transfer
->ProcessCompletion();
483 void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status
,
484 size_t bytes_transferred
) {
485 task_runner_
->PostTask(
487 base::Bind(&UsbDeviceHandleImpl::TransferComplete
, device_handle_
,
488 base::Unretained(this),
489 base::Bind(callback_
, status
, buffer_
, bytes_transferred
)));
492 scoped_refptr
<UsbDevice
> UsbDeviceHandleImpl::GetDevice() const {
496 void UsbDeviceHandleImpl::Close() {
497 DCHECK(thread_checker_
.CalledOnValidThread());
499 device_
->Close(this);
502 void UsbDeviceHandleImpl::SetConfiguration(int configuration_value
,
503 const ResultCallback
& callback
) {
504 DCHECK(thread_checker_
.CalledOnValidThread());
510 for (Transfer
* transfer
: transfers_
) {
513 claimed_interfaces_
.clear();
515 blocking_task_runner_
->PostTask(
517 base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread
, this,
518 handle_
, configuration_value
, callback
));
521 void UsbDeviceHandleImpl::ClaimInterface(int interface_number
,
522 const ResultCallback
& callback
) {
523 DCHECK(thread_checker_
.CalledOnValidThread());
528 if (ContainsKey(claimed_interfaces_
, interface_number
)) {
533 blocking_task_runner_
->PostTask(
535 base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread
, this,
536 handle_
, interface_number
, callback
));
539 bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number
) {
540 DCHECK(thread_checker_
.CalledOnValidThread());
543 if (!ContainsKey(claimed_interfaces_
, interface_number
))
546 // Cancel all the transfers on that interface.
547 InterfaceClaimer
* interface_claimer
=
548 claimed_interfaces_
[interface_number
].get();
549 for (Transfer
* transfer
: transfers_
) {
550 if (transfer
->claimed_interface() == interface_claimer
) {
554 claimed_interfaces_
.erase(interface_number
);
556 RefreshEndpointMap();
560 void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
561 int interface_number
,
562 int alternate_setting
,
563 const ResultCallback
& callback
) {
564 DCHECK(thread_checker_
.CalledOnValidThread());
565 if (!device_
|| !ContainsKey(claimed_interfaces_
, interface_number
)) {
570 blocking_task_runner_
->PostTask(
573 &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread
,
574 this, handle_
, interface_number
, alternate_setting
, callback
));
577 void UsbDeviceHandleImpl::ResetDevice(const ResultCallback
& callback
) {
578 DCHECK(thread_checker_
.CalledOnValidThread());
584 blocking_task_runner_
->PostTask(
585 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread
,
586 this, handle_
, callback
));
589 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction
,
590 TransferRequestType request_type
,
591 TransferRecipient recipient
,
595 scoped_refptr
<net::IOBuffer
> buffer
,
597 unsigned int timeout
,
598 const TransferCallback
& callback
) {
599 if (task_runner_
->BelongsToCurrentThread()) {
600 ControlTransferInternal(direction
, request_type
, recipient
, request
, value
,
601 index
, buffer
, length
, timeout
, task_runner_
,
604 task_runner_
->PostTask(
605 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal
,
606 this, direction
, request_type
, recipient
, request
,
607 value
, index
, buffer
, length
, timeout
,
608 base::ThreadTaskRunnerHandle::Get(), callback
));
612 void UsbDeviceHandleImpl::BulkTransfer(UsbEndpointDirection direction
,
614 scoped_refptr
<net::IOBuffer
> buffer
,
616 unsigned int timeout
,
617 const TransferCallback
& callback
) {
618 if (task_runner_
->BelongsToCurrentThread()) {
619 BulkTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
620 task_runner_
, callback
);
622 task_runner_
->PostTask(
623 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::BulkTransferInternal
, this,
624 direction
, endpoint
, buffer
, length
, timeout
,
625 base::ThreadTaskRunnerHandle::Get(), callback
));
629 void UsbDeviceHandleImpl::InterruptTransfer(UsbEndpointDirection direction
,
631 scoped_refptr
<net::IOBuffer
> buffer
,
633 unsigned int timeout
,
634 const TransferCallback
& callback
) {
635 if (task_runner_
->BelongsToCurrentThread()) {
636 InterruptTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
637 task_runner_
, callback
);
639 task_runner_
->PostTask(
641 base::Bind(&UsbDeviceHandleImpl::InterruptTransferInternal
, this,
642 direction
, endpoint
, 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 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
669 scoped_refptr
<UsbContext
> context
,
670 scoped_refptr
<UsbDeviceImpl
> device
,
671 PlatformUsbDeviceHandle handle
,
672 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
)
676 task_runner_(base::ThreadTaskRunnerHandle::Get()),
677 blocking_task_runner_(blocking_task_runner
) {
678 DCHECK(handle
) << "Cannot create device with NULL handle.";
681 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
682 DCHECK(thread_checker_
.CalledOnValidThread());
684 libusb_close(handle_
);
688 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
689 PlatformUsbDeviceHandle handle
,
690 int configuration_value
,
691 const ResultCallback
& callback
) {
692 int rv
= libusb_set_configuration(handle_
, configuration_value
);
693 if (rv
!= LIBUSB_SUCCESS
) {
694 USB_LOG(EVENT
) << "Failed to set configuration " << configuration_value
695 << ": " << ConvertPlatformUsbErrorToString(rv
);
697 task_runner_
->PostTask(
698 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete
,
699 this, rv
== LIBUSB_SUCCESS
, callback
));
702 void UsbDeviceHandleImpl::SetConfigurationComplete(
704 const ResultCallback
& callback
) {
706 device_
->RefreshConfiguration();
707 RefreshEndpointMap();
709 callback
.Run(success
);
712 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
713 PlatformUsbDeviceHandle handle
,
714 int interface_number
,
715 const ResultCallback
& callback
) {
716 int rv
= libusb_claim_interface(handle
, interface_number
);
717 if (rv
!= LIBUSB_SUCCESS
) {
718 VLOG(1) << "Failed to claim interface: "
719 << ConvertPlatformUsbErrorToString(rv
);
721 task_runner_
->PostTask(
722 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete
, this,
723 interface_number
, rv
== LIBUSB_SUCCESS
, callback
));
726 void UsbDeviceHandleImpl::ClaimInterfaceComplete(
727 int interface_number
,
729 const ResultCallback
& callback
) {
731 claimed_interfaces_
[interface_number
] =
732 new InterfaceClaimer(this, interface_number
);
733 RefreshEndpointMap();
735 callback
.Run(success
);
738 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
739 PlatformUsbDeviceHandle handle
,
740 int interface_number
,
741 int alternate_setting
,
742 const ResultCallback
& callback
) {
743 int rv
= libusb_set_interface_alt_setting(handle
, interface_number
,
745 if (rv
!= LIBUSB_SUCCESS
) {
746 USB_LOG(EVENT
) << "Failed to set interface " << interface_number
747 << " to alternate setting " << alternate_setting
<< ": "
748 << ConvertPlatformUsbErrorToString(rv
);
750 task_runner_
->PostTask(
752 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete
,
753 this, interface_number
, alternate_setting
,
754 rv
== LIBUSB_SUCCESS
, callback
));
757 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
758 int interface_number
,
759 int alternate_setting
,
761 const ResultCallback
& callback
) {
763 claimed_interfaces_
[interface_number
]->set_alternate_setting(
765 RefreshEndpointMap();
767 callback
.Run(success
);
770 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
771 PlatformUsbDeviceHandle handle
,
772 const ResultCallback
& callback
) {
773 int rv
= libusb_reset_device(handle
);
774 if (rv
!= LIBUSB_SUCCESS
) {
775 USB_LOG(EVENT
) << "Failed to reset device: "
776 << ConvertPlatformUsbErrorToString(rv
);
778 task_runner_
->PostTask(
779 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete
, this,
780 rv
== LIBUSB_SUCCESS
, callback
));
783 void UsbDeviceHandleImpl::ResetDeviceComplete(bool success
,
784 const ResultCallback
& callback
) {
785 callback
.Run(success
);
788 void UsbDeviceHandleImpl::RefreshEndpointMap() {
789 DCHECK(thread_checker_
.CalledOnValidThread());
790 endpoint_map_
.clear();
791 const UsbConfigDescriptor
* config
= device_
->GetConfiguration();
793 for (const auto& map_entry
: claimed_interfaces_
) {
794 int interface_number
= map_entry
.first
;
795 const scoped_refptr
<InterfaceClaimer
>& claimed_iface
= map_entry
.second
;
797 for (const UsbInterfaceDescriptor
& iface
: config
->interfaces
) {
798 if (iface
.interface_number
== interface_number
&&
799 iface
.alternate_setting
== claimed_iface
->alternate_setting()) {
800 for (const UsbEndpointDescriptor
& endpoint
: iface
.endpoints
) {
801 endpoint_map_
[endpoint
.address
] = interface_number
;
810 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
811 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint
) {
812 if (ContainsKey(endpoint_map_
, endpoint
))
813 return claimed_interfaces_
[endpoint_map_
[endpoint
]];
817 void UsbDeviceHandleImpl::ControlTransferInternal(
818 UsbEndpointDirection direction
,
819 TransferRequestType request_type
,
820 TransferRecipient recipient
,
824 scoped_refptr
<net::IOBuffer
> buffer
,
826 unsigned int timeout
,
827 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
828 const TransferCallback
& callback
) {
829 DCHECK(thread_checker_
.CalledOnValidThread());
832 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
836 if (length
> UINT16_MAX
) {
837 USB_LOG(USER
) << "Transfer too long.";
838 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
842 const size_t resized_length
= LIBUSB_CONTROL_SETUP_SIZE
+ length
;
843 scoped_refptr
<net::IOBuffer
> resized_buffer(
844 new net::IOBufferWithSize(static_cast<int>(resized_length
)));
845 if (!resized_buffer
.get()) {
846 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
849 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
, buffer
->data(),
852 scoped_ptr
<Transfer
> transfer
= Transfer::CreateControlTransfer(
853 this, CreateRequestType(direction
, request_type
, recipient
), request
,
854 value
, index
, static_cast<uint16
>(length
), resized_buffer
, timeout
,
855 callback_task_runner
, callback
);
857 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
861 SubmitTransfer(transfer
.Pass());
864 void UsbDeviceHandleImpl::BulkTransferInternal(
865 const UsbEndpointDirection direction
,
866 const uint8 endpoint
,
867 scoped_refptr
<net::IOBuffer
> buffer
,
869 const unsigned int timeout
,
870 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
871 const TransferCallback
& callback
) {
872 DCHECK(thread_checker_
.CalledOnValidThread());
875 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
879 if (length
> INT_MAX
) {
880 USB_LOG(USER
) << "Transfer too long.";
881 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
885 scoped_ptr
<Transfer
> transfer
= Transfer::CreateBulkTransfer(
886 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
887 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
889 SubmitTransfer(transfer
.Pass());
892 void UsbDeviceHandleImpl::InterruptTransferInternal(
893 UsbEndpointDirection direction
,
895 scoped_refptr
<net::IOBuffer
> buffer
,
897 unsigned int timeout
,
898 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
899 const TransferCallback
& callback
) {
900 DCHECK(thread_checker_
.CalledOnValidThread());
903 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
907 if (length
> INT_MAX
) {
908 USB_LOG(USER
) << "Transfer too long.";
909 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
913 scoped_ptr
<Transfer
> transfer
= Transfer::CreateInterruptTransfer(
914 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
915 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
917 SubmitTransfer(transfer
.Pass());
920 void UsbDeviceHandleImpl::IsochronousTransferInternal(
921 const UsbEndpointDirection direction
,
923 scoped_refptr
<net::IOBuffer
> buffer
,
925 unsigned int packets
,
926 unsigned int packet_length
,
927 unsigned int timeout
,
928 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
929 const TransferCallback
& callback
) {
930 DCHECK(thread_checker_
.CalledOnValidThread());
933 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
937 if (length
> INT_MAX
) {
938 USB_LOG(USER
) << "Transfer too long.";
939 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
943 scoped_ptr
<Transfer
> transfer
= Transfer::CreateIsochronousTransfer(
944 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
945 static_cast<int>(length
), packets
, packet_length
, timeout
,
946 callback_task_runner
, callback
);
948 SubmitTransfer(transfer
.Pass());
951 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
952 DCHECK(thread_checker_
.CalledOnValidThread());
954 // Transfer is owned by libusb until its completion callback is run. This
955 // object holds a weak reference.
956 transfers_
.insert(transfer
.get());
957 blocking_task_runner_
->PostTask(
959 base::Bind(&Transfer::Submit
, base::Unretained(transfer
.release())));
962 void UsbDeviceHandleImpl::TransferComplete(Transfer
* transfer
,
963 const base::Closure
& callback
) {
964 DCHECK(thread_checker_
.CalledOnValidThread());
965 DCHECK(ContainsKey(transfers_
, transfer
)) << "Missing transfer completed";
966 transfers_
.erase(transfer
);
968 if (transfer
->callback_task_runner()->RunsTasksOnCurrentThread()) {
971 transfer
->callback_task_runner()->PostTask(FROM_HERE
, callback
);
974 // libusb_free_transfer races with libusb_submit_transfer and only work-
975 // around is to make sure to call them on the same thread.
976 blocking_task_runner_
->DeleteSoon(FROM_HERE
, transfer
);
979 void UsbDeviceHandleImpl::InternalClose() {
980 DCHECK(thread_checker_
.CalledOnValidThread());
984 // Cancel all the transfers.
985 for (Transfer
* transfer
: transfers_
) {
986 // The callback will be called some time later.
990 // Attempt-release all the interfaces.
991 // It will be retained until the transfer cancellation is finished.
992 claimed_interfaces_
.clear();
994 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
999 } // namespace device