| 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 fa4c08544ff53997e053f31fbc4b79febb274455..338af1663b9aff190db2ce63aa9b19bffe9c8f44 100644
|
| --- a/device/usb/usb_device_handle_impl.cc
|
| +++ b/device/usb/usb_device_handle_impl.cc
|
| @@ -5,7 +5,6 @@
|
| #include "device/usb/usb_device_handle_impl.h"
|
|
|
| #include <algorithm>
|
| -#include <numeric>
|
| #include <utility>
|
| #include <vector>
|
|
|
| @@ -118,26 +117,6 @@
|
| } else {
|
| callback_task_runner->PostTask(
|
| FROM_HERE, base::Bind(callback, status, buffer, result));
|
| - }
|
| -}
|
| -
|
| -void ReportIsochronousTransferError(
|
| - scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const UsbDeviceHandle::IsochronousTransferCallback& callback,
|
| - const std::vector<uint32_t> packet_lengths,
|
| - UsbTransferStatus status) {
|
| - std::vector<UsbDeviceHandle::IsochronousPacket> packets(
|
| - packet_lengths.size());
|
| - for (size_t i = 0; i < packet_lengths.size(); ++i) {
|
| - packets[i].length = packet_lengths[i];
|
| - packets[i].transferred_length = 0;
|
| - packets[i].status = status;
|
| - }
|
| - if (callback_task_runner->RunsTasksOnCurrentThread()) {
|
| - callback.Run(nullptr, packets);
|
| - } else {
|
| - callback_task_runner->PostTask(FROM_HERE,
|
| - base::Bind(callback, nullptr, packets));
|
| }
|
| }
|
|
|
| @@ -212,10 +191,11 @@
|
| uint8_t endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| + unsigned int packets,
|
| + unsigned int packet_length,
|
| unsigned int timeout,
|
| - scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const IsochronousTransferCallback& callback);
|
| + scoped_refptr<base::TaskRunner> task_runner,
|
| + const TransferCallback& callback);
|
|
|
| ~Transfer();
|
|
|
| @@ -240,15 +220,8 @@
|
| size_t length,
|
| scoped_refptr<base::TaskRunner> callback_task_runner,
|
| const TransferCallback& callback);
|
| - Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| - scoped_refptr<InterfaceClaimer> claimed_interface,
|
| - scoped_refptr<net::IOBuffer> buffer,
|
| - scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const IsochronousTransferCallback& callback);
|
|
|
| static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);
|
| -
|
| - void IsochronousTransferComplete();
|
|
|
| UsbTransferType transfer_type_;
|
| scoped_refptr<UsbDeviceHandleImpl> device_handle_;
|
| @@ -260,7 +233,6 @@
|
| scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
| scoped_refptr<base::TaskRunner> callback_task_runner_;
|
| TransferCallback callback_;
|
| - IsochronousTransferCallback iso_callback_;
|
| };
|
|
|
| // static
|
| @@ -317,11 +289,11 @@
|
| return nullptr;
|
| }
|
|
|
| - libusb_fill_bulk_transfer(transfer->platform_transfer_,
|
| - device_handle->handle_, endpoint,
|
| - reinterpret_cast<uint8_t*>(buffer->data()), length,
|
| - &UsbDeviceHandleImpl::Transfer::PlatformCallback,
|
| - transfer.get(), timeout);
|
| + libusb_fill_bulk_transfer(
|
| + transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| + reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
|
| + &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
|
| + timeout);
|
|
|
| return transfer;
|
| }
|
| @@ -348,7 +320,7 @@
|
|
|
| libusb_fill_interrupt_transfer(
|
| transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| - reinterpret_cast<uint8_t*>(buffer->data()), length,
|
| + reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
|
| &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
|
| timeout);
|
|
|
| @@ -362,16 +334,20 @@
|
| uint8_t endpoint,
|
| scoped_refptr<net::IOBuffer> buffer,
|
| size_t length,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| + unsigned int packets,
|
| + unsigned int packet_length,
|
| unsigned int timeout,
|
| scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const IsochronousTransferCallback& callback) {
|
| + const TransferCallback& callback) {
|
| + DCHECK(packets <= length && (packets * packet_length) <= length)
|
| + << "transfer length is too small";
|
| +
|
| scoped_ptr<Transfer> transfer(new Transfer(
|
| device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
|
| - buffer, callback_task_runner, callback));
|
| -
|
| - int num_packets = static_cast<int>(packet_lengths.size());
|
| - transfer->platform_transfer_ = libusb_alloc_transfer(num_packets);
|
| + USB_TRANSFER_ISOCHRONOUS, buffer, length, callback_task_runner,
|
| + callback));
|
| +
|
| + transfer->platform_transfer_ = libusb_alloc_transfer(packets);
|
| if (!transfer->platform_transfer_) {
|
| USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
|
| return nullptr;
|
| @@ -380,10 +356,8 @@
|
| libusb_fill_iso_transfer(
|
| transfer->platform_transfer_, device_handle->handle_, endpoint,
|
| reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
|
| - num_packets, &Transfer::PlatformCallback, transfer.get(), timeout);
|
| -
|
| - for (size_t i = 0; i < packet_lengths.size(); ++i)
|
| - transfer->platform_transfer_->iso_packet_desc[i].length = packet_lengths[i];
|
| + packets, &Transfer::PlatformCallback, transfer.get(), timeout);
|
| + libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_length);
|
|
|
| return transfer;
|
| }
|
| @@ -406,21 +380,6 @@
|
| task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| }
|
|
|
| -UsbDeviceHandleImpl::Transfer::Transfer(
|
| - scoped_refptr<UsbDeviceHandleImpl> device_handle,
|
| - scoped_refptr<InterfaceClaimer> claimed_interface,
|
| - scoped_refptr<net::IOBuffer> buffer,
|
| - scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const IsochronousTransferCallback& callback)
|
| - : transfer_type_(USB_TRANSFER_ISOCHRONOUS),
|
| - device_handle_(device_handle),
|
| - buffer_(buffer),
|
| - claimed_interface_(claimed_interface),
|
| - callback_task_runner_(callback_task_runner),
|
| - iso_callback_(callback) {
|
| - task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| -}
|
| -
|
| UsbDeviceHandleImpl::Transfer::~Transfer() {
|
| if (platform_transfer_) {
|
| libusb_free_transfer(platform_transfer_);
|
| @@ -472,22 +431,46 @@
|
| buffer_ = resized_buffer;
|
| }
|
| }
|
| - // Fall through!
|
| + break;
|
| +
|
| + case USB_TRANSFER_ISOCHRONOUS:
|
| + // Isochronous replies might carry data in the different isoc packets even
|
| + // if the transfer actual_data value is zero. Furthermore, not all of the
|
| + // received packets might contain data, so we need to calculate how many
|
| + // data bytes we are effectively providing and pack the results.
|
| + if (actual_length == 0) {
|
| + size_t packet_buffer_start = 0;
|
| + for (int i = 0; i < platform_transfer_->num_iso_packets; ++i) {
|
| + PlatformUsbIsoPacketDescriptor packet =
|
| + &platform_transfer_->iso_packet_desc[i];
|
| + if (packet->actual_length > 0) {
|
| + // We don't need to copy as long as all packets until now provide
|
| + // all the data the packet can hold.
|
| + if (actual_length < packet_buffer_start) {
|
| + CHECK(packet_buffer_start + packet->actual_length <= length_);
|
| + memmove(buffer_->data() + actual_length,
|
| + buffer_->data() + packet_buffer_start,
|
| + packet->actual_length);
|
| + }
|
| + actual_length += packet->actual_length;
|
| + }
|
| +
|
| + packet_buffer_start += packet->length;
|
| + }
|
| + }
|
| + break;
|
|
|
| case USB_TRANSFER_BULK:
|
| case USB_TRANSFER_INTERRUPT:
|
| - TransferComplete(ConvertTransferStatus(platform_transfer_->status),
|
| - actual_length);
|
| - break;
|
| -
|
| - case USB_TRANSFER_ISOCHRONOUS:
|
| - IsochronousTransferComplete();
|
| break;
|
|
|
| default:
|
| NOTREACHED() << "Invalid usb transfer type";
|
| break;
|
| }
|
| +
|
| + TransferComplete(ConvertTransferStatus(platform_transfer_->status),
|
| + actual_length);
|
| }
|
|
|
| /* static */
|
| @@ -501,37 +484,11 @@
|
|
|
| void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
|
| size_t bytes_transferred) {
|
| - base::Closure closure;
|
| - if (transfer_type_ == USB_TRANSFER_ISOCHRONOUS) {
|
| - DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status);
|
| - std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets);
|
| - for (size_t i = 0; i < packets.size(); ++i) {
|
| - packets[i].length = platform_transfer_->iso_packet_desc[i].length;
|
| - packets[i].transferred_length = 0;
|
| - packets[i].status = status;
|
| - }
|
| - closure = base::Bind(iso_callback_, buffer_, packets);
|
| - } else {
|
| - closure = base::Bind(callback_, status, buffer_, bytes_transferred);
|
| - }
|
| task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&UsbDeviceHandleImpl::TransferComplete,
|
| - device_handle_, base::Unretained(this), closure));
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::Transfer::IsochronousTransferComplete() {
|
| - std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets);
|
| - for (size_t i = 0; i < packets.size(); ++i) {
|
| - packets[i].length = platform_transfer_->iso_packet_desc[i].length;
|
| - packets[i].transferred_length =
|
| - platform_transfer_->iso_packet_desc[i].actual_length;
|
| - packets[i].status =
|
| - ConvertTransferStatus(platform_transfer_->iso_packet_desc[i].status);
|
| - }
|
| - task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&UsbDeviceHandleImpl::TransferComplete,
|
| - device_handle_, base::Unretained(this),
|
| - base::Bind(iso_callback_, buffer_, packets)));
|
| + FROM_HERE,
|
| + base::Bind(&UsbDeviceHandleImpl::TransferComplete, device_handle_,
|
| + base::Unretained(this),
|
| + base::Bind(callback_, status, buffer_, bytes_transferred)));
|
| }
|
|
|
| scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
|
| @@ -675,42 +632,26 @@
|
| }
|
| }
|
|
|
| -void UsbDeviceHandleImpl::IsochronousTransferIn(
|
| +void UsbDeviceHandleImpl::IsochronousTransfer(
|
| + UsbEndpointDirection direction,
|
| uint8_t endpoint_number,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| + scoped_refptr<net::IOBuffer> buffer,
|
| + size_t length,
|
| + unsigned int packets,
|
| + unsigned int packet_length,
|
| unsigned int timeout,
|
| - const IsochronousTransferCallback& callback) {
|
| + const TransferCallback& callback) {
|
| uint8_t endpoint_address =
|
| - ConvertTransferDirection(USB_DIRECTION_INBOUND) | endpoint_number;
|
| + ConvertTransferDirection(direction) | endpoint_number;
|
| if (task_runner_->BelongsToCurrentThread()) {
|
| - IsochronousTransferInInternal(endpoint_address, packet_lengths, timeout,
|
| - task_runner_, callback);
|
| + IsochronousTransferInternal(endpoint_address, buffer, length, packets,
|
| + packet_length, timeout, task_runner_, callback);
|
| } else {
|
| task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInInternal, this,
|
| - endpoint_address, packet_lengths, timeout,
|
| - base::ThreadTaskRunnerHandle::Get(), callback));
|
| - }
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::IsochronousTransferOut(
|
| - uint8_t endpoint_number,
|
| - scoped_refptr<net::IOBuffer> buffer,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| - unsigned int timeout,
|
| - const IsochronousTransferCallback& callback) {
|
| - uint8_t endpoint_address =
|
| - ConvertTransferDirection(USB_DIRECTION_OUTBOUND) | endpoint_number;
|
| - if (task_runner_->BelongsToCurrentThread()) {
|
| - IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths,
|
| - timeout, task_runner_, callback);
|
| - } else {
|
| - task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&UsbDeviceHandleImpl::IsochronousTransferOutInternal, this,
|
| - endpoint_address, buffer, packet_lengths, timeout,
|
| - base::ThreadTaskRunnerHandle::Get(), callback));
|
| + base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal, this,
|
| + endpoint_address, buffer, length, packets, packet_length,
|
| + timeout, base::ThreadTaskRunnerHandle::Get(), callback));
|
| }
|
| }
|
|
|
| @@ -945,50 +886,33 @@
|
| SubmitTransfer(std::move(transfer));
|
| }
|
|
|
| -void UsbDeviceHandleImpl::IsochronousTransferInInternal(
|
| +void UsbDeviceHandleImpl::IsochronousTransferInternal(
|
| uint8_t endpoint_address,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| + 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 IsochronousTransferCallback& callback) {
|
| + const TransferCallback& callback) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| if (!device_) {
|
| - ReportIsochronousTransferError(callback_task_runner, callback,
|
| - packet_lengths, USB_TRANSFER_DISCONNECT);
|
| - return;
|
| - }
|
| -
|
| - size_t length =
|
| - std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
|
| - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(length));
|
| + RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
|
| + buffer, 0);
|
| + return;
|
| + }
|
| +
|
| + if (!base::IsValueInRangeForNumericType<int>(length)) {
|
| + USB_LOG(USER) << "Transfer too long.";
|
| + RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
|
| + buffer, 0);
|
| + return;
|
| + }
|
| +
|
| scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
|
| - this, endpoint_address, buffer, length, packet_lengths, timeout,
|
| - callback_task_runner, callback);
|
| -
|
| - SubmitTransfer(std::move(transfer));
|
| -}
|
| -
|
| -void UsbDeviceHandleImpl::IsochronousTransferOutInternal(
|
| - uint8_t endpoint_address,
|
| - scoped_refptr<net::IOBuffer> buffer,
|
| - const std::vector<uint32_t>& packet_lengths,
|
| - unsigned int timeout,
|
| - scoped_refptr<base::TaskRunner> callback_task_runner,
|
| - const IsochronousTransferCallback& callback) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - if (!device_) {
|
| - ReportIsochronousTransferError(callback_task_runner, callback,
|
| - packet_lengths, USB_TRANSFER_DISCONNECT);
|
| - return;
|
| - }
|
| -
|
| - size_t length =
|
| - std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
|
| - scoped_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
|
| - this, endpoint_address, buffer, length, packet_lengths, timeout,
|
| - callback_task_runner, callback);
|
| + this, endpoint_address, buffer, static_cast<int>(length), packets,
|
| + packet_length, timeout, callback_task_runner, callback);
|
|
|
| SubmitTransfer(std::move(transfer));
|
| }
|
|
|