OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/api/usb/usb_api.h" | 5 #include "extensions/browser/api/usb/usb_api.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <numeric> | |
7 #include <string> | 9 #include <string> |
8 #include <utility> | 10 #include <utility> |
9 #include <vector> | 11 #include <vector> |
10 | 12 |
11 #include "base/barrier_closure.h" | 13 #include "base/barrier_closure.h" |
12 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
13 #include "device/core/device_client.h" | 15 #include "device/core/device_client.h" |
14 #include "device/usb/usb_descriptors.h" | 16 #include "device/usb/usb_descriptors.h" |
15 #include "device/usb/usb_device_handle.h" | 17 #include "device/usb/usb_device_handle.h" |
16 #include "device/usb/usb_service.h" | 18 #include "device/usb/usb_service.h" |
(...skipping 1110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1127 GetDeviceHandle(parameters->handle); | 1129 GetDeviceHandle(parameters->handle); |
1128 if (!device_handle.get()) { | 1130 if (!device_handle.get()) { |
1129 return RespondNow(Error(kErrorNoConnection)); | 1131 return RespondNow(Error(kErrorNoConnection)); |
1130 } | 1132 } |
1131 | 1133 |
1132 const IsochronousTransferInfo& transfer = parameters->transfer_info; | 1134 const IsochronousTransferInfo& transfer = parameters->transfer_info; |
1133 const GenericTransferInfo& generic_transfer = transfer.transfer_info; | 1135 const GenericTransferInfo& generic_transfer = transfer.transfer_info; |
1134 size_t size = 0; | 1136 size_t size = 0; |
1135 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND; | 1137 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND; |
1136 | 1138 |
1137 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) { | 1139 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) |
1138 return RespondNow(Error(kErrorConvertDirection)); | 1140 return RespondNow(Error(kErrorConvertDirection)); |
1139 } | |
1140 | 1141 |
1141 if (!GetTransferSize(generic_transfer, &size)) { | 1142 if (!GetTransferSize(generic_transfer, &size)) |
1142 return RespondNow(Error(kErrorInvalidTransferLength)); | 1143 return RespondNow(Error(kErrorInvalidTransferLength)); |
1143 } | |
1144 | 1144 |
1145 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) { | 1145 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) |
1146 return RespondNow(Error(kErrorInvalidNumberOfPackets)); | 1146 return RespondNow(Error(kErrorInvalidNumberOfPackets)); |
1147 } | 1147 size_t packets = transfer.packets; |
1148 | 1148 |
1149 unsigned int packets = transfer.packets; | |
1150 if (transfer.packet_length < 0 || | 1149 if (transfer.packet_length < 0 || |
1151 transfer.packet_length >= kMaxPacketLength) { | 1150 transfer.packet_length >= kMaxPacketLength) { |
1152 return RespondNow(Error(kErrorInvalidPacketLength)); | 1151 return RespondNow(Error(kErrorInvalidPacketLength)); |
1153 } | 1152 } |
1154 | 1153 |
1155 unsigned int packet_length = transfer.packet_length; | 1154 size_t total_length = packets * transfer.packet_length; |
1156 const uint64_t total_length = packets * packet_length; | 1155 if (packets > size || total_length > size) |
1157 if (packets > size || total_length > size) { | |
1158 return RespondNow(Error(kErrorTransferLength)); | 1156 return RespondNow(Error(kErrorTransferLength)); |
1157 std::vector<uint32_t> packet_lengths(packets, transfer.packet_length); | |
1158 | |
1159 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0; | |
1160 if (timeout < 0) | |
1161 return RespondNow(Error(kErrorInvalidTimeout)); | |
1162 | |
1163 if (direction == device::USB_DIRECTION_INBOUND) { | |
1164 device_handle->IsochronousTransferIn( | |
1165 generic_transfer.endpoint, packet_lengths, timeout, | |
1166 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); | |
1167 } else { | |
1168 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
1169 generic_transfer, direction, transfer.packets * transfer.packet_length); | |
1170 if (!buffer.get()) | |
1171 return RespondNow(Error(kErrorMalformedParameters)); | |
1172 | |
1173 device_handle->IsochronousTransferOut( | |
1174 generic_transfer.endpoint, buffer.get(), packet_lengths, timeout, | |
1175 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); | |
1176 } | |
1177 return RespondLater(); | |
1178 } | |
1179 | |
1180 void UsbIsochronousTransferFunction::OnCompleted( | |
1181 scoped_refptr<net::IOBuffer> data, | |
1182 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { | |
1183 size_t length = std::accumulate( | |
1184 packets.begin(), packets.end(), 0, | |
1185 [](const size_t& a, const UsbDeviceHandle::IsochronousPacket& packet) { | |
1186 return a + packet.transferred_length; | |
1187 }); | |
1188 scoped_ptr<char[]> buffer(new char[length]); | |
1189 | |
1190 UsbTransferStatus status = device::USB_TRANSFER_COMPLETED; | |
1191 size_t buffer_offset = 0; | |
1192 size_t data_offset = 0; | |
1193 for (const auto& packet : packets) { | |
scheib
2016/01/27 01:42:13
test for an example of an error here.
Reilly Grant (use Gerrit)
2016/01/29 23:25:36
Done.
| |
1194 // Capture the error status of the first unsuccessful packet. | |
1195 if (status == device::USB_TRANSFER_COMPLETED && | |
1196 packet.status != device::USB_TRANSFER_COMPLETED) { | |
1197 status = packet.status; | |
1198 } | |
1199 | |
1200 memcpy(&buffer[buffer_offset], data->data() + data_offset, | |
scheib
2016/01/27 01:42:13
Is there test coverage for this API bindings code?
Reilly Grant (use Gerrit)
2016/01/29 23:25:36
Yes, in //extensions/test/data/api_test/usb.
| |
1201 packet.transferred_length); | |
1202 buffer_offset += packet.transferred_length; | |
1203 data_offset += packet.length; | |
1159 } | 1204 } |
1160 | 1205 |
1161 scoped_refptr<net::IOBuffer> buffer = | 1206 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue()); |
1162 CreateBufferForTransfer(generic_transfer, direction, size); | 1207 transfer_info->SetInteger(kResultCodeKey, status); |
1163 if (!buffer.get()) { | 1208 transfer_info->Set(kDataKey, |
1164 return RespondNow(Error(kErrorMalformedParameters)); | 1209 new base::BinaryValue(std::move(buffer), length)); |
1210 if (status == device::USB_TRANSFER_COMPLETED) { | |
1211 Respond(OneArgument(std::move(transfer_info))); | |
1212 } else { | |
1213 scoped_ptr<base::ListValue> error_args(new base::ListValue()); | |
1214 error_args->Append(std::move(transfer_info)); | |
1215 // Returning arguments with an error is wrong but we're stuck with it. | |
scheib
2016/01/27 01:42:13
'wrong'? why? deprecated?
Reilly Grant (use Gerrit)
2016/01/29 23:25:36
It wasn't supposed to work but it does and some AP
scheib
2016/01/30 22:01:06
Please explain it in the code comment.
| |
1216 Respond(ErrorWithArguments(std::move(error_args), | |
1217 ConvertTransferStatusToApi(status))); | |
1165 } | 1218 } |
1166 | |
1167 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0; | |
1168 if (timeout < 0) { | |
1169 return RespondNow(Error(kErrorInvalidTimeout)); | |
1170 } | |
1171 | |
1172 device_handle->IsochronousTransfer( | |
1173 direction, generic_transfer.endpoint, buffer.get(), size, packets, | |
1174 packet_length, timeout, | |
1175 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); | |
1176 return RespondLater(); | |
1177 } | 1219 } |
1178 | 1220 |
1179 UsbResetDeviceFunction::UsbResetDeviceFunction() { | 1221 UsbResetDeviceFunction::UsbResetDeviceFunction() { |
1180 } | 1222 } |
1181 | 1223 |
1182 UsbResetDeviceFunction::~UsbResetDeviceFunction() { | 1224 UsbResetDeviceFunction::~UsbResetDeviceFunction() { |
1183 } | 1225 } |
1184 | 1226 |
1185 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() { | 1227 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() { |
1186 parameters_ = ResetDevice::Params::Create(*args_); | 1228 parameters_ = ResetDevice::Params::Create(*args_); |
(...skipping 22 matching lines...) Expand all Loading... | |
1209 ReleaseDeviceHandle(parameters_->handle); | 1251 ReleaseDeviceHandle(parameters_->handle); |
1210 | 1252 |
1211 scoped_ptr<base::ListValue> error_args(new base::ListValue()); | 1253 scoped_ptr<base::ListValue> error_args(new base::ListValue()); |
1212 error_args->AppendBoolean(false); | 1254 error_args->AppendBoolean(false); |
1213 // Returning arguments with an error is wrong but we're stuck with it. | 1255 // Returning arguments with an error is wrong but we're stuck with it. |
1214 Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice)); | 1256 Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice)); |
1215 } | 1257 } |
1216 } | 1258 } |
1217 | 1259 |
1218 } // namespace extensions | 1260 } // namespace extensions |
OLD | NEW |