summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
authorreillyg <reillyg@chromium.org>2016-02-01 16:56:15 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-02 00:58:06 +0000
commit051c98e9d3e843295d659b5676fcfa9dc1be5da6 (patch)
tree54414ed43e166fb91bcfb3d6413157ad9cf27fe6 /device
parentea6d840e4d96f6df739f55a89ccf69daa3569a77 (diff)
downloadchromium_src-051c98e9d3e843295d659b5676fcfa9dc1be5da6.zip
chromium_src-051c98e9d3e843295d659b5676fcfa9dc1be5da6.tar.gz
chromium_src-051c98e9d3e843295d659b5676fcfa9dc1be5da6.tar.bz2
Update device/usb and its Mojo interface for variable size ISO packets.
To support the WebUSB API our underlying USB library needs to support isochronous transfers with full control over the packet size. We also need to know the completion status of each packet which was previously not available. This patch updates the interface to match that provided by libusb and the underlying platform specific APIs. BUG=492204 Review URL: https://codereview.chromium.org/1618393004 Cr-Commit-Position: refs/heads/master@{#372844}
Diffstat (limited to 'device')
-rw-r--r--device/devices_app/usb/device_impl.cc96
-rw-r--r--device/devices_app/usb/device_impl.h12
-rw-r--r--device/devices_app/usb/device_impl_unittest.cc195
-rw-r--r--device/devices_app/usb/public/interfaces/device.mojom37
-rw-r--r--device/devices_app/usb/type_converters.cc13
-rw-r--r--device/devices_app/usb/type_converters.h12
-rw-r--r--device/usb/mock_usb_device_handle.h23
-rw-r--r--device/usb/usb_device_handle.h32
-rw-r--r--device/usb/usb_device_handle_impl.cc240
-rw-r--r--device/usb/usb_device_handle_impl.h35
10 files changed, 455 insertions, 240 deletions
diff --git a/device/devices_app/usb/device_impl.cc b/device/devices_app/usb/device_impl.cc
index fd2f0ff..ae8ad40 100644
--- a/device/devices_app/usb/device_impl.cc
+++ b/device/devices_app/usb/device_impl.cc
@@ -5,7 +5,11 @@
#include "device/devices_app/usb/device_impl.h"
#include <stddef.h>
+
+#include <algorithm>
+#include <numeric>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/callback.h"
@@ -128,32 +132,46 @@ void OnControlTransferOutPermissionCheckComplete(
}
}
+mojo::Array<IsochronousPacketPtr> BuildIsochronousPacketArray(
+ mojo::Array<uint32_t> packet_lengths,
+ TransferStatus status) {
+ mojo::Array<IsochronousPacketPtr> packets(packet_lengths.size());
+ for (size_t i = 0; i < packet_lengths.size(); ++i) {
+ packets[i] = IsochronousPacket::New();
+ packets[i]->length = packet_lengths[i];
+ packets[i]->status = status;
+ }
+ return packets;
+}
+
void OnIsochronousTransferIn(
scoped_ptr<Device::IsochronousTransferInCallback> callback,
- uint32_t packet_size,
- UsbTransferStatus status,
scoped_refptr<net::IOBuffer> buffer,
- size_t buffer_size) {
- size_t num_packets = buffer_size / packet_size;
- mojo::Array<mojo::Array<uint8_t>> packets(num_packets);
+ const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
+ mojo::Array<uint8_t> data;
if (buffer) {
- for (size_t i = 0; i < num_packets; ++i) {
- size_t packet_index = i * packet_size;
- std::vector<uint8_t> bytes(packet_size);
- std::copy(buffer->data() + packet_index,
- buffer->data() + packet_index + packet_size, bytes.begin());
- packets[i].Swap(&bytes);
- }
+ // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
+ // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
+ // instead of copy.
+ uint32_t buffer_size =
+ std::accumulate(packets.begin(), packets.end(), 0u,
+ [](const uint32_t& a,
+ const UsbDeviceHandle::IsochronousPacket& packet) {
+ return a + packet.length;
+ });
+ std::vector<uint8_t> bytes(buffer_size);
+ std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
+ data.Swap(&bytes);
}
- callback->Run(mojo::ConvertTo<TransferStatus>(status), std::move(packets));
+ callback->Run(std::move(data),
+ mojo::Array<IsochronousPacketPtr>::From(packets));
}
void OnIsochronousTransferOut(
scoped_ptr<Device::IsochronousTransferOutCallback> callback,
- UsbTransferStatus status,
scoped_refptr<net::IOBuffer> buffer,
- size_t buffer_size) {
- callback->Run(mojo::ConvertTo<TransferStatus>(status));
+ const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
+ callback->Run(mojo::Array<IsochronousPacketPtr>::From(packets));
}
} // namespace
@@ -398,58 +416,46 @@ void DeviceImpl::GenericTransferOut(
void DeviceImpl::IsochronousTransferIn(
uint8_t endpoint_number,
- uint32_t num_packets,
- uint32_t packet_length,
+ mojo::Array<uint32_t> packet_lengths,
uint32_t timeout,
const IsochronousTransferInCallback& callback) {
if (!device_handle_) {
- callback.Run(TransferStatus::TRANSFER_ERROR,
- mojo::Array<mojo::Array<uint8_t>>());
+ callback.Run(mojo::Array<uint8_t>(),
+ BuildIsochronousPacketArray(std::move(packet_lengths),
+ TransferStatus::TRANSFER_ERROR));
return;
}
auto callback_ptr =
make_scoped_ptr(new IsochronousTransferInCallback(callback));
uint8_t endpoint_address = endpoint_number | 0x80;
- size_t transfer_size = static_cast<size_t>(num_packets) * packet_length;
- scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
- device_handle_->IsochronousTransfer(
- USB_DIRECTION_INBOUND, endpoint_address, buffer, transfer_size,
- num_packets, packet_length, timeout,
- base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr),
- packet_length));
+ device_handle_->IsochronousTransferIn(
+ endpoint_address, packet_lengths.storage(), timeout,
+ base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr)));
}
void DeviceImpl::IsochronousTransferOut(
uint8_t endpoint_number,
- mojo::Array<mojo::Array<uint8_t>> packets,
+ mojo::Array<uint8_t> data,
+ mojo::Array<uint32_t> packet_lengths,
uint32_t timeout,
const IsochronousTransferOutCallback& callback) {
if (!device_handle_) {
- callback.Run(TransferStatus::TRANSFER_ERROR);
+ callback.Run(BuildIsochronousPacketArray(std::move(packet_lengths),
+ TransferStatus::TRANSFER_ERROR));
return;
}
auto callback_ptr =
make_scoped_ptr(new IsochronousTransferOutCallback(callback));
uint8_t endpoint_address = endpoint_number;
- uint32_t packet_size = 0;
- for (size_t i = 0; i < packets.size(); ++i) {
- packet_size =
- std::max(packet_size, static_cast<uint32_t>(packets[i].size()));
- }
- size_t transfer_size = packet_size * packets.size();
- scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
- memset(buffer->data(), 0, transfer_size);
- for (size_t i = 0; i < packets.size(); ++i) {
- uint8_t* packet =
- reinterpret_cast<uint8_t*>(&buffer->data()[i * packet_size]);
- DCHECK_LE(packets[i].size(), static_cast<size_t>(packet_size));
- memcpy(packet, packets[i].storage().data(), packets[i].size());
+ scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
+ {
+ const std::vector<uint8_t>& storage = data.storage();
+ std::copy(storage.begin(), storage.end(), buffer->data());
}
- device_handle_->IsochronousTransfer(
- USB_DIRECTION_OUTBOUND, endpoint_address, buffer, transfer_size,
- static_cast<uint32_t>(packets.size()), packet_size, timeout,
+ device_handle_->IsochronousTransferOut(
+ endpoint_address, buffer, packet_lengths.storage(), timeout,
base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr)));
}
diff --git a/device/devices_app/usb/device_impl.h b/device/devices_app/usb/device_impl.h
index 5290fa7..2b438c8 100644
--- a/device/devices_app/usb/device_impl.h
+++ b/device/devices_app/usb/device_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef DEVICE_USB_DEVICE_IMPL_H_
-#define DEVICE_USB_DEVICE_IMPL_H_
+#ifndef DEVICE_DEVICES_APP_USB_DEVICE_IMPL_H_
+#define DEVICE_DEVICES_APP_USB_DEVICE_IMPL_H_
#include <stdint.h>
@@ -84,13 +84,13 @@ class DeviceImpl : public Device {
const GenericTransferOutCallback& callback) override;
void IsochronousTransferIn(
uint8_t endpoint_number,
- uint32_t num_packets,
- uint32_t packet_length,
+ mojo::Array<uint32_t> packet_lengths,
uint32_t timeout,
const IsochronousTransferInCallback& callback) override;
void IsochronousTransferOut(
uint8_t endpoint_number,
- mojo::Array<mojo::Array<uint8_t>> packets,
+ mojo::Array<uint8_t> data,
+ mojo::Array<uint32_t> packet_lengths,
uint32_t timeout,
const IsochronousTransferOutCallback& callback) override;
@@ -110,4 +110,4 @@ class DeviceImpl : public Device {
} // namespace usb
} // namespace device
-#endif // DEVICE_USB_DEVICE_IMPL_H_
+#endif // DEVICE_DEVICES_APP_USB_DEVICE_IMPL_H_
diff --git a/device/devices_app/usb/device_impl_unittest.cc b/device/devices_app/usb/device_impl_unittest.cc
index 87324d2..e5ee893 100644
--- a/device/devices_app/usb/device_impl_unittest.cc
+++ b/device/devices_app/usb/device_impl_unittest.cc
@@ -6,9 +6,12 @@
#include <stddef.h>
#include <stdint.h>
+
#include <map>
+#include <numeric>
#include <queue>
#include <set>
+#include <string>
#include <utility>
#include <vector>
@@ -34,7 +37,7 @@ namespace {
class ConfigBuilder {
public:
- ConfigBuilder(uint8_t value) { config_.configuration_value = value; }
+ explicit ConfigBuilder(uint8_t value) { config_.configuration_value = value; }
ConfigBuilder& AddInterface(uint8_t interface_number,
uint8_t alternate_setting,
@@ -102,21 +105,35 @@ void ExpectTransferInAndThen(TransferStatus expected_status,
continuation.Run();
}
-void ExpectPacketsAndThen(
- TransferStatus expected_status,
- const std::vector<std::vector<uint8_t>>& expected_packets,
- const base::Closure& continuation,
- TransferStatus actual_status,
- mojo::Array<mojo::Array<uint8_t>> actual_packets) {
- EXPECT_EQ(expected_status, actual_status);
+void ExpectPacketsOutAndThen(const std::vector<uint32_t>& expected_packets,
+ const base::Closure& continuation,
+ mojo::Array<IsochronousPacketPtr> actual_packets) {
ASSERT_EQ(expected_packets.size(), actual_packets.size());
for (size_t i = 0; i < expected_packets.size(); ++i) {
- EXPECT_EQ(expected_packets[i].size(), actual_packets[i].size())
- << "Packet sizes differ at index: " << i;
- for (size_t j = 0; j < expected_packets[i].size(); ++j) {
- EXPECT_EQ(expected_packets[i][j], actual_packets[i][j])
- << "Contents of packet " << i << " differ at index " << j;
- }
+ EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length)
+ << "Packet lengths differ at index: " << i;
+ EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status)
+ << "Packet at index " << i << " not completed.";
+ }
+ continuation.Run();
+}
+
+void ExpectPacketsInAndThen(const std::vector<uint8_t>& expected_bytes,
+ const std::vector<uint32_t>& expected_packets,
+ const base::Closure& continuation,
+ mojo::Array<uint8_t> actual_bytes,
+ mojo::Array<IsochronousPacketPtr> actual_packets) {
+ ASSERT_EQ(expected_packets.size(), actual_packets.size());
+ for (size_t i = 0; i < expected_packets.size(); ++i) {
+ EXPECT_EQ(expected_packets[i], actual_packets[i]->transferred_length)
+ << "Packet lengths differ at index: " << i;
+ EXPECT_EQ(TransferStatus::COMPLETED, actual_packets[i]->status)
+ << "Packet at index " << i << " not completed.";
+ }
+ ASSERT_EQ(expected_bytes.size(), actual_bytes.size());
+ for (size_t i = 0; i < expected_bytes.size(); ++i) {
+ EXPECT_EQ(expected_bytes[i], actual_bytes[i])
+ << "Contents differ at index: " << i;
}
continuation.Run();
}
@@ -186,8 +203,11 @@ class USBDeviceImplTest : public testing::Test {
.WillByDefault(Invoke(this, &USBDeviceImplTest::ControlTransfer));
ON_CALL(mock_handle(), GenericTransfer(_, _, _, _, _, _))
.WillByDefault(Invoke(this, &USBDeviceImplTest::GenericTransfer));
- ON_CALL(mock_handle(), IsochronousTransfer(_, _, _, _, _, _, _, _))
- .WillByDefault(Invoke(this, &USBDeviceImplTest::IsochronousTransfer));
+ ON_CALL(mock_handle(), IsochronousTransferIn(_, _, _, _))
+ .WillByDefault(Invoke(this, &USBDeviceImplTest::IsochronousTransferIn));
+ ON_CALL(mock_handle(), IsochronousTransferOut(_, _, _, _, _))
+ .WillByDefault(
+ Invoke(this, &USBDeviceImplTest::IsochronousTransferOut));
return proxy;
}
@@ -206,10 +226,24 @@ class USBDeviceImplTest : public testing::Test {
mock_inbound_data_.push(data);
}
+ void AddMockInboundPackets(
+ const std::vector<uint8_t>& data,
+ const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
+ mock_inbound_data_.push(data);
+ mock_inbound_packets_.push(packets);
+ }
+
void AddMockOutboundData(const std::vector<uint8_t>& data) {
mock_outbound_data_.push(data);
}
+ void AddMockOutboundPackets(
+ const std::vector<uint8_t>& data,
+ const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
+ mock_outbound_data_.push(data);
+ mock_outbound_packets_.push(packets);
+ }
+
private:
void OpenMockHandle(const UsbDevice::OpenCallback& callback) {
EXPECT_FALSE(is_device_open_);
@@ -336,18 +370,59 @@ class USBDeviceImplTest : public testing::Test {
OutboundTransfer(buffer, length, callback);
}
- void IsochronousTransfer(UsbEndpointDirection direction,
- uint8_t endpoint,
- scoped_refptr<net::IOBuffer> buffer,
- size_t length,
- unsigned int packets,
- unsigned int packet_length,
- unsigned int timeout,
- const UsbDeviceHandle::TransferCallback& callback) {
- if (direction == USB_DIRECTION_INBOUND)
- InboundTransfer(callback);
- else
- OutboundTransfer(buffer, length, callback);
+ void IsochronousTransferIn(
+ uint8_t endpoint_number,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const UsbDeviceHandle::IsochronousTransferCallback& callback) {
+ ASSERT_FALSE(mock_inbound_data_.empty());
+ const std::vector<uint8_t>& bytes = mock_inbound_data_.front();
+ size_t length = bytes.size();
+ scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(length);
+ std::copy(bytes.begin(), bytes.end(), buffer->data());
+ mock_inbound_data_.pop();
+
+ ASSERT_FALSE(mock_inbound_packets_.empty());
+ std::vector<UsbDeviceHandle::IsochronousPacket> packets =
+ mock_inbound_packets_.front();
+ ASSERT_EQ(packets.size(), packet_lengths.size());
+ for (size_t i = 0; i < packets.size(); ++i) {
+ EXPECT_EQ(packets[i].length, packet_lengths[i])
+ << "Packet lengths differ at index: " << i;
+ }
+ mock_inbound_packets_.pop();
+
+ callback.Run(buffer, packets);
+ }
+
+ void IsochronousTransferOut(
+ uint8_t endpoint_number,
+ scoped_refptr<net::IOBuffer> buffer,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const UsbDeviceHandle::IsochronousTransferCallback& callback) {
+ ASSERT_FALSE(mock_outbound_data_.empty());
+ const std::vector<uint8_t>& bytes = mock_outbound_data_.front();
+ size_t length =
+ std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
+ ASSERT_EQ(bytes.size(), length);
+ for (size_t i = 0; i < length; ++i) {
+ EXPECT_EQ(bytes[i], buffer->data()[i]) << "Contents differ at index: "
+ << i;
+ }
+ mock_outbound_data_.pop();
+
+ ASSERT_FALSE(mock_outbound_packets_.empty());
+ std::vector<UsbDeviceHandle::IsochronousPacket> packets =
+ mock_outbound_packets_.front();
+ ASSERT_EQ(packets.size(), packet_lengths.size());
+ for (size_t i = 0; i < packets.size(); ++i) {
+ EXPECT_EQ(packets[i].length, packet_lengths[i])
+ << "Packet lengths differ at index: " << i;
+ }
+ mock_outbound_packets_.pop();
+
+ callback.Run(buffer, packets);
}
scoped_ptr<base::MessageLoop> message_loop_;
@@ -361,6 +436,10 @@ class USBDeviceImplTest : public testing::Test {
std::queue<std::vector<uint8_t>> mock_inbound_data_;
std::queue<std::vector<uint8_t>> mock_outbound_data_;
+ std::queue<std::vector<UsbDeviceHandle::IsochronousPacket>>
+ mock_inbound_packets_;
+ std::queue<std::vector<UsbDeviceHandle::IsochronousPacket>>
+ mock_outbound_packets_;
std::set<uint8_t> claimed_interfaces_;
@@ -758,56 +837,52 @@ TEST_F(USBDeviceImplTest, IsochronousTransfer) {
loop.Run();
}
- std::string outbound_packet_data = "aaaaaaaabbbbbbbbccccccccdddddddd";
- std::vector<uint8_t> fake_outbound_packets(outbound_packet_data.size());
- std::copy(outbound_packet_data.begin(), outbound_packet_data.end(),
- fake_outbound_packets.begin());
+ std::vector<UsbDeviceHandle::IsochronousPacket> fake_packets(4);
+ for (size_t i = 0; i < fake_packets.size(); ++i) {
+ fake_packets[i].length = 8;
+ fake_packets[i].transferred_length = 8;
+ fake_packets[i].status = USB_TRANSFER_COMPLETED;
+ }
+ std::vector<uint32_t> fake_packet_lengths(4, 8);
+
+ std::vector<uint32_t> expected_transferred_lengths(4, 8);
+
+ std::string outbound_data = "aaaaaaaabbbbbbbbccccccccdddddddd";
+ std::vector<uint8_t> fake_outbound_data(outbound_data.size());
+ std::copy(outbound_data.begin(), outbound_data.end(),
+ fake_outbound_data.begin());
- std::string inbound_packet_data = "ddddddddccccccccbbbbbbbbaaaaaaaa";
- std::vector<uint8_t> fake_inbound_packets(inbound_packet_data.size());
- std::copy(inbound_packet_data.begin(), inbound_packet_data.end(),
- fake_inbound_packets.begin());
+ std::string inbound_data = "ddddddddccccccccbbbbbbbbaaaaaaaa";
+ std::vector<uint8_t> fake_inbound_data(inbound_data.size());
+ std::copy(inbound_data.begin(), inbound_data.end(),
+ fake_inbound_data.begin());
AddMockConfig(ConfigBuilder(1).AddInterface(7, 0, 1, 2, 3));
- AddMockOutboundData(fake_outbound_packets);
- AddMockInboundData(fake_inbound_packets);
+ AddMockOutboundPackets(fake_outbound_data, fake_packets);
+ AddMockInboundPackets(fake_inbound_data, fake_packets);
EXPECT_CALL(mock_handle(),
- IsochronousTransfer(USB_DIRECTION_OUTBOUND, 0x01, _,
- fake_outbound_packets.size(), 4, 8, 0, _));
+ IsochronousTransferOut(0x01, _, fake_packet_lengths, 0, _));
{
base::RunLoop loop;
- mojo::Array<mojo::Array<uint8_t>> packets =
- mojo::Array<mojo::Array<uint8_t>>::New(4);
- for (size_t i = 0; i < 4; ++i) {
- std::vector<uint8_t> bytes(8);
- std::copy(outbound_packet_data.begin() + i * 8,
- outbound_packet_data.begin() + i * 8 + 8, bytes.begin());
- packets[i].Swap(&bytes);
- }
device->IsochronousTransferOut(
- 1, std::move(packets), 0,
- base::Bind(&ExpectTransferStatusAndThen, TransferStatus::COMPLETED,
+ 1, mojo::Array<uint8_t>::From(fake_outbound_data),
+ mojo::Array<uint32_t>::From(fake_packet_lengths), 0,
+ base::Bind(&ExpectPacketsOutAndThen, expected_transferred_lengths,
loop.QuitClosure()));
loop.Run();
}
EXPECT_CALL(mock_handle(),
- IsochronousTransfer(USB_DIRECTION_INBOUND, 0x81, _,
- fake_inbound_packets.size(), 4, 8, 0, _));
+ IsochronousTransferIn(0x81, fake_packet_lengths, 0, _));
{
base::RunLoop loop;
- std::vector<std::vector<uint8_t>> packets(4);
- for (size_t i = 0; i < 4; ++i) {
- packets[i].resize(8);
- std::copy(inbound_packet_data.begin() + i * 8,
- inbound_packet_data.begin() + i * 8 + 8, packets[i].begin());
- }
device->IsochronousTransferIn(
- 1, 4, 8, 0, base::Bind(&ExpectPacketsAndThen, TransferStatus::COMPLETED,
- packets, loop.QuitClosure()));
+ 1, mojo::Array<uint32_t>::From(fake_packet_lengths), 0,
+ base::Bind(&ExpectPacketsInAndThen, fake_inbound_data,
+ expected_transferred_lengths, loop.QuitClosure()));
loop.Run();
}
diff --git a/device/devices_app/usb/public/interfaces/device.mojom b/device/devices_app/usb/public/interfaces/device.mojom
index 438aed1..25addb2 100644
--- a/device/devices_app/usb/public/interfaces/device.mojom
+++ b/device/devices_app/usb/public/interfaces/device.mojom
@@ -139,6 +139,12 @@ enum TransferStatus {
SHORT_PACKET,
};
+struct IsochronousPacket {
+ uint32 length;
+ uint32 transferred_length;
+ TransferStatus status;
+};
+
interface Device {
// Retrieve a DeviceInfo struct containing metadata about the device,
// including the set of all available device configurations.
@@ -238,22 +244,22 @@ interface Device {
// transfers can be initiated on the endpoint. The endpoint must be of type
// ISOCHRONOUS.
//
- // |packet_length| specifies the maximum expected number of bytes to receive
- // for each packet in this transfer. |num_packets| specifies the maximum total
- // number of packets to receive.
+ // |packet_lengths| specifies the maximum expected number of bytes to receive
+ // for each packet in this transfer.
//
// |timeout| specifies the request timeout in milliseconds. A timeout of 0
// indicates no timeout: the request will remain pending indefinitely until
// completed or otherwise terminated.
//
- // |packets| contains the set of packets received from the device, in order.
- // No received packet's size will exceed |packet_length|, and will be null
- // if |status| is neither COMPLETED, BABBLE, or SHORT_PACKET.
+ // |data| contains the data received from the device, if any. |packets|
+ // contains the status of each packet received from the device, in order. The
+ // length of the packet indicates its position in |data| while it's
+ // transferred length gives the amount of data actually received from the
+ // device.
IsochronousTransferIn(uint8 endpoint_number,
- uint32 num_packets,
- uint32 packet_length,
+ array<uint32> packet_lengths,
uint32 timeout)
- => (TransferStatus status, array<array<uint8>>? packets);
+ => (array<uint8>? data, array<IsochronousPacket> packets);
// Initiates an outbound isochronous transfer request on a specific endpoint.
// The interface to which |endpoint_number| belongs must be claimed, and the
@@ -261,14 +267,19 @@ interface Device {
// transfers can be initiated on the endpoint. The endpoint must be of type
// ISOCHRONOUS.
//
- // |packets| specifies the series of data packets to send to the device for
- // this transfer.
+ // |data| specifies the bytes to send to the device.
+ //
+ // |packet_lengths| specifies how |data| should be separated into packets when
+ // it is sent to the device.
//
// |timeout| specifies the request timeout in milliseconds. A timeout of 0
// indicates no timeout: the request will remain pending indefinitely until
// completed or otherwise terminated.
+
+ // |packets| contains the status of each packet sent to the device, in order.
IsochronousTransferOut(uint8 endpoint_number,
- array<array<uint8>> packets,
+ array<uint8> data,
+ array<uint32> packet_lengths,
uint32 timeout)
- => (TransferStatus status);
+ => (array<IsochronousPacket> packets);
};
diff --git a/device/devices_app/usb/type_converters.cc b/device/devices_app/usb/type_converters.cc
index e7b2ea6..709b0ca 100644
--- a/device/devices_app/usb/type_converters.cc
+++ b/device/devices_app/usb/type_converters.cc
@@ -267,4 +267,17 @@ TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice>::Convert(
return info;
}
+// static
+device::usb::IsochronousPacketPtr
+TypeConverter<device::usb::IsochronousPacketPtr,
+ device::UsbDeviceHandle::IsochronousPacket>::
+ Convert(const device::UsbDeviceHandle::IsochronousPacket& packet) {
+ device::usb::IsochronousPacketPtr info =
+ device::usb::IsochronousPacket::New();
+ info->length = packet.length;
+ info->transferred_length = packet.transferred_length;
+ info->status = mojo::ConvertTo<device::usb::TransferStatus>(packet.status);
+ return info;
+}
+
} // namespace mojo
diff --git a/device/devices_app/usb/type_converters.h b/device/devices_app/usb/type_converters.h
index 59c2f4c..15484ea 100644
--- a/device/devices_app/usb/type_converters.h
+++ b/device/devices_app/usb/type_converters.h
@@ -16,8 +16,9 @@
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/type_converter.h"
-// Type converters to convert objects between internal device/usb data types and
-// public Mojo interface data types.
+// Type converters to translate between internal device/usb data types and
+// public Mojo interface data types. This must be included by any source file
+// that uses these conversions explicitly or implicitly.
namespace device {
class UsbDevice;
@@ -121,6 +122,13 @@ struct TypeConverter<device::usb::DeviceInfoPtr, device::UsbDevice> {
static device::usb::DeviceInfoPtr Convert(const device::UsbDevice& device);
};
+template <>
+struct TypeConverter<device::usb::IsochronousPacketPtr,
+ device::UsbDeviceHandle::IsochronousPacket> {
+ static device::usb::IsochronousPacketPtr Convert(
+ const device::UsbDeviceHandle::IsochronousPacket& packet);
+};
+
} // namespace mojo
#endif // DEVICE_DEVICES_APP_USB_TYPE_CONVERTERS_H_
diff --git a/device/usb/mock_usb_device_handle.h b/device/usb/mock_usb_device_handle.h
index 372068c..26e6190 100644
--- a/device/usb/mock_usb_device_handle.h
+++ b/device/usb/mock_usb_device_handle.h
@@ -5,11 +5,12 @@
#ifndef DEVICE_USB_MOCK_USB_DEVICE_HANDLE_H_
#define DEVICE_USB_MOCK_USB_DEVICE_HANDLE_H_
-#include "device/usb/usb_device_handle.h"
-
#include <stddef.h>
#include <stdint.h>
+#include <vector>
+
+#include "device/usb/usb_device_handle.h"
#include "net/base/io_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,7 +18,7 @@ namespace device {
class MockUsbDeviceHandle : public UsbDeviceHandle {
public:
- MockUsbDeviceHandle(UsbDevice* device);
+ explicit MockUsbDeviceHandle(UsbDevice* device);
scoped_refptr<UsbDevice> GetDevice() const override;
MOCK_METHOD0(Close, void());
@@ -44,15 +45,17 @@ class MockUsbDeviceHandle : public UsbDeviceHandle {
size_t length,
unsigned int timeout,
const TransferCallback& callback));
- MOCK_METHOD8(IsochronousTransfer,
- void(UsbEndpointDirection direction,
- uint8_t endpoint,
+ MOCK_METHOD4(IsochronousTransferIn,
+ void(uint8_t endpoint,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback));
+ MOCK_METHOD5(IsochronousTransferOut,
+ void(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,
- const TransferCallback& callback));
+ const IsochronousTransferCallback& callback));
MOCK_METHOD6(GenericTransfer,
void(UsbEndpointDirection direction,
uint8_t endpoint,
diff --git a/device/usb/usb_device_handle.h b/device/usb/usb_device_handle.h
index a97dddc..b206cf1 100644
--- a/device/usb/usb_device_handle.h
+++ b/device/usb/usb_device_handle.h
@@ -40,9 +40,18 @@ enum UsbTransferStatus {
// UsbDeviceHandle class provides basic I/O related functionalities.
class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
public:
+ struct IsochronousPacket {
+ uint32_t length;
+ uint32_t transferred_length;
+ UsbTransferStatus status;
+ };
+
using ResultCallback = base::Callback<void(bool)>;
using TransferCallback = base::Callback<
void(UsbTransferStatus, scoped_refptr<net::IOBuffer>, size_t)>;
+ using IsochronousTransferCallback =
+ base::Callback<void(scoped_refptr<net::IOBuffer>,
+ const std::vector<IsochronousPacket>& packets)>;
enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
@@ -81,17 +90,21 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
unsigned int timeout,
const TransferCallback& callback) = 0;
- virtual void IsochronousTransfer(UsbEndpointDirection direction,
- uint8_t endpoint,
- scoped_refptr<net::IOBuffer> buffer,
- size_t length,
- unsigned int packets,
- unsigned int packet_length,
- unsigned int timeout,
- const TransferCallback& callback) = 0;
+ virtual void IsochronousTransferIn(
+ uint8_t endpoint_number,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback) = 0;
+
+ virtual void IsochronousTransferOut(
+ uint8_t endpoint_number,
+ scoped_refptr<net::IOBuffer> buffer,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback) = 0;
virtual void GenericTransfer(UsbEndpointDirection direction,
- uint8_t endpoint,
+ uint8_t endpoint_number,
scoped_refptr<net::IOBuffer> buffer,
size_t length,
unsigned int timeout,
@@ -109,6 +122,7 @@ class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
virtual ~UsbDeviceHandle();
+ private:
DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
};
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index 338af16..fa4c085 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));
}
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h
index 7d10e42..ce2daff 100644
--- a/device/usb/usb_device_handle_impl.h
+++ b/device/usb/usb_device_handle_impl.h
@@ -71,14 +71,18 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle {
unsigned int timeout,
const TransferCallback& callback) override;
- void IsochronousTransfer(UsbEndpointDirection direction,
- uint8_t endpoint_number,
- scoped_refptr<net::IOBuffer> buffer,
- size_t length,
- unsigned int packets,
- unsigned int packet_length,
- unsigned int timeout,
- const TransferCallback& callback) override;
+ void IsochronousTransferIn(
+ uint8_t endpoint,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback) override;
+
+ void IsochronousTransferOut(
+ uint8_t endpoint,
+ scoped_refptr<net::IOBuffer> buffer,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ const IsochronousTransferCallback& callback) override;
void GenericTransfer(UsbEndpointDirection direction,
uint8_t endpoint_number,
@@ -149,15 +153,20 @@ class UsbDeviceHandleImpl : public UsbDeviceHandle {
scoped_refptr<base::TaskRunner> callback_task_runner,
const TransferCallback& callback);
- void IsochronousTransferInternal(
+ void IsochronousTransferInInternal(
+ uint8_t endpoint_address,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ scoped_refptr<base::TaskRunner> callback_task_runner,
+ const IsochronousTransferCallback& callback);
+
+ void IsochronousTransferOutInternal(
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);
void GenericTransferInternal(
uint8_t endpoint_address,