| Index: device/usb/usb_device_handle_impl.cc
|
| diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
|
| index fc14e82c30723f560ebb1a50ab29691d715c1c80..921af4f2225f37fc8bda9fdbaf38e5004281745a 100644
|
| --- a/device/usb/usb_device_handle_impl.cc
|
| +++ b/device/usb/usb_device_handle_impl.cc
|
| @@ -157,6 +157,7 @@ bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const {
|
| class UsbDeviceHandleImpl::Transfer {
|
| public:
|
| static scoped_ptr<Transfer> CreateControlTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 type,
|
| uint8 request,
|
| uint16 value,
|
| @@ -164,62 +165,77 @@ class UsbDeviceHandleImpl::Transfer {
|
| uint16 length,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback);
|
| static scoped_ptr<Transfer> CreateBulkTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| int length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback);
|
| static scoped_ptr<Transfer> CreateInterruptTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| int length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback);
|
| static scoped_ptr<Transfer> CreateIsochronousTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| unsigned int packets,
|
| unsigned int packet_length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> task_runner,
|
| + const TransferCallback& callback);
|
|
|
| ~Transfer();
|
|
|
| - bool Submit(base::WeakPtr<UsbDeviceHandleImpl> device_handle);
|
| + void Submit();
|
| void Cancel();
|
| void ProcessCompletion();
|
| - void Complete(UsbTransferStatus status, size_t bytes_transferred);
|
| + void TransferComplete(UsbTransferStatus status, size_t bytes_transferred);
|
|
|
| const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const {
|
| return claimed_interface_.get();
|
| }
|
|
|
| + scoped_refptr<base::TaskRunner> callback_task_runner() const {
|
| + return callback_task_runner_;
|
| + }
|
| +
|
| private:
|
| - Transfer(UsbTransferType transfer_type,
|
| + Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| + scoped_refptr<InterfaceClaimer> claimed_interface,
|
| + UsbTransferType transfer_type,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| - const UsbTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback);
|
|
|
| static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);
|
|
|
| UsbTransferType transfer_type_;
|
| - base::WeakPtr<UsbDeviceHandleImpl> device_handle_;
|
| - PlatformUsbTransferHandle platform_transfer_;
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle_;
|
| + PlatformUsbTransferHandle platform_transfer_ = nullptr;
|
| scoped_refptr<net::IOBuffer> buffer_;
|
| scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| size_t length_;
|
| - bool cancelled_;
|
| - UsbTransferCallback callback_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_;
|
| + bool cancelled_ = false;
|
| + scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
| + scoped_refptr<base::TaskRunner> callback_task_runner_;
|
| + TransferCallback callback_;
|
| };
|
|
|
| // static
|
| scoped_ptr<UsbDeviceHandleImpl::Transfer>
|
| UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 type,
|
| uint8 request,
|
| uint16 value,
|
| @@ -227,10 +243,11 @@ UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
|
| uint16 length,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| - scoped_ptr<Transfer> transfer(new Transfer(USB_TRANSFER_CONTROL, buffer,
|
| - length + LIBUSB_CONTROL_SETUP_SIZE,
|
| - callback));
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + scoped_ptr<Transfer> transfer(new Transfer(
|
| + device_handle, nullptr, USB_TRANSFER_CONTROL, buffer,
|
| + length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback));
|
|
|
| transfer->platform_transfer_ = libusb_alloc_transfer(0);
|
| if (!transfer->platform_transfer_) {
|
| @@ -241,7 +258,7 @@ UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
|
| libusb_fill_control_setup(reinterpret_cast<uint8*>(buffer->data()), type,
|
| request, value, index, length);
|
| libusb_fill_control_transfer(transfer->platform_transfer_,
|
| - nullptr, /* filled in by Submit() */
|
| + device_handle->handle_,
|
| reinterpret_cast<uint8*>(buffer->data()),
|
| &UsbDeviceHandleImpl::Transfer::PlatformCallback,
|
| transfer.get(), timeout);
|
| @@ -252,13 +269,16 @@ UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
|
| // static
|
| scoped_ptr<UsbDeviceHandleImpl::Transfer>
|
| UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| int length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| - scoped_ptr<Transfer> transfer(
|
| - new Transfer(USB_TRANSFER_BULK, buffer, length, callback));
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + scoped_ptr<Transfer> transfer(new Transfer(
|
| + device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
|
| + USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback));
|
|
|
| transfer->platform_transfer_ = libusb_alloc_transfer(0);
|
| if (!transfer->platform_transfer_) {
|
| @@ -266,12 +286,11 @@ UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
|
| return nullptr;
|
| }
|
|
|
| - libusb_fill_bulk_transfer(transfer->platform_transfer_,
|
| - nullptr, /* filled in by Submit() */
|
| - endpoint, reinterpret_cast<uint8*>(buffer->data()),
|
| - static_cast<int>(length),
|
| - &UsbDeviceHandleImpl::Transfer::PlatformCallback,
|
| - transfer.get(), timeout);
|
| + libusb_fill_bulk_transfer(
|
| + transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| + reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
|
| + &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
|
| + timeout);
|
|
|
| return transfer.Pass();
|
| }
|
| @@ -279,13 +298,16 @@ UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
|
| // static
|
| scoped_ptr<UsbDeviceHandleImpl::Transfer>
|
| UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| int length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| - scoped_ptr<Transfer> transfer(
|
| - new Transfer(USB_TRANSFER_INTERRUPT, buffer, length, callback));
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + scoped_ptr<Transfer> transfer(new Transfer(
|
| + device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
|
| + USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback));
|
|
|
| transfer->platform_transfer_ = libusb_alloc_transfer(0);
|
| if (!transfer->platform_transfer_) {
|
| @@ -294,9 +316,8 @@ UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
|
| }
|
|
|
| libusb_fill_interrupt_transfer(
|
| - transfer->platform_transfer_, nullptr, /* filled in by Submit() */
|
| - endpoint, reinterpret_cast<uint8*>(buffer->data()),
|
| - static_cast<int>(length),
|
| + transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| + reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
|
| &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
|
| timeout);
|
|
|
| @@ -306,18 +327,22 @@ UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
|
| // static
|
| scoped_ptr<UsbDeviceHandleImpl::Transfer>
|
| UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| uint8 endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| unsigned int packets,
|
| unsigned int packet_length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| DCHECK(packets <= length && (packets * packet_length) <= length)
|
| << "transfer length is too small";
|
|
|
| - scoped_ptr<Transfer> transfer(
|
| - new Transfer(USB_TRANSFER_ISOCHRONOUS, buffer, length, callback));
|
| + scoped_ptr<Transfer> transfer(new Transfer(
|
| + device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
|
| + USB_TRANSFER_ISOCHRONOUS, buffer, length, callback_task_runner,
|
| + callback));
|
|
|
| transfer->platform_transfer_ = libusb_alloc_transfer(packets);
|
| if (!transfer->platform_transfer_) {
|
| @@ -326,27 +351,30 @@ UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
|
| }
|
|
|
| libusb_fill_iso_transfer(
|
| - transfer->platform_transfer_, nullptr, /* filled in by Submit() */
|
| - endpoint, reinterpret_cast<uint8*>(buffer->data()),
|
| - static_cast<int>(length), packets, &Transfer::PlatformCallback,
|
| - transfer.get(), timeout);
|
| + transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| + reinterpret_cast<uint8*>(buffer->data()), static_cast<int>(length),
|
| + packets, &Transfer::PlatformCallback, transfer.get(), timeout);
|
| libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length);
|
|
|
| return transfer.Pass();
|
| }
|
|
|
| -UsbDeviceHandleImpl::Transfer::Transfer(UsbTransferType transfer_type,
|
| - scoped_refptr<net::IOBuffer> buffer,
|
| - size_t length,
|
| - const UsbTransferCallback& callback)
|
| +UsbDeviceHandleImpl::Transfer::Transfer(
|
| + scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| + scoped_refptr<InterfaceClaimer> claimed_interface,
|
| + UsbTransferType transfer_type,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback)
|
| : transfer_type_(transfer_type),
|
| + device_handle_(device_handle),
|
| buffer_(buffer),
|
| + claimed_interface_(claimed_interface),
|
| length_(length),
|
| - cancelled_(false),
|
| + callback_task_runner_(callback_task_runner),
|
| callback_(callback) {
|
| - // Remember the thread from which this transfer was created so that |callback|
|
| - // can be dispatched there.
|
| - callback_task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| + task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| }
|
|
|
| UsbDeviceHandleImpl::Transfer::~Transfer() {
|
| @@ -355,26 +383,12 @@ UsbDeviceHandleImpl::Transfer::~Transfer() {
|
| }
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::Transfer::Submit(
|
| - base::WeakPtr<UsbDeviceHandleImpl> device_handle) {
|
| - device_handle_ = device_handle;
|
| - // Remember the thread from which this transfer was submitted so that it can
|
| - // be marked complete there.
|
| - task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| - // GetClaimedInterfaceForEndpoint may return nullptr. libusb_submit_transfer
|
| - // will fail if it requires an interface we didn't claim.
|
| - claimed_interface_ = device_handle->GetClaimedInterfaceForEndpoint(
|
| - platform_transfer_->endpoint);
|
| - platform_transfer_->dev_handle = device_handle_->handle_;
|
| -
|
| +void UsbDeviceHandleImpl::Transfer::Submit() {
|
| const int rv = libusb_submit_transfer(platform_transfer_);
|
| - if (rv == LIBUSB_SUCCESS) {
|
| - return true;
|
| - } else {
|
| + if (rv != LIBUSB_SUCCESS) {
|
| USB_LOG(EVENT) << "Failed to submit transfer: "
|
| << ConvertPlatformUsbErrorToString(rv);
|
| - Complete(USB_TRANSFER_ERROR, 0);
|
| - return false;
|
| + TransferComplete(USB_TRANSFER_ERROR, 0);
|
| }
|
| }
|
|
|
| @@ -453,51 +467,26 @@ void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
|
| break;
|
| }
|
|
|
| - Complete(ConvertTransferStatus(platform_transfer_->status), actual_length);
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status,
|
| - size_t bytes_transferred) {
|
| - if (callback_task_runner_->RunsTasksOnCurrentThread()) {
|
| - callback_.Run(status, buffer_, bytes_transferred);
|
| - } else {
|
| - callback_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(callback_, status, buffer_, bytes_transferred));
|
| - }
|
| + TransferComplete(ConvertTransferStatus(platform_transfer_->status),
|
| + actual_length);
|
| }
|
|
|
| /* static */
|
| void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
|
| PlatformUsbTransferHandle platform_transfer) {
|
| - scoped_ptr<Transfer> transfer(
|
| - reinterpret_cast<Transfer*>(platform_transfer->user_data));
|
| + Transfer* transfer =
|
| + reinterpret_cast<Transfer*>(platform_transfer->user_data);
|
| DCHECK(transfer->platform_transfer_ == platform_transfer);
|
| -
|
| - // Because device_handle_ is a weak pointer it is guaranteed that the callback
|
| - // will be discarded if the handle has been freed.
|
| - Transfer* tmp_transfer = transfer.get(); // base::Passed invalidates transfer
|
| - tmp_transfer->task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&UsbDeviceHandleImpl::CompleteTransfer,
|
| - tmp_transfer->device_handle_,
|
| - base::Passed(&transfer)));
|
| -}
|
| -
|
| -UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context,
|
| - scoped_refptr<UsbDeviceImpl> device,
|
| - PlatformUsbDeviceHandle handle)
|
| - : device_(device),
|
| - handle_(handle),
|
| - context_(context),
|
| - task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| - weak_factory_(this) {
|
| - DCHECK(handle) << "Cannot create device with NULL handle.";
|
| + transfer->ProcessCompletion();
|
| }
|
|
|
| -UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - libusb_close(handle_);
|
| - handle_ = NULL;
|
| +void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
|
| + size_t bytes_transferred) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::TransferComplete, device_handle_,
|
| + base::Owned(this),
|
| + base::Bind(callback_, status, buffer_, bytes_transferred)));
|
| }
|
|
|
| scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
|
| @@ -510,10 +499,12 @@ void UsbDeviceHandleImpl::Close() {
|
| device_->Close(this);
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) {
|
| +void UsbDeviceHandleImpl::SetConfiguration(int configuration_value,
|
| + const ResultCallback& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| if (!device_) {
|
| - return false;
|
| + callback.Run(false);
|
| + return;
|
| }
|
|
|
| for (Transfer* transfer : transfers_) {
|
| @@ -521,36 +512,31 @@ bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) {
|
| }
|
| claimed_interfaces_.clear();
|
|
|
| - int rv = libusb_set_configuration(handle_, configuration_value);
|
| - if (rv == LIBUSB_SUCCESS) {
|
| - device_->RefreshConfiguration();
|
| - RefreshEndpointMap();
|
| - } else {
|
| - USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
|
| - << ": " << ConvertPlatformUsbErrorToString(rv);
|
| - }
|
| - return rv == LIBUSB_SUCCESS;
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread, this,
|
| + handle_, configuration_value, callback));
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) {
|
| +void UsbDeviceHandleImpl::ClaimInterface(int interface_number,
|
| + const ResultCallback& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!device_)
|
| - return false;
|
| - if (ContainsKey(claimed_interfaces_, interface_number))
|
| - return true;
|
| -
|
| - scoped_refptr<InterfaceClaimer> claimer =
|
| - new InterfaceClaimer(this, interface_number);
|
| -
|
| - if (claimer->Claim()) {
|
| - claimed_interfaces_[interface_number] = claimer;
|
| - RefreshEndpointMap();
|
| - return true;
|
| + if (!device_) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| + if (ContainsKey(claimed_interfaces_, interface_number)) {
|
| + callback.Run(true);
|
| + return;
|
| }
|
| - return false;
|
| +
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread, this,
|
| + handle_, interface_number, callback));
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) {
|
| +bool UsbDeviceHandleImpl::ReleaseInterface(int interface_number) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| if (!device_)
|
| return false;
|
| @@ -571,103 +557,282 @@ bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) {
|
| return true;
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
|
| - const int interface_number,
|
| - const int alternate_setting) {
|
| +void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
|
| + int interface_number,
|
| + int alternate_setting,
|
| + const ResultCallback& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!device_)
|
| - return false;
|
| - if (!ContainsKey(claimed_interfaces_, interface_number))
|
| - return false;
|
| - const int rv = libusb_set_interface_alt_setting(
|
| - handle_, interface_number, alternate_setting);
|
| - if (rv == LIBUSB_SUCCESS) {
|
| - claimed_interfaces_[interface_number]->set_alternate_setting(
|
| - alternate_setting);
|
| - RefreshEndpointMap();
|
| + if (!device_ || !ContainsKey(claimed_interfaces_, interface_number)) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(
|
| + &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread,
|
| + this, handle_, interface_number, alternate_setting, callback));
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::ResetDevice(const ResultCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!device_) {
|
| + callback.Run(false);
|
| + return;
|
| + }
|
| +
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread,
|
| + this, handle_, callback));
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
|
| + TransferRequestType request_type,
|
| + TransferRecipient recipient,
|
| + uint8 request,
|
| + uint16 value,
|
| + uint16 index,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int timeout,
|
| + const TransferCallback& callback) {
|
| + if (task_runner_->BelongsToCurrentThread()) {
|
| + ControlTransferInternal(direction, request_type, recipient, request, value,
|
| + index, buffer, length, timeout, task_runner_,
|
| + callback);
|
| + } else {
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal,
|
| + this, direction, request_type, recipient, request,
|
| + value, index, buffer, length, timeout,
|
| + base::ThreadTaskRunnerHandle::Get(), callback));
|
| + }
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::BulkTransfer(UsbEndpointDirection direction,
|
| + uint8 endpoint,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int timeout,
|
| + const TransferCallback& callback) {
|
| + if (task_runner_->BelongsToCurrentThread()) {
|
| + BulkTransferInternal(direction, endpoint, buffer, length, timeout,
|
| + task_runner_, callback);
|
| } else {
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::BulkTransferInternal, this,
|
| + direction, endpoint, buffer, length, timeout,
|
| + base::ThreadTaskRunnerHandle::Get(), callback));
|
| + }
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::InterruptTransfer(UsbEndpointDirection direction,
|
| + uint8 endpoint,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int timeout,
|
| + const TransferCallback& callback) {
|
| + if (task_runner_->BelongsToCurrentThread()) {
|
| + InterruptTransferInternal(direction, endpoint, buffer, length, timeout,
|
| + task_runner_, callback);
|
| + } else {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::InterruptTransferInternal, this,
|
| + direction, endpoint, buffer, length, timeout,
|
| + base::ThreadTaskRunnerHandle::Get(), callback));
|
| + }
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::IsochronousTransfer(
|
| + UsbEndpointDirection direction,
|
| + uint8 endpoint,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int packets,
|
| + unsigned int packet_length,
|
| + unsigned int timeout,
|
| + const TransferCallback& callback) {
|
| + if (task_runner_->BelongsToCurrentThread()) {
|
| + IsochronousTransferInternal(direction, endpoint, buffer, length, packets,
|
| + packet_length, timeout, task_runner_, callback);
|
| + } else {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal, this,
|
| + direction, endpoint, buffer, length, packets, packet_length,
|
| + timeout, base::ThreadTaskRunnerHandle::Get(), callback));
|
| + }
|
| +}
|
| +
|
| +UsbDeviceHandleImpl::UsbDeviceHandleImpl(
|
| + scoped_refptr<UsbContext> context,
|
| + scoped_refptr<UsbDeviceImpl> device,
|
| + PlatformUsbDeviceHandle handle,
|
| + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
|
| + : device_(device),
|
| + handle_(handle),
|
| + context_(context),
|
| + task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + blocking_task_runner_(blocking_task_runner) {
|
| + DCHECK(handle) << "Cannot create device with NULL handle.";
|
| +}
|
| +
|
| +UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + libusb_close(handle_);
|
| + handle_ = NULL;
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
|
| + PlatformUsbDeviceHandle handle,
|
| + int configuration_value,
|
| + const ResultCallback& callback) {
|
| + int rv = libusb_set_configuration(handle_, configuration_value);
|
| + if (rv != LIBUSB_SUCCESS) {
|
| + USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
|
| + << ": " << ConvertPlatformUsbErrorToString(rv);
|
| + }
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete,
|
| + this, rv == LIBUSB_SUCCESS, callback));
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::SetConfigurationComplete(
|
| + bool success,
|
| + const ResultCallback& callback) {
|
| + if (success) {
|
| + device_->RefreshConfiguration();
|
| + RefreshEndpointMap();
|
| + }
|
| + callback.Run(success);
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
|
| + PlatformUsbDeviceHandle handle,
|
| + int interface_number,
|
| + const ResultCallback& callback) {
|
| + int rv = libusb_claim_interface(handle, interface_number);
|
| + if (rv != LIBUSB_SUCCESS) {
|
| + VLOG(1) << "Failed to claim interface: "
|
| + << ConvertPlatformUsbErrorToString(rv);
|
| + }
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete, this,
|
| + interface_number, rv == LIBUSB_SUCCESS, callback));
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::ClaimInterfaceComplete(
|
| + int interface_number,
|
| + bool success,
|
| + const ResultCallback& callback) {
|
| + if (success) {
|
| + claimed_interfaces_[interface_number] =
|
| + new InterfaceClaimer(this, interface_number);
|
| + RefreshEndpointMap();
|
| + }
|
| + callback.Run(success);
|
| +}
|
| +
|
| +void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
|
| + PlatformUsbDeviceHandle handle,
|
| + int interface_number,
|
| + int alternate_setting,
|
| + const ResultCallback& callback) {
|
| + int rv = libusb_set_interface_alt_setting(handle, interface_number,
|
| + alternate_setting);
|
| + if (rv != LIBUSB_SUCCESS) {
|
| USB_LOG(EVENT) << "Failed to set interface " << interface_number
|
| << " to alternate setting " << alternate_setting << ": "
|
| << ConvertPlatformUsbErrorToString(rv);
|
| }
|
| - return rv == LIBUSB_SUCCESS;
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete,
|
| + this, interface_number, alternate_setting,
|
| + rv == LIBUSB_SUCCESS, callback));
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::ResetDevice() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!device_)
|
| - return false;
|
| +void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
|
| + int interface_number,
|
| + int alternate_setting,
|
| + bool success,
|
| + const ResultCallback& callback) {
|
| + if (success) {
|
| + claimed_interfaces_[interface_number]->set_alternate_setting(
|
| + alternate_setting);
|
| + RefreshEndpointMap();
|
| + }
|
| + callback.Run(success);
|
| +}
|
|
|
| - const int rv = libusb_reset_device(handle_);
|
| +void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
|
| + PlatformUsbDeviceHandle handle,
|
| + const ResultCallback& callback) {
|
| + int rv = libusb_reset_device(handle);
|
| if (rv != LIBUSB_SUCCESS) {
|
| USB_LOG(EVENT) << "Failed to reset device: "
|
| << ConvertPlatformUsbErrorToString(rv);
|
| }
|
| - return rv == LIBUSB_SUCCESS;
|
| + task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete, this,
|
| + rv == LIBUSB_SUCCESS, callback));
|
| }
|
|
|
| -bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id,
|
| - base::string16* string) {
|
| - if (!GetSupportedLanguages()) {
|
| - return false;
|
| - }
|
| +void UsbDeviceHandleImpl::ResetDeviceComplete(bool success,
|
| + const ResultCallback& callback) {
|
| + callback.Run(success);
|
| +}
|
|
|
| - std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id);
|
| - if (it != strings_.end()) {
|
| - *string = it->second;
|
| - return true;
|
| - }
|
| -
|
| - for (size_t i = 0; i < languages_.size(); ++i) {
|
| - // Get the string using language ID.
|
| - uint16 language_id = languages_[i];
|
| - // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
|
| - base::char16 text[128];
|
| - int size =
|
| - libusb_get_string_descriptor(handle_,
|
| - string_id,
|
| - language_id,
|
| - reinterpret_cast<unsigned char*>(&text[0]),
|
| - sizeof(text));
|
| - if (size < 0) {
|
| - USB_LOG(EVENT) << "Failed to get string descriptor " << string_id
|
| - << " (langid " << language_id
|
| - << "): " << ConvertPlatformUsbErrorToString(size);
|
| - continue;
|
| - } else if (size < 2) {
|
| - USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
|
| - << language_id << ") has no header.";
|
| - continue;
|
| - // The first 2 bytes of the descriptor are the total length and type tag.
|
| - } else if ((text[0] & 0xff) != size) {
|
| - USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
|
| - << language_id << ") size mismatch: " << (text[0] & 0xff)
|
| - << " != " << size;
|
| - continue;
|
| - } else if ((text[0] >> 8) != LIBUSB_DT_STRING) {
|
| - USB_LOG(EVENT) << "String descriptor " << string_id << " (langid "
|
| - << language_id << ") is not a string descriptor.";
|
| - continue;
|
| - }
|
| +void UsbDeviceHandleImpl::RefreshEndpointMap() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + endpoint_map_.clear();
|
| + const UsbConfigDescriptor* config = device_->GetConfiguration();
|
| + if (config) {
|
| + for (const auto& map_entry : claimed_interfaces_) {
|
| + int interface_number = map_entry.first;
|
| + const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second;
|
|
|
| - *string = base::string16(text + 1, (size - 2) / 2);
|
| - strings_[string_id] = *string;
|
| - return true;
|
| + for (const UsbInterfaceDescriptor& iface : config->interfaces) {
|
| + if (iface.interface_number == interface_number &&
|
| + iface.alternate_setting == claimed_iface->alternate_setting()) {
|
| + for (const UsbEndpointDescriptor& endpoint : iface.endpoints) {
|
| + endpoint_map_[endpoint.address] = interface_number;
|
| + }
|
| + break;
|
| + }
|
| + }
|
| + }
|
| }
|
| +}
|
|
|
| - return false;
|
| +scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
|
| +UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
|
| + if (ContainsKey(endpoint_map_, endpoint))
|
| + return claimed_interfaces_[endpoint_map_[endpoint]];
|
| + return NULL;
|
| }
|
|
|
| -void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
|
| - TransferRequestType request_type,
|
| - TransferRecipient recipient,
|
| - uint8 request,
|
| - uint16 value,
|
| - uint16 index,
|
| - net::IOBuffer* buffer,
|
| - size_t length,
|
| - unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| +void UsbDeviceHandleImpl::ControlTransferInternal(
|
| + UsbEndpointDirection direction,
|
| + TransferRequestType request_type,
|
| + TransferRecipient recipient,
|
| + uint8 request,
|
| + uint16 value,
|
| + uint16 index,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int timeout,
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!device_) {
|
| + callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
|
| + return;
|
| + }
|
| +
|
| if (length > UINT16_MAX) {
|
| USB_LOG(USER) << "Transfer too long.";
|
| callback.Run(USB_TRANSFER_ERROR, buffer, 0);
|
| @@ -685,22 +850,32 @@ void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
|
| length);
|
|
|
| scoped_ptr<Transfer> transfer = Transfer::CreateControlTransfer(
|
| - CreateRequestType(direction, request_type, recipient), request, value,
|
| - index, static_cast<uint16>(length), resized_buffer, timeout, callback);
|
| + this, CreateRequestType(direction, request_type, recipient), request,
|
| + value, index, static_cast<uint16>(length), resized_buffer, timeout,
|
| + callback_task_runner, callback);
|
| if (!transfer) {
|
| callback.Run(USB_TRANSFER_ERROR, buffer, 0);
|
| return;
|
| }
|
|
|
| - PostOrSubmitTransfer(transfer.Pass());
|
| + SubmitTransfer(transfer.Pass());
|
| }
|
|
|
| -void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction,
|
| - const uint8 endpoint,
|
| - net::IOBuffer* buffer,
|
| - const size_t length,
|
| - const unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| +void UsbDeviceHandleImpl::BulkTransferInternal(
|
| + const UsbEndpointDirection direction,
|
| + const uint8 endpoint,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + const size_t length,
|
| + const unsigned int timeout,
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!device_) {
|
| + callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
|
| + return;
|
| + }
|
| +
|
| if (length > INT_MAX) {
|
| USB_LOG(USER) << "Transfer too long.";
|
| callback.Run(USB_TRANSFER_ERROR, buffer, 0);
|
| @@ -708,19 +883,27 @@ void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction,
|
| }
|
|
|
| scoped_ptr<Transfer> transfer = Transfer::CreateBulkTransfer(
|
| - ConvertTransferDirection(direction) | endpoint, buffer,
|
| - static_cast<int>(length), timeout, callback);
|
| + this, ConvertTransferDirection(direction) | endpoint, buffer,
|
| + static_cast<int>(length), timeout, callback_task_runner, callback);
|
|
|
| - PostOrSubmitTransfer(transfer.Pass());
|
| + SubmitTransfer(transfer.Pass());
|
| }
|
|
|
| -void UsbDeviceHandleImpl::InterruptTransfer(
|
| +void UsbDeviceHandleImpl::InterruptTransferInternal(
|
| UsbEndpointDirection direction,
|
| uint8 endpoint,
|
| - net::IOBuffer* buffer,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!device_) {
|
| + callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
|
| + return;
|
| + }
|
| +
|
| if (length > INT_MAX) {
|
| USB_LOG(USER) << "Transfer too long.";
|
| callback.Run(USB_TRANSFER_ERROR, buffer, 0);
|
| @@ -728,21 +911,29 @@ void UsbDeviceHandleImpl::InterruptTransfer(
|
| }
|
|
|
| scoped_ptr<Transfer> transfer = Transfer::CreateInterruptTransfer(
|
| - ConvertTransferDirection(direction) | endpoint, buffer,
|
| - static_cast<int>(length), timeout, callback);
|
| + this, ConvertTransferDirection(direction) | endpoint, buffer,
|
| + static_cast<int>(length), timeout, callback_task_runner, callback);
|
|
|
| - PostOrSubmitTransfer(transfer.Pass());
|
| + SubmitTransfer(transfer.Pass());
|
| }
|
|
|
| -void UsbDeviceHandleImpl::IsochronousTransfer(
|
| +void UsbDeviceHandleImpl::IsochronousTransferInternal(
|
| const UsbEndpointDirection direction,
|
| - const uint8 endpoint,
|
| - net::IOBuffer* buffer,
|
| - const size_t length,
|
| - const unsigned int packets,
|
| - const unsigned int packet_length,
|
| - const unsigned int timeout,
|
| - const UsbTransferCallback& callback) {
|
| + uint8 endpoint,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int packets,
|
| + unsigned int packet_length,
|
| + unsigned int timeout,
|
| + scoped_refptr<base::TaskRunner> callback_task_runner,
|
| + const TransferCallback& callback) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + if (!device_) {
|
| + callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
|
| + return;
|
| + }
|
| +
|
| if (length > INT_MAX) {
|
| USB_LOG(USER) << "Transfer too long.";
|
| callback.Run(USB_TRANSFER_ERROR, buffer, 0);
|
| @@ -750,104 +941,35 @@ void UsbDeviceHandleImpl::IsochronousTransfer(
|
| }
|
|
|
| scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
|
| - ConvertTransferDirection(direction) | endpoint, buffer,
|
| - static_cast<int>(length), packets, packet_length, timeout, callback);
|
| + this, ConvertTransferDirection(direction) | endpoint, buffer,
|
| + static_cast<int>(length), packets, packet_length, timeout,
|
| + callback_task_runner, callback);
|
|
|
| - PostOrSubmitTransfer(transfer.Pass());
|
| + SubmitTransfer(transfer.Pass());
|
| }
|
|
|
| -void UsbDeviceHandleImpl::RefreshEndpointMap() {
|
| +void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - endpoint_map_.clear();
|
| - const UsbConfigDescriptor* config = device_->GetConfiguration();
|
| - if (config) {
|
| - for (const auto& map_entry : claimed_interfaces_) {
|
| - int interface_number = map_entry.first;
|
| - const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second;
|
|
|
| - for (const UsbInterfaceDescriptor& iface : config->interfaces) {
|
| - if (iface.interface_number == interface_number &&
|
| - iface.alternate_setting == claimed_iface->alternate_setting()) {
|
| - for (const UsbEndpointDescriptor& endpoint : iface.endpoints) {
|
| - endpoint_map_[endpoint.address] = interface_number;
|
| - }
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
|
| -UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
|
| - if (ContainsKey(endpoint_map_, endpoint))
|
| - return claimed_interfaces_[endpoint_map_[endpoint]];
|
| - return NULL;
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::PostOrSubmitTransfer(scoped_ptr<Transfer> transfer) {
|
| - if (task_runner_->RunsTasksOnCurrentThread()) {
|
| - SubmitTransfer(transfer.Pass());
|
| - } else {
|
| - task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, this,
|
| - base::Passed(&transfer)));
|
| - }
|
| + // Transfer is owned by libusb until its completion callback is run. This
|
| + // object holds a weak reference.
|
| + transfers_.insert(transfer.get());
|
| + blocking_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&Transfer::Submit, base::Unretained(transfer.release())));
|
| }
|
|
|
| -void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) {
|
| +void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
|
| + const base::Closure& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(ContainsKey(transfers_, transfer)) << "Missing transfer completed";
|
| + transfers_.erase(transfer);
|
|
|
| - if (device_) {
|
| - if (transfer->Submit(weak_factory_.GetWeakPtr())) {
|
| - // Transfer is now owned by libusb until its completion callback is run.
|
| - // This object holds a weak reference.
|
| - transfers_.insert(transfer.release());
|
| - }
|
| + if (transfer->callback_task_runner()->RunsTasksOnCurrentThread()) {
|
| + callback.Run();
|
| } else {
|
| - transfer->Complete(USB_TRANSFER_DISCONNECT, 0);
|
| - }
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::CompleteTransfer(scoped_ptr<Transfer> transfer) {
|
| - DCHECK(ContainsKey(transfers_, transfer.get()))
|
| - << "Missing transfer completed";
|
| - transfers_.erase(transfer.get());
|
| - transfer->ProcessCompletion();
|
| -}
|
| -
|
| -bool UsbDeviceHandleImpl::GetSupportedLanguages() {
|
| - if (!languages_.empty()) {
|
| - return true;
|
| + transfer->callback_task_runner()->PostTask(FROM_HERE, callback);
|
| }
|
| -
|
| - // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
|
| - uint16 languages[128];
|
| - int size = libusb_get_string_descriptor(
|
| - handle_,
|
| - 0,
|
| - 0,
|
| - reinterpret_cast<unsigned char*>(&languages[0]),
|
| - sizeof(languages));
|
| - if (size < 0) {
|
| - USB_LOG(EVENT) << "Failed to get list of supported languages: "
|
| - << ConvertPlatformUsbErrorToString(size);
|
| - return false;
|
| - } else if (size < 2) {
|
| - USB_LOG(EVENT) << "String descriptor zero has no header.";
|
| - return false;
|
| - // The first 2 bytes of the descriptor are the total length and type tag.
|
| - } else if ((languages[0] & 0xff) != size) {
|
| - USB_LOG(EVENT) << "String descriptor zero size mismatch: "
|
| - << (languages[0] & 0xff) << " != " << size;
|
| - return false;
|
| - } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) {
|
| - USB_LOG(EVENT) << "String descriptor zero is not a string descriptor.";
|
| - return false;
|
| - }
|
| -
|
| - languages_.assign(languages[1], languages[(size - 2) / 2]);
|
| - return true;
|
| }
|
|
|
| void UsbDeviceHandleImpl::InternalClose() {
|
|
|