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

Unified Diff: extensions/browser/api/usb/usb_api.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 | « extensions/browser/api/usb/usb_api.h ('k') | extensions/browser/api/usb/usb_apitest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/browser/api/usb/usb_api.cc
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index 16710ddabbba41f9b003f5c6fed7d5b4cd442720..303523964fe927b17fff7499a5e2ef08532c86a5 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -4,6 +4,8 @@
#include "extensions/browser/api/usb/usb_api.h"
+#include <algorithm>
+#include <numeric>
#include <string>
#include <utility>
#include <vector>
@@ -468,7 +470,8 @@ void UsbTransferFunction::OnCompleted(UsbTransferStatus status,
} else {
scoped_ptr<base::ListValue> error_args(new base::ListValue());
error_args->Append(std::move(transfer_info));
- // Returning arguments with an error is wrong but we're stuck with it.
+ // Using ErrorWithArguments is discouraged but required to provide the
+ // detailed transfer info as the transfer may have partially succeeded.
Respond(ErrorWithArguments(std::move(error_args),
ConvertTransferStatusToApi(status)));
}
@@ -1134,48 +1137,89 @@ ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() {
size_t size = 0;
UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
- if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) {
+ if (!ConvertDirectionFromApi(generic_transfer.direction, &direction))
return RespondNow(Error(kErrorConvertDirection));
- }
- if (!GetTransferSize(generic_transfer, &size)) {
+ if (!GetTransferSize(generic_transfer, &size))
return RespondNow(Error(kErrorInvalidTransferLength));
- }
- if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
+ if (transfer.packets < 0 || transfer.packets >= kMaxPackets)
return RespondNow(Error(kErrorInvalidNumberOfPackets));
- }
+ size_t packets = transfer.packets;
- unsigned int packets = transfer.packets;
if (transfer.packet_length < 0 ||
transfer.packet_length >= kMaxPacketLength) {
return RespondNow(Error(kErrorInvalidPacketLength));
}
- unsigned int packet_length = transfer.packet_length;
- const uint64_t total_length = packets * packet_length;
- if (packets > size || total_length > size) {
+ size_t total_length = packets * transfer.packet_length;
+ if (packets > size || total_length > size)
return RespondNow(Error(kErrorTransferLength));
- }
-
- scoped_refptr<net::IOBuffer> buffer =
- CreateBufferForTransfer(generic_transfer, direction, size);
- if (!buffer.get()) {
- return RespondNow(Error(kErrorMalformedParameters));
- }
+ std::vector<uint32_t> packet_lengths(packets, transfer.packet_length);
int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
- if (timeout < 0) {
+ if (timeout < 0)
return RespondNow(Error(kErrorInvalidTimeout));
- }
- device_handle->IsochronousTransfer(
- direction, generic_transfer.endpoint, buffer.get(), size, packets,
- packet_length, timeout,
- base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
+ if (direction == device::USB_DIRECTION_INBOUND) {
+ device_handle->IsochronousTransferIn(
+ generic_transfer.endpoint, packet_lengths, timeout,
+ base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
+ } else {
+ scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
+ generic_transfer, direction, transfer.packets * transfer.packet_length);
+ if (!buffer.get())
+ return RespondNow(Error(kErrorMalformedParameters));
+
+ device_handle->IsochronousTransferOut(
+ generic_transfer.endpoint, buffer.get(), packet_lengths, timeout,
+ base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
+ }
return RespondLater();
}
+void UsbIsochronousTransferFunction::OnCompleted(
+ scoped_refptr<net::IOBuffer> data,
+ const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
+ size_t length = std::accumulate(
+ packets.begin(), packets.end(), 0,
+ [](const size_t& a, const UsbDeviceHandle::IsochronousPacket& packet) {
+ return a + packet.transferred_length;
+ });
+ scoped_ptr<char[]> buffer(new char[length]);
+
+ UsbTransferStatus status = device::USB_TRANSFER_COMPLETED;
+ size_t buffer_offset = 0;
+ size_t data_offset = 0;
+ for (const auto& packet : packets) {
+ // Capture the error status of the first unsuccessful packet.
+ if (status == device::USB_TRANSFER_COMPLETED &&
+ packet.status != device::USB_TRANSFER_COMPLETED) {
+ status = packet.status;
+ }
+
+ memcpy(&buffer[buffer_offset], data->data() + data_offset,
+ packet.transferred_length);
+ buffer_offset += packet.transferred_length;
+ data_offset += packet.length;
+ }
+
+ scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue());
+ transfer_info->SetInteger(kResultCodeKey, status);
+ transfer_info->Set(kDataKey,
+ new base::BinaryValue(std::move(buffer), length));
+ if (status == device::USB_TRANSFER_COMPLETED) {
+ Respond(OneArgument(std::move(transfer_info)));
+ } else {
+ scoped_ptr<base::ListValue> error_args(new base::ListValue());
+ error_args->Append(std::move(transfer_info));
+ // Using ErrorWithArguments is discouraged but required to provide the
+ // detailed transfer info as the transfer may have partially succeeded.
+ Respond(ErrorWithArguments(std::move(error_args),
+ ConvertTransferStatusToApi(status)));
+ }
+}
+
UsbResetDeviceFunction::UsbResetDeviceFunction() {
}
@@ -1210,7 +1254,8 @@ void UsbResetDeviceFunction::OnComplete(bool success) {
scoped_ptr<base::ListValue> error_args(new base::ListValue());
error_args->AppendBoolean(false);
- // Returning arguments with an error is wrong but we're stuck with it.
+ // Using ErrorWithArguments is discouraged but required to maintain
+ // compatibility with existing applications.
Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice));
}
}
« no previous file with comments | « extensions/browser/api/usb/usb_api.h ('k') | extensions/browser/api/usb/usb_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698