Chromium Code Reviews| 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 |