| 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 |