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 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 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, 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
,
589 void UsbDeviceHandleImpl::ClearHalt(uint8 endpoint
,
590 const ResultCallback
& callback
) {
591 DCHECK(thread_checker_
.CalledOnValidThread());
597 InterfaceClaimer
* interface_claimer
=
598 GetClaimedInterfaceForEndpoint(endpoint
).get();
599 for (Transfer
* transfer
: transfers_
) {
600 if (transfer
->claimed_interface() == interface_claimer
) {
605 blocking_task_runner_
->PostTask(
606 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ClearHaltOnBlockingThread
,
607 this, endpoint
, callback
));
610 void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction
,
611 TransferRequestType request_type
,
612 TransferRecipient recipient
,
616 scoped_refptr
<net::IOBuffer
> buffer
,
618 unsigned int timeout
,
619 const TransferCallback
& callback
) {
620 if (task_runner_
->BelongsToCurrentThread()) {
621 ControlTransferInternal(direction
, request_type
, recipient
, request
, value
,
622 index
, buffer
, length
, timeout
, task_runner_
,
625 task_runner_
->PostTask(
626 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal
,
627 this, direction
, request_type
, recipient
, request
,
628 value
, index
, buffer
, length
, timeout
,
629 base::ThreadTaskRunnerHandle::Get(), callback
));
633 void UsbDeviceHandleImpl::BulkTransfer(UsbEndpointDirection direction
,
635 scoped_refptr
<net::IOBuffer
> buffer
,
637 unsigned int timeout
,
638 const TransferCallback
& callback
) {
639 if (task_runner_
->BelongsToCurrentThread()) {
640 BulkTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
641 task_runner_
, callback
);
643 task_runner_
->PostTask(
644 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::BulkTransferInternal
, this,
645 direction
, endpoint
, buffer
, length
, timeout
,
646 base::ThreadTaskRunnerHandle::Get(), callback
));
650 void UsbDeviceHandleImpl::InterruptTransfer(UsbEndpointDirection direction
,
652 scoped_refptr
<net::IOBuffer
> buffer
,
654 unsigned int timeout
,
655 const TransferCallback
& callback
) {
656 if (task_runner_
->BelongsToCurrentThread()) {
657 InterruptTransferInternal(direction
, endpoint
, buffer
, length
, timeout
,
658 task_runner_
, callback
);
660 task_runner_
->PostTask(
662 base::Bind(&UsbDeviceHandleImpl::InterruptTransferInternal
, this,
663 direction
, endpoint
, buffer
, length
, timeout
,
664 base::ThreadTaskRunnerHandle::Get(), callback
));
668 void UsbDeviceHandleImpl::IsochronousTransfer(
669 UsbEndpointDirection direction
,
671 scoped_refptr
<net::IOBuffer
> buffer
,
673 unsigned int packets
,
674 unsigned int packet_length
,
675 unsigned int timeout
,
676 const TransferCallback
& callback
) {
677 if (task_runner_
->BelongsToCurrentThread()) {
678 IsochronousTransferInternal(direction
, endpoint
, buffer
, length
, packets
,
679 packet_length
, timeout
, task_runner_
, callback
);
681 task_runner_
->PostTask(
683 base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal
, this,
684 direction
, endpoint
, buffer
, length
, packets
, packet_length
,
685 timeout
, base::ThreadTaskRunnerHandle::Get(), callback
));
689 UsbDeviceHandleImpl::UsbDeviceHandleImpl(
690 scoped_refptr
<UsbContext
> context
,
691 scoped_refptr
<UsbDeviceImpl
> device
,
692 PlatformUsbDeviceHandle handle
,
693 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
)
697 task_runner_(base::ThreadTaskRunnerHandle::Get()),
698 blocking_task_runner_(blocking_task_runner
) {
699 DCHECK(handle
) << "Cannot create device with NULL handle.";
702 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
703 // This class is RefCountedThreadSafe and so the destructor may be called on
705 libusb_close(handle_
);
708 void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
709 int configuration_value
,
710 const ResultCallback
& callback
) {
711 int rv
= libusb_set_configuration(handle_
, configuration_value
);
712 if (rv
!= LIBUSB_SUCCESS
) {
713 USB_LOG(EVENT
) << "Failed to set configuration " << configuration_value
714 << ": " << ConvertPlatformUsbErrorToString(rv
);
716 task_runner_
->PostTask(
717 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete
,
718 this, rv
== LIBUSB_SUCCESS
, callback
));
721 void UsbDeviceHandleImpl::SetConfigurationComplete(
723 const ResultCallback
& callback
) {
725 device_
->RefreshActiveConfiguration();
726 RefreshEndpointMap();
728 callback
.Run(success
);
731 void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
732 int interface_number
,
733 const ResultCallback
& callback
) {
734 int rv
= libusb_claim_interface(handle_
, interface_number
);
735 if (rv
!= LIBUSB_SUCCESS
) {
736 VLOG(1) << "Failed to claim interface: "
737 << ConvertPlatformUsbErrorToString(rv
);
739 task_runner_
->PostTask(
740 FROM_HERE
, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete
, this,
741 interface_number
, rv
== LIBUSB_SUCCESS
, callback
));
744 void UsbDeviceHandleImpl::ClaimInterfaceComplete(
745 int interface_number
,
747 const ResultCallback
& callback
) {
749 claimed_interfaces_
[interface_number
] =
750 new InterfaceClaimer(this, interface_number
);
751 RefreshEndpointMap();
753 callback
.Run(success
);
756 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
757 int interface_number
,
758 int alternate_setting
,
759 const ResultCallback
& callback
) {
760 int rv
= libusb_set_interface_alt_setting(handle_
, interface_number
,
762 if (rv
!= LIBUSB_SUCCESS
) {
763 USB_LOG(EVENT
) << "Failed to set interface " << interface_number
764 << " to alternate setting " << alternate_setting
<< ": "
765 << ConvertPlatformUsbErrorToString(rv
);
767 task_runner_
->PostTask(
769 base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete
,
770 this, interface_number
, alternate_setting
,
771 rv
== LIBUSB_SUCCESS
, callback
));
774 void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
775 int interface_number
,
776 int alternate_setting
,
778 const ResultCallback
& callback
) {
780 claimed_interfaces_
[interface_number
]->set_alternate_setting(
782 RefreshEndpointMap();
784 callback
.Run(success
);
787 void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
788 const ResultCallback
& callback
) {
789 int rv
= libusb_reset_device(handle_
);
790 if (rv
!= LIBUSB_SUCCESS
) {
791 USB_LOG(EVENT
) << "Failed to reset device: "
792 << ConvertPlatformUsbErrorToString(rv
);
794 task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, rv
== LIBUSB_SUCCESS
));
797 void UsbDeviceHandleImpl::ClearHaltOnBlockingThread(
799 const ResultCallback
& callback
) {
800 int rv
= libusb_clear_halt(handle_
, endpoint
);
801 if (rv
!= LIBUSB_SUCCESS
) {
802 USB_LOG(EVENT
) << "Failed to clear halt: "
803 << ConvertPlatformUsbErrorToString(rv
);
805 task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, rv
== LIBUSB_SUCCESS
));
808 void UsbDeviceHandleImpl::RefreshEndpointMap() {
809 DCHECK(thread_checker_
.CalledOnValidThread());
810 endpoint_map_
.clear();
811 const UsbConfigDescriptor
* config
= device_
->GetActiveConfiguration();
813 for (const auto& map_entry
: claimed_interfaces_
) {
814 int interface_number
= map_entry
.first
;
815 const scoped_refptr
<InterfaceClaimer
>& claimed_iface
= map_entry
.second
;
817 for (const UsbInterfaceDescriptor
& iface
: config
->interfaces
) {
818 if (iface
.interface_number
== interface_number
&&
819 iface
.alternate_setting
== claimed_iface
->alternate_setting()) {
820 for (const UsbEndpointDescriptor
& endpoint
: iface
.endpoints
) {
821 endpoint_map_
[endpoint
.address
] = interface_number
;
830 scoped_refptr
<UsbDeviceHandleImpl::InterfaceClaimer
>
831 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8 endpoint
) {
832 if (ContainsKey(endpoint_map_
, endpoint
))
833 return claimed_interfaces_
[endpoint_map_
[endpoint
]];
837 void UsbDeviceHandleImpl::ControlTransferInternal(
838 UsbEndpointDirection direction
,
839 TransferRequestType request_type
,
840 TransferRecipient recipient
,
844 scoped_refptr
<net::IOBuffer
> buffer
,
846 unsigned int timeout
,
847 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
848 const TransferCallback
& callback
) {
849 DCHECK(thread_checker_
.CalledOnValidThread());
852 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
856 if (length
> UINT16_MAX
) {
857 USB_LOG(USER
) << "Transfer too long.";
858 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
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 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
869 memcpy(resized_buffer
->data() + LIBUSB_CONTROL_SETUP_SIZE
, buffer
->data(),
872 scoped_ptr
<Transfer
> transfer
= Transfer::CreateControlTransfer(
873 this, CreateRequestType(direction
, request_type
, recipient
), request
,
874 value
, index
, static_cast<uint16
>(length
), resized_buffer
, timeout
,
875 callback_task_runner
, callback
);
877 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
881 SubmitTransfer(transfer
.Pass());
884 void UsbDeviceHandleImpl::BulkTransferInternal(
885 const UsbEndpointDirection direction
,
886 const uint8 endpoint
,
887 scoped_refptr
<net::IOBuffer
> buffer
,
889 const unsigned int timeout
,
890 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
891 const TransferCallback
& callback
) {
892 DCHECK(thread_checker_
.CalledOnValidThread());
895 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
899 if (length
> INT_MAX
) {
900 USB_LOG(USER
) << "Transfer too long.";
901 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
905 scoped_ptr
<Transfer
> transfer
= Transfer::CreateBulkTransfer(
906 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
907 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
909 SubmitTransfer(transfer
.Pass());
912 void UsbDeviceHandleImpl::InterruptTransferInternal(
913 UsbEndpointDirection direction
,
915 scoped_refptr
<net::IOBuffer
> buffer
,
917 unsigned int timeout
,
918 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
919 const TransferCallback
& callback
) {
920 DCHECK(thread_checker_
.CalledOnValidThread());
923 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
927 if (length
> INT_MAX
) {
928 USB_LOG(USER
) << "Transfer too long.";
929 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
933 scoped_ptr
<Transfer
> transfer
= Transfer::CreateInterruptTransfer(
934 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
935 static_cast<int>(length
), timeout
, callback_task_runner
, callback
);
937 SubmitTransfer(transfer
.Pass());
940 void UsbDeviceHandleImpl::IsochronousTransferInternal(
941 const UsbEndpointDirection direction
,
943 scoped_refptr
<net::IOBuffer
> buffer
,
945 unsigned int packets
,
946 unsigned int packet_length
,
947 unsigned int timeout
,
948 scoped_refptr
<base::TaskRunner
> callback_task_runner
,
949 const TransferCallback
& callback
) {
950 DCHECK(thread_checker_
.CalledOnValidThread());
953 callback
.Run(USB_TRANSFER_DISCONNECT
, buffer
, 0);
957 if (length
> INT_MAX
) {
958 USB_LOG(USER
) << "Transfer too long.";
959 callback
.Run(USB_TRANSFER_ERROR
, buffer
, 0);
963 scoped_ptr
<Transfer
> transfer
= Transfer::CreateIsochronousTransfer(
964 this, ConvertTransferDirection(direction
) | endpoint
, buffer
,
965 static_cast<int>(length
), packets
, packet_length
, timeout
,
966 callback_task_runner
, callback
);
968 SubmitTransfer(transfer
.Pass());
971 void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr
<Transfer
> transfer
) {
972 DCHECK(thread_checker_
.CalledOnValidThread());
974 // Transfer is owned by libusb until its completion callback is run. This
975 // object holds a weak reference.
976 transfers_
.insert(transfer
.get());
977 blocking_task_runner_
->PostTask(
979 base::Bind(&Transfer::Submit
, base::Unretained(transfer
.release())));
982 void UsbDeviceHandleImpl::TransferComplete(Transfer
* transfer
,
983 const base::Closure
& callback
) {
984 DCHECK(thread_checker_
.CalledOnValidThread());
985 DCHECK(ContainsKey(transfers_
, transfer
)) << "Missing transfer completed";
986 transfers_
.erase(transfer
);
988 if (transfer
->callback_task_runner()->RunsTasksOnCurrentThread()) {
991 transfer
->callback_task_runner()->PostTask(FROM_HERE
, callback
);
994 // libusb_free_transfer races with libusb_submit_transfer and only work-
995 // around is to make sure to call them on the same thread.
996 blocking_task_runner_
->DeleteSoon(FROM_HERE
, transfer
);
999 void UsbDeviceHandleImpl::InternalClose() {
1000 DCHECK(thread_checker_
.CalledOnValidThread());
1004 // Cancel all the transfers.
1005 for (Transfer
* transfer
: transfers_
) {
1006 // The callback will be called some time later.
1010 // Attempt-release all the interfaces.
1011 // It will be retained until the transfer cancellation is finished.
1012 claimed_interfaces_
.clear();
1014 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
1019 } // namespace device