Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2492)

Unified Diff: device/usb/usb_device_handle_impl.cc

Issue 1618393004: Update device/usb and its Mojo interface for variable size ISO packets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Document use of ErrorWithArguments. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | extensions/browser/api/usb/usb_api.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 338af1663b9aff190db2ce63aa9b19bffe9c8f44..fa4c08544ff53997e053f31fbc4b79febb274455 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -5,6 +5,7 @@
#include "device/usb/usb_device_handle_impl.h"
#include <algorithm>
+#include <numeric>
#include <utility>
#include <vector>
@@ -120,6 +121,26 @@ static void RunTransferCallback(
}
}
+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));
+ }
+}
+
} // namespace
class UsbDeviceHandleImpl::InterfaceClaimer
@@ -191,11 +212,10 @@ class UsbDeviceHandleImpl::Transfer {
uint8_t endpoint,
scoped_refptr<net::IOBuffer> buffer,
size_t length,
- unsigned int packets,
- unsigned int packet_length,
+ const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
- scoped_refptr<base::TaskRunner> task_runner,
- const TransferCallback& callback);
+ scoped_refptr<base::TaskRunner> callback_task_runner,
+ const IsochronousTransferCallback& callback);
~Transfer();
@@ -220,9 +240,16 @@ class UsbDeviceHandleImpl::Transfer {
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_;
PlatformUsbTransferHandle platform_transfer_ = nullptr;
@@ -233,6 +260,7 @@ class UsbDeviceHandleImpl::Transfer {
scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_refptr<base::TaskRunner> callback_task_runner_;
TransferCallback callback_;
+ IsochronousTransferCallback iso_callback_;
};
// static
@@ -289,11 +317,11 @@ UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
return nullptr;
}
- 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);
+ libusb_fill_bulk_transfer(transfer->platform_transfer_,
+ device_handle->handle_, endpoint,
+ reinterpret_cast<uint8_t*>(buffer->data()), length,
+ &UsbDeviceHandleImpl::Transfer::PlatformCallback,
+ transfer.get(), timeout);
return transfer;
}
@@ -320,7 +348,7 @@ UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
libusb_fill_interrupt_transfer(
transfer->platform_transfer_, device_handle->handle_, endpoint,
- reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
+ reinterpret_cast<uint8_t*>(buffer->data()), length,
&UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
timeout);
@@ -334,20 +362,16 @@ UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
uint8_t endpoint,
scoped_refptr<net::IOBuffer> buffer,
size_t length,
- unsigned int packets,
- unsigned int packet_length,
+ const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
scoped_refptr<base::TaskRunner> callback_task_runner,
- const TransferCallback& callback) {
- DCHECK(packets <= length && (packets * packet_length) <= length)
- << "transfer length is too small";
-
+ const IsochronousTransferCallback& callback) {
scoped_ptr<Transfer> transfer(new Transfer(
device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
- USB_TRANSFER_ISOCHRONOUS, buffer, length, callback_task_runner,
- callback));
+ buffer, callback_task_runner, callback));
- transfer->platform_transfer_ = libusb_alloc_transfer(packets);
+ int num_packets = static_cast<int>(packet_lengths.size());
+ transfer->platform_transfer_ = libusb_alloc_transfer(num_packets);
if (!transfer->platform_transfer_) {
USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
return nullptr;
@@ -356,8 +380,10 @@ UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
libusb_fill_iso_transfer(
transfer->platform_transfer_, device_handle->handle_, endpoint,
reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
- packets, &Transfer::PlatformCallback, transfer.get(), timeout);
- libusb_set_iso_packet_lengths(transfer->platform_transfer_, packet_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];
return transfer;
}
@@ -380,6 +406,21 @@ UsbDeviceHandleImpl::Transfer::Transfer(
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_);
@@ -431,46 +472,22 @@ void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
buffer_ = resized_buffer;
}
}
- 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;
+ // Fall through!
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 */
@@ -484,11 +501,37 @@ void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
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),
- base::Bind(callback_, status, buffer_, bytes_transferred)));
+ 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)));
}
scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
@@ -632,26 +675,42 @@ void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
}
}
-void UsbDeviceHandleImpl::IsochronousTransfer(
- UsbEndpointDirection direction,
+void UsbDeviceHandleImpl::IsochronousTransferIn(
+ uint8_t endpoint_number,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback) {
+ uint8_t endpoint_address =
+ ConvertTransferDirection(USB_DIRECTION_INBOUND) | endpoint_number;
+ if (task_runner_->BelongsToCurrentThread()) {
+ IsochronousTransferInInternal(endpoint_address, packet_lengths, 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,
- size_t length,
- unsigned int packets,
- unsigned int packet_length,
+ const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
- const TransferCallback& callback) {
+ const IsochronousTransferCallback& callback) {
uint8_t endpoint_address =
- ConvertTransferDirection(direction) | endpoint_number;
+ ConvertTransferDirection(USB_DIRECTION_OUTBOUND) | endpoint_number;
if (task_runner_->BelongsToCurrentThread()) {
- IsochronousTransferInternal(endpoint_address, buffer, length, packets,
- packet_length, timeout, task_runner_, callback);
+ IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths,
+ timeout, task_runner_, callback);
} else {
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInternal, this,
- endpoint_address, buffer, length, packets, packet_length,
- timeout, base::ThreadTaskRunnerHandle::Get(), callback));
+ base::Bind(&UsbDeviceHandleImpl::IsochronousTransferOutInternal, this,
+ endpoint_address, buffer, packet_lengths, timeout,
+ base::ThreadTaskRunnerHandle::Get(), callback));
}
}
@@ -886,33 +945,50 @@ void UsbDeviceHandleImpl::ControlTransferInternal(
SubmitTransfer(std::move(transfer));
}
-void UsbDeviceHandleImpl::IsochronousTransferInternal(
+void UsbDeviceHandleImpl::IsochronousTransferInInternal(
uint8_t endpoint_address,
- scoped_refptr<net::IOBuffer> buffer,
- size_t length,
- unsigned int packets,
- unsigned int packet_length,
+ const std::vector<uint32_t>& packet_lengths,
unsigned int timeout,
scoped_refptr<base::TaskRunner> callback_task_runner,
- const TransferCallback& callback) {
+ const IsochronousTransferCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!device_) {
- RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
- buffer, 0);
+ ReportIsochronousTransferError(callback_task_runner, callback,
+ packet_lengths, USB_TRANSFER_DISCONNECT);
return;
}
- if (!base::IsValueInRangeForNumericType<int>(length)) {
- USB_LOG(USER) << "Transfer too long.";
- RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
- buffer, 0);
+ size_t length =
+ std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(length));
+ 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, static_cast<int>(length), packets,
- packet_length, timeout, callback_task_runner, callback);
+ this, endpoint_address, buffer, length, packet_lengths, timeout,
+ callback_task_runner, callback);
SubmitTransfer(std::move(transfer));
}
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | extensions/browser/api/usb/usb_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698