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