Chromium Code Reviews| 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..ff2582178aeef1e80efa28c88f30e1e548791c17 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,72 @@ class UsbDeviceHandleImpl::Transfer { |
| uint16 length, |
| scoped_refptr<net::IOBuffer> buffer, |
| unsigned int timeout, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback); |
| static scoped_ptr<Transfer> CreateBulkTransfer( |
| + scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| uint8 endpoint, |
| scoped_refptr<net::IOBuffer> buffer, |
| int length, |
| unsigned int timeout, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback); |
| static scoped_ptr<Transfer> CreateInterruptTransfer( |
| + scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| uint8 endpoint, |
| scoped_refptr<net::IOBuffer> buffer, |
| int length, |
| unsigned int timeout, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& 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, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& 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(); |
| } |
| 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, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback); |
| static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); |
| UsbTransferType transfer_type_; |
| - base::WeakPtr<UsbDeviceHandleImpl> device_handle_; |
| + scoped_refptr<UsbDeviceHandleImpl> device_handle_; |
| PlatformUsbTransferHandle platform_transfer_; |
| scoped_refptr<net::IOBuffer> buffer_; |
| scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; |
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| size_t length_; |
| bool cancelled_; |
| + scoped_refptr<base::SequencedTaskRunner> task_runner_; |
| UsbTransferCallback callback_; |
| - scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; |
| }; |
| // static |
| scoped_ptr<UsbDeviceHandleImpl::Transfer> |
| UsbDeviceHandleImpl::Transfer::CreateControlTransfer( |
| + scoped_refptr<UsbDeviceHandleImpl> device_handle, |
| uint8 type, |
| uint8 request, |
| uint16 value, |
| @@ -227,10 +238,11 @@ UsbDeviceHandleImpl::Transfer::CreateControlTransfer( |
| uint16 length, |
| scoped_refptr<net::IOBuffer> buffer, |
| unsigned int timeout, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback) { |
| - scoped_ptr<Transfer> transfer(new Transfer(USB_TRANSFER_CONTROL, buffer, |
| - length + LIBUSB_CONTROL_SETUP_SIZE, |
| - callback)); |
| + scoped_ptr<Transfer> transfer( |
| + new Transfer(device_handle, nullptr, USB_TRANSFER_CONTROL, buffer, |
| + length + LIBUSB_CONTROL_SETUP_SIZE, task_runner, callback)); |
| transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| if (!transfer->platform_transfer_) { |
| @@ -241,7 +253,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 +264,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, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback) { |
| - scoped_ptr<Transfer> transfer( |
| - new Transfer(USB_TRANSFER_BULK, buffer, length, callback)); |
| + scoped_ptr<Transfer> transfer(new Transfer( |
| + device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| + USB_TRANSFER_BULK, buffer, length, task_runner, callback)); |
| transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| if (!transfer->platform_transfer_) { |
| @@ -266,12 +281,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 +293,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, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& callback) { |
| - scoped_ptr<Transfer> transfer( |
| - new Transfer(USB_TRANSFER_INTERRUPT, buffer, length, callback)); |
| + scoped_ptr<Transfer> transfer(new Transfer( |
| + device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), |
| + USB_TRANSFER_INTERRUPT, buffer, length, task_runner, callback)); |
| transfer->platform_transfer_ = libusb_alloc_transfer(0); |
| if (!transfer->platform_transfer_) { |
| @@ -294,9 +311,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 +322,21 @@ 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, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| const UsbTransferCallback& 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, task_runner, callback)); |
| transfer->platform_transfer_ = libusb_alloc_transfer(packets); |
| if (!transfer->platform_transfer_) { |
| @@ -326,27 +345,31 @@ 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::SequencedTaskRunner> task_runner, |
| + const UsbTransferCallback& callback) |
| : transfer_type_(transfer_type), |
| + device_handle_(device_handle), |
| + platform_transfer_(NULL), |
| buffer_(buffer), |
| + claimed_interface_(claimed_interface), |
| length_(length), |
| cancelled_(false), |
| + task_runner_(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(); |
| } |
| UsbDeviceHandleImpl::Transfer::~Transfer() { |
| @@ -355,26 +378,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,43 +462,38 @@ 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); |
| + transfer->ProcessCompletion(); |
| +} |
| - // 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))); |
| +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))); |
| } |
| -UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, |
| - scoped_refptr<UsbDeviceImpl> device, |
| - PlatformUsbDeviceHandle handle) |
| +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()), |
| - weak_factory_(this) { |
| + blocking_task_runner_(blocking_task_runner) { |
| DCHECK(handle) << "Cannot create device with NULL handle."; |
| } |
| @@ -510,10 +514,12 @@ void UsbDeviceHandleImpl::Close() { |
| device_->Close(this); |
| } |
| -bool UsbDeviceHandleImpl::SetConfiguration(int configuration_value) { |
| +void UsbDeviceHandleImpl::SetConfiguration(int configuration_value, |
| + const UsbSuccessCallback& callback) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (!device_) { |
| - return false; |
| + task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| } |
| for (Transfer* transfer : transfers_) { |
| @@ -521,36 +527,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 UsbSuccessCallback& 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_) { |
| + task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| } |
| - return false; |
| + if (ContainsKey(claimed_interfaces_, interface_number)) { |
| + task_runner_->PostTask(FROM_HERE, base::Bind(callback, true)); |
|
Ken Rockot(use gerrit already)
2015/04/07 22:09:43
nit: Maybe it doesn't matter, but is there realist
Reilly Grant (use Gerrit)
2015/04/08 21:39:03
I'll change it because I've recently decided that
|
| + return; |
| + } |
| + |
| + 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,91 +572,33 @@ 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 UsbSuccessCallback& 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(); |
| - } else { |
| - USB_LOG(EVENT) << "Failed to set interface " << interface_number |
| - << " to alternate setting " << alternate_setting << ": " |
| - << ConvertPlatformUsbErrorToString(rv); |
| + if (!device_ || !ContainsKey(claimed_interfaces_, interface_number)) { |
| + task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| } |
| - return rv == LIBUSB_SUCCESS; |
| -} |
| - |
| -bool UsbDeviceHandleImpl::ResetDevice() { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| - if (!device_) |
| - return false; |
| - const int rv = libusb_reset_device(handle_); |
| - if (rv != LIBUSB_SUCCESS) { |
| - USB_LOG(EVENT) << "Failed to reset device: " |
| - << ConvertPlatformUsbErrorToString(rv); |
| - } |
| - return rv == LIBUSB_SUCCESS; |
| + blocking_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread, |
| + this, handle_, interface_number, alternate_setting, callback)); |
| } |
| -bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, |
| - base::string16* string) { |
| - if (!GetSupportedLanguages()) { |
| - return false; |
| - } |
| - |
| - 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; |
| - } |
| - |
| - *string = base::string16(text + 1, (size - 2) / 2); |
| - strings_[string_id] = *string; |
| - return true; |
| +void UsbDeviceHandleImpl::ResetDevice(const UsbSuccessCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (!device_) { |
| + task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
| + return; |
| } |
| - return false; |
| + blocking_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread, |
| + this, handle_, callback)); |
| } |
| void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, |
| @@ -668,6 +611,13 @@ void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction, |
| size_t length, |
| unsigned int timeout, |
| const UsbTransferCallback& 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,14 +635,15 @@ 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, |
| + 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, |
| @@ -701,6 +652,13 @@ void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, |
| const size_t length, |
| const unsigned int timeout, |
| const UsbTransferCallback& 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,10 +666,10 @@ 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, task_runner_, callback); |
| - PostOrSubmitTransfer(transfer.Pass()); |
| + SubmitTransfer(transfer.Pass()); |
| } |
| void UsbDeviceHandleImpl::InterruptTransfer( |
| @@ -721,6 +679,13 @@ void UsbDeviceHandleImpl::InterruptTransfer( |
| size_t length, |
| unsigned int timeout, |
| const UsbTransferCallback& 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,10 +693,10 @@ 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, task_runner_, callback); |
| - PostOrSubmitTransfer(transfer.Pass()); |
| + SubmitTransfer(transfer.Pass()); |
| } |
| void UsbDeviceHandleImpl::IsochronousTransfer( |
| @@ -743,6 +708,13 @@ void UsbDeviceHandleImpl::IsochronousTransfer( |
| const unsigned int packet_length, |
| const unsigned int timeout, |
| const UsbTransferCallback& 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,10 +722,112 @@ 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, task_runner_, |
| + callback); |
| + |
| + SubmitTransfer(transfer.Pass()); |
| +} |
| + |
| +void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread( |
| + PlatformUsbDeviceHandle handle, |
| + int configuration_value, |
| + const UsbSuccessCallback& 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 UsbSuccessCallback& callback) { |
| + if (success) { |
| + device_->RefreshConfiguration(); |
| + RefreshEndpointMap(); |
| + } |
| + callback.Run(success); |
| +} |
| + |
| +void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread( |
| + PlatformUsbDeviceHandle handle, |
| + int interface_number, |
| + const UsbSuccessCallback& 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 UsbSuccessCallback& callback) { |
| + if (success) { |
| + claimed_interfaces_[interface_number] = |
| + new InterfaceClaimer(this, interface_number); |
| + RefreshEndpointMap(); |
| + } |
| + callback.Run(success); |
| +} |
| - PostOrSubmitTransfer(transfer.Pass()); |
| +void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread( |
| + PlatformUsbDeviceHandle handle, |
| + int interface_number, |
| + int alternate_setting, |
| + const UsbSuccessCallback& 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); |
| + } |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete, |
| + this, interface_number, alternate_setting, |
| + rv == LIBUSB_SUCCESS, callback)); |
| +} |
| + |
| +void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete( |
| + int interface_number, |
| + int alternate_setting, |
| + bool success, |
| + const UsbSuccessCallback& callback) { |
| + if (success) { |
| + claimed_interfaces_[interface_number]->set_alternate_setting( |
| + alternate_setting); |
| + RefreshEndpointMap(); |
| + } |
| + callback.Run(success); |
| +} |
| + |
| +void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread( |
| + PlatformUsbDeviceHandle handle, |
| + const UsbSuccessCallback& callback) { |
| + int rv = libusb_reset_device(handle); |
| + if (rv != LIBUSB_SUCCESS) { |
| + USB_LOG(EVENT) << "Failed to reset device: " |
| + << ConvertPlatformUsbErrorToString(rv); |
| + } |
| + task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceComplete, this, |
| + rv == LIBUSB_SUCCESS, callback)); |
| +} |
| + |
| +void UsbDeviceHandleImpl::ResetDeviceComplete( |
| + bool success, |
| + const UsbSuccessCallback& callback) { |
| + callback.Run(success); |
| } |
| void UsbDeviceHandleImpl::RefreshEndpointMap() { |
| @@ -785,69 +859,23 @@ UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char 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))); |
| - } |
| -} |
| - |
| void UsbDeviceHandleImpl::SubmitTransfer(scoped_ptr<Transfer> transfer) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - 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()); |
| - } |
| - } else { |
| - transfer->Complete(USB_TRANSFER_DISCONNECT, 0); |
| - } |
| + // 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::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; |
| - } |
| - |
| - // 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::TransferComplete(Transfer* transfer, |
| + const base::Closure& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(ContainsKey(transfers_, transfer)) << "Missing transfer completed"; |
| + transfers_.erase(transfer); |
| + callback.Run(); |
| } |
| void UsbDeviceHandleImpl::InternalClose() { |