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)); |
} |