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 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue()); | 463 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue()); |
462 transfer_info->SetInteger(kResultCodeKey, status); | 464 transfer_info->SetInteger(kResultCodeKey, status); |
463 transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer( | 465 transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer( |
464 data->data(), length)); | 466 data->data(), length)); |
465 | 467 |
466 if (status == device::USB_TRANSFER_COMPLETED) { | 468 if (status == device::USB_TRANSFER_COMPLETED) { |
467 Respond(OneArgument(std::move(transfer_info))); | 469 Respond(OneArgument(std::move(transfer_info))); |
468 } else { | 470 } else { |
469 scoped_ptr<base::ListValue> error_args(new base::ListValue()); | 471 scoped_ptr<base::ListValue> error_args(new base::ListValue()); |
470 error_args->Append(std::move(transfer_info)); | 472 error_args->Append(std::move(transfer_info)); |
471 // Returning arguments with an error is wrong but we're stuck with it. | 473 // Using ErrorWithArguments is discouraged but required to provide the |
| 474 // detailed transfer info as the transfer may have partially succeeded. |
472 Respond(ErrorWithArguments(std::move(error_args), | 475 Respond(ErrorWithArguments(std::move(error_args), |
473 ConvertTransferStatusToApi(status))); | 476 ConvertTransferStatusToApi(status))); |
474 } | 477 } |
475 } | 478 } |
476 | 479 |
477 UsbFindDevicesFunction::UsbFindDevicesFunction() { | 480 UsbFindDevicesFunction::UsbFindDevicesFunction() { |
478 } | 481 } |
479 | 482 |
480 UsbFindDevicesFunction::~UsbFindDevicesFunction() { | 483 UsbFindDevicesFunction::~UsbFindDevicesFunction() { |
481 } | 484 } |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 GetDeviceHandle(parameters->handle); | 1130 GetDeviceHandle(parameters->handle); |
1128 if (!device_handle.get()) { | 1131 if (!device_handle.get()) { |
1129 return RespondNow(Error(kErrorNoConnection)); | 1132 return RespondNow(Error(kErrorNoConnection)); |
1130 } | 1133 } |
1131 | 1134 |
1132 const IsochronousTransferInfo& transfer = parameters->transfer_info; | 1135 const IsochronousTransferInfo& transfer = parameters->transfer_info; |
1133 const GenericTransferInfo& generic_transfer = transfer.transfer_info; | 1136 const GenericTransferInfo& generic_transfer = transfer.transfer_info; |
1134 size_t size = 0; | 1137 size_t size = 0; |
1135 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND; | 1138 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND; |
1136 | 1139 |
1137 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) { | 1140 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) |
1138 return RespondNow(Error(kErrorConvertDirection)); | 1141 return RespondNow(Error(kErrorConvertDirection)); |
1139 } | |
1140 | 1142 |
1141 if (!GetTransferSize(generic_transfer, &size)) { | 1143 if (!GetTransferSize(generic_transfer, &size)) |
1142 return RespondNow(Error(kErrorInvalidTransferLength)); | 1144 return RespondNow(Error(kErrorInvalidTransferLength)); |
1143 } | |
1144 | 1145 |
1145 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) { | 1146 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) |
1146 return RespondNow(Error(kErrorInvalidNumberOfPackets)); | 1147 return RespondNow(Error(kErrorInvalidNumberOfPackets)); |
1147 } | 1148 size_t packets = transfer.packets; |
1148 | 1149 |
1149 unsigned int packets = transfer.packets; | |
1150 if (transfer.packet_length < 0 || | 1150 if (transfer.packet_length < 0 || |
1151 transfer.packet_length >= kMaxPacketLength) { | 1151 transfer.packet_length >= kMaxPacketLength) { |
1152 return RespondNow(Error(kErrorInvalidPacketLength)); | 1152 return RespondNow(Error(kErrorInvalidPacketLength)); |
1153 } | 1153 } |
1154 | 1154 |
1155 unsigned int packet_length = transfer.packet_length; | 1155 size_t total_length = packets * transfer.packet_length; |
1156 const uint64_t total_length = packets * packet_length; | 1156 if (packets > size || total_length > size) |
1157 if (packets > size || total_length > size) { | |
1158 return RespondNow(Error(kErrorTransferLength)); | 1157 return RespondNow(Error(kErrorTransferLength)); |
| 1158 std::vector<uint32_t> packet_lengths(packets, transfer.packet_length); |
| 1159 |
| 1160 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0; |
| 1161 if (timeout < 0) |
| 1162 return RespondNow(Error(kErrorInvalidTimeout)); |
| 1163 |
| 1164 if (direction == device::USB_DIRECTION_INBOUND) { |
| 1165 device_handle->IsochronousTransferIn( |
| 1166 generic_transfer.endpoint, packet_lengths, timeout, |
| 1167 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); |
| 1168 } else { |
| 1169 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( |
| 1170 generic_transfer, direction, transfer.packets * transfer.packet_length); |
| 1171 if (!buffer.get()) |
| 1172 return RespondNow(Error(kErrorMalformedParameters)); |
| 1173 |
| 1174 device_handle->IsochronousTransferOut( |
| 1175 generic_transfer.endpoint, buffer.get(), packet_lengths, timeout, |
| 1176 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); |
| 1177 } |
| 1178 return RespondLater(); |
| 1179 } |
| 1180 |
| 1181 void UsbIsochronousTransferFunction::OnCompleted( |
| 1182 scoped_refptr<net::IOBuffer> data, |
| 1183 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { |
| 1184 size_t length = std::accumulate( |
| 1185 packets.begin(), packets.end(), 0, |
| 1186 [](const size_t& a, const UsbDeviceHandle::IsochronousPacket& packet) { |
| 1187 return a + packet.transferred_length; |
| 1188 }); |
| 1189 scoped_ptr<char[]> buffer(new char[length]); |
| 1190 |
| 1191 UsbTransferStatus status = device::USB_TRANSFER_COMPLETED; |
| 1192 size_t buffer_offset = 0; |
| 1193 size_t data_offset = 0; |
| 1194 for (const auto& packet : packets) { |
| 1195 // Capture the error status of the first unsuccessful packet. |
| 1196 if (status == device::USB_TRANSFER_COMPLETED && |
| 1197 packet.status != device::USB_TRANSFER_COMPLETED) { |
| 1198 status = packet.status; |
| 1199 } |
| 1200 |
| 1201 memcpy(&buffer[buffer_offset], data->data() + data_offset, |
| 1202 packet.transferred_length); |
| 1203 buffer_offset += packet.transferred_length; |
| 1204 data_offset += packet.length; |
1159 } | 1205 } |
1160 | 1206 |
1161 scoped_refptr<net::IOBuffer> buffer = | 1207 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue()); |
1162 CreateBufferForTransfer(generic_transfer, direction, size); | 1208 transfer_info->SetInteger(kResultCodeKey, status); |
1163 if (!buffer.get()) { | 1209 transfer_info->Set(kDataKey, |
1164 return RespondNow(Error(kErrorMalformedParameters)); | 1210 new base::BinaryValue(std::move(buffer), length)); |
| 1211 if (status == device::USB_TRANSFER_COMPLETED) { |
| 1212 Respond(OneArgument(std::move(transfer_info))); |
| 1213 } else { |
| 1214 scoped_ptr<base::ListValue> error_args(new base::ListValue()); |
| 1215 error_args->Append(std::move(transfer_info)); |
| 1216 // Using ErrorWithArguments is discouraged but required to provide the |
| 1217 // detailed transfer info as the transfer may have partially succeeded. |
| 1218 Respond(ErrorWithArguments(std::move(error_args), |
| 1219 ConvertTransferStatusToApi(status))); |
1165 } | 1220 } |
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 } | 1221 } |
1178 | 1222 |
1179 UsbResetDeviceFunction::UsbResetDeviceFunction() { | 1223 UsbResetDeviceFunction::UsbResetDeviceFunction() { |
1180 } | 1224 } |
1181 | 1225 |
1182 UsbResetDeviceFunction::~UsbResetDeviceFunction() { | 1226 UsbResetDeviceFunction::~UsbResetDeviceFunction() { |
1183 } | 1227 } |
1184 | 1228 |
1185 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() { | 1229 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() { |
1186 parameters_ = ResetDevice::Params::Create(*args_); | 1230 parameters_ = ResetDevice::Params::Create(*args_); |
(...skipping 16 matching lines...) Expand all Loading... |
1203 } else { | 1247 } else { |
1204 scoped_refptr<UsbDeviceHandle> device_handle = | 1248 scoped_refptr<UsbDeviceHandle> device_handle = |
1205 GetDeviceHandle(parameters_->handle); | 1249 GetDeviceHandle(parameters_->handle); |
1206 if (device_handle.get()) { | 1250 if (device_handle.get()) { |
1207 device_handle->Close(); | 1251 device_handle->Close(); |
1208 } | 1252 } |
1209 ReleaseDeviceHandle(parameters_->handle); | 1253 ReleaseDeviceHandle(parameters_->handle); |
1210 | 1254 |
1211 scoped_ptr<base::ListValue> error_args(new base::ListValue()); | 1255 scoped_ptr<base::ListValue> error_args(new base::ListValue()); |
1212 error_args->AppendBoolean(false); | 1256 error_args->AppendBoolean(false); |
1213 // Returning arguments with an error is wrong but we're stuck with it. | 1257 // Using ErrorWithArguments is discouraged but required to maintain |
| 1258 // compatibility with existing applications. |
1214 Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice)); | 1259 Respond(ErrorWithArguments(std::move(error_args), kErrorResetDevice)); |
1215 } | 1260 } |
1216 } | 1261 } |
1217 | 1262 |
1218 } // namespace extensions | 1263 } // namespace extensions |
OLD | NEW |