| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/extensions/api/usb/usb_api.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/message_loop/message_loop_proxy.h" | |
| 12 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" | |
| 13 #include "chrome/common/extensions/api/usb.h" | |
| 14 #include "components/usb_service/usb_device_handle.h" | |
| 15 #include "components/usb_service/usb_service.h" | |
| 16 #include "extensions/browser/extension_system.h" | |
| 17 #include "extensions/common/permissions/permissions_data.h" | |
| 18 #include "extensions/common/permissions/usb_device_permission.h" | |
| 19 | |
| 20 namespace usb = extensions::api::usb; | |
| 21 namespace BulkTransfer = usb::BulkTransfer; | |
| 22 namespace ClaimInterface = usb::ClaimInterface; | |
| 23 namespace CloseDevice = usb::CloseDevice; | |
| 24 namespace ControlTransfer = usb::ControlTransfer; | |
| 25 namespace FindDevices = usb::FindDevices; | |
| 26 namespace GetDevices = usb::GetDevices; | |
| 27 namespace InterruptTransfer = usb::InterruptTransfer; | |
| 28 namespace IsochronousTransfer = usb::IsochronousTransfer; | |
| 29 namespace ListInterfaces = usb::ListInterfaces; | |
| 30 namespace OpenDevice = usb::OpenDevice; | |
| 31 namespace ReleaseInterface = usb::ReleaseInterface; | |
| 32 namespace RequestAccess = usb::RequestAccess; | |
| 33 namespace ResetDevice = usb::ResetDevice; | |
| 34 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting; | |
| 35 | |
| 36 using content::BrowserThread; | |
| 37 using std::string; | |
| 38 using std::vector; | |
| 39 using usb::ControlTransferInfo; | |
| 40 using usb::ConnectionHandle; | |
| 41 using usb::Device; | |
| 42 using usb::Direction; | |
| 43 using usb::EndpointDescriptor; | |
| 44 using usb::GenericTransferInfo; | |
| 45 using usb::InterfaceDescriptor; | |
| 46 using usb::IsochronousTransferInfo; | |
| 47 using usb::Recipient; | |
| 48 using usb::RequestType; | |
| 49 using usb::SynchronizationType; | |
| 50 using usb::TransferType; | |
| 51 using usb::UsageType; | |
| 52 using usb_service::UsbConfigDescriptor; | |
| 53 using usb_service::UsbDevice; | |
| 54 using usb_service::UsbDeviceHandle; | |
| 55 using usb_service::UsbEndpointDescriptor; | |
| 56 using usb_service::UsbEndpointDirection; | |
| 57 using usb_service::UsbInterfaceAltSettingDescriptor; | |
| 58 using usb_service::UsbInterfaceDescriptor; | |
| 59 using usb_service::UsbService; | |
| 60 using usb_service::UsbSynchronizationType; | |
| 61 using usb_service::UsbTransferStatus; | |
| 62 using usb_service::UsbTransferType; | |
| 63 using usb_service::UsbUsageType; | |
| 64 | |
| 65 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector; | |
| 66 typedef scoped_ptr<DeviceVector> ScopedDeviceVector; | |
| 67 | |
| 68 namespace { | |
| 69 | |
| 70 const char kDataKey[] = "data"; | |
| 71 const char kResultCodeKey[] = "resultCode"; | |
| 72 | |
| 73 const char kErrorInitService[] = "Failed to initialize USB service."; | |
| 74 | |
| 75 const char kErrorOpen[] = "Failed to open device."; | |
| 76 const char kErrorCancelled[] = "Transfer was cancelled."; | |
| 77 const char kErrorDisconnect[] = "Device disconnected."; | |
| 78 const char kErrorGeneric[] = "Transfer failed."; | |
| 79 #if !defined(OS_CHROMEOS) | |
| 80 const char kErrorNotSupported[] = "Not supported on this platform."; | |
| 81 #endif | |
| 82 const char kErrorOverflow[] = "Inbound transfer overflow."; | |
| 83 const char kErrorStalled[] = "Transfer stalled."; | |
| 84 const char kErrorTimeout[] = "Transfer timed out."; | |
| 85 const char kErrorTransferLength[] = "Transfer length is insufficient."; | |
| 86 | |
| 87 const char kErrorCannotListInterfaces[] = "Error listing interfaces."; | |
| 88 const char kErrorCannotClaimInterface[] = "Error claiming interface."; | |
| 89 const char kErrorCannotReleaseInterface[] = "Error releasing interface."; | |
| 90 const char kErrorCannotSetInterfaceAlternateSetting[] = | |
| 91 "Error setting alternate interface setting."; | |
| 92 const char kErrorConvertDirection[] = "Invalid transfer direction."; | |
| 93 const char kErrorConvertRecipient[] = "Invalid transfer recipient."; | |
| 94 const char kErrorConvertRequestType[] = "Invalid request type."; | |
| 95 const char kErrorConvertSynchronizationType[] = "Invalid synchronization type"; | |
| 96 const char kErrorConvertTransferType[] = "Invalid endpoint type."; | |
| 97 const char kErrorConvertUsageType[] = "Invalid usage type."; | |
| 98 const char kErrorMalformedParameters[] = "Error parsing parameters."; | |
| 99 const char kErrorNoDevice[] = "No such device."; | |
| 100 const char kErrorPermissionDenied[] = | |
| 101 "Permission to access device was denied"; | |
| 102 const char kErrorInvalidTransferLength[] = | |
| 103 "Transfer length must be a positive number less than 104,857,600."; | |
| 104 const char kErrorInvalidNumberOfPackets[] = | |
| 105 "Number of packets must be a positive number less than 4,194,304."; | |
| 106 const char kErrorInvalidPacketLength[] = "Packet length must be a " | |
| 107 "positive number less than 65,536."; | |
| 108 const char kErrorResetDevice[] = | |
| 109 "Error resetting the device. The device has been closed."; | |
| 110 | |
| 111 const size_t kMaxTransferLength = 100 * 1024 * 1024; | |
| 112 const int kMaxPackets = 4 * 1024 * 1024; | |
| 113 const int kMaxPacketLength = 64 * 1024; | |
| 114 | |
| 115 UsbDevice* g_device_for_test = NULL; | |
| 116 | |
| 117 bool ConvertDirectionToApi(const UsbEndpointDirection& input, | |
| 118 Direction* output) { | |
| 119 switch (input) { | |
| 120 case usb_service::USB_DIRECTION_INBOUND: | |
| 121 *output = usb::DIRECTION_IN; | |
| 122 return true; | |
| 123 case usb_service::USB_DIRECTION_OUTBOUND: | |
| 124 *output = usb::DIRECTION_OUT; | |
| 125 return true; | |
| 126 default: | |
| 127 NOTREACHED(); | |
| 128 return false; | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 bool ConvertSynchronizationTypeToApi(const UsbSynchronizationType& input, | |
| 133 usb::SynchronizationType* output) { | |
| 134 switch (input) { | |
| 135 case usb_service::USB_SYNCHRONIZATION_NONE: | |
| 136 *output = usb::SYNCHRONIZATION_TYPE_NONE; | |
| 137 return true; | |
| 138 case usb_service::USB_SYNCHRONIZATION_ASYNCHRONOUS: | |
| 139 *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS; | |
| 140 return true; | |
| 141 case usb_service::USB_SYNCHRONIZATION_ADAPTIVE: | |
| 142 *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE; | |
| 143 return true; | |
| 144 case usb_service::USB_SYNCHRONIZATION_SYNCHRONOUS: | |
| 145 *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS; | |
| 146 return true; | |
| 147 default: | |
| 148 NOTREACHED(); | |
| 149 return false; | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 bool ConvertTransferTypeToApi( | |
| 154 const UsbTransferType& input, | |
| 155 usb::TransferType* output) { | |
| 156 switch (input) { | |
| 157 case usb_service::USB_TRANSFER_CONTROL: | |
| 158 *output = usb::TRANSFER_TYPE_CONTROL; | |
| 159 return true; | |
| 160 case usb_service::USB_TRANSFER_INTERRUPT: | |
| 161 *output = usb::TRANSFER_TYPE_INTERRUPT; | |
| 162 return true; | |
| 163 case usb_service::USB_TRANSFER_ISOCHRONOUS: | |
| 164 *output = usb::TRANSFER_TYPE_ISOCHRONOUS; | |
| 165 return true; | |
| 166 case usb_service::USB_TRANSFER_BULK: | |
| 167 *output = usb::TRANSFER_TYPE_BULK; | |
| 168 return true; | |
| 169 default: | |
| 170 NOTREACHED(); | |
| 171 return false; | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 bool ConvertUsageTypeToApi(const UsbUsageType& input, usb::UsageType* output) { | |
| 176 switch (input) { | |
| 177 case usb_service::USB_USAGE_DATA: | |
| 178 *output = usb::USAGE_TYPE_DATA; | |
| 179 return true; | |
| 180 case usb_service::USB_USAGE_FEEDBACK: | |
| 181 *output = usb::USAGE_TYPE_FEEDBACK; | |
| 182 return true; | |
| 183 case usb_service::USB_USAGE_EXPLICIT_FEEDBACK: | |
| 184 *output = usb::USAGE_TYPE_EXPLICITFEEDBACK; | |
| 185 return true; | |
| 186 default: | |
| 187 NOTREACHED(); | |
| 188 return false; | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 bool ConvertDirection(const Direction& input, | |
| 193 UsbEndpointDirection* output) { | |
| 194 switch (input) { | |
| 195 case usb::DIRECTION_IN: | |
| 196 *output = usb_service::USB_DIRECTION_INBOUND; | |
| 197 return true; | |
| 198 case usb::DIRECTION_OUT: | |
| 199 *output = usb_service::USB_DIRECTION_OUTBOUND; | |
| 200 return true; | |
| 201 default: | |
| 202 NOTREACHED(); | |
| 203 return false; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 bool ConvertRequestType(const RequestType& input, | |
| 208 UsbDeviceHandle::TransferRequestType* output) { | |
| 209 switch (input) { | |
| 210 case usb::REQUEST_TYPE_STANDARD: | |
| 211 *output = UsbDeviceHandle::STANDARD; | |
| 212 return true; | |
| 213 case usb::REQUEST_TYPE_CLASS: | |
| 214 *output = UsbDeviceHandle::CLASS; | |
| 215 return true; | |
| 216 case usb::REQUEST_TYPE_VENDOR: | |
| 217 *output = UsbDeviceHandle::VENDOR; | |
| 218 return true; | |
| 219 case usb::REQUEST_TYPE_RESERVED: | |
| 220 *output = UsbDeviceHandle::RESERVED; | |
| 221 return true; | |
| 222 default: | |
| 223 NOTREACHED(); | |
| 224 return false; | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 bool ConvertRecipient(const Recipient& input, | |
| 229 UsbDeviceHandle::TransferRecipient* output) { | |
| 230 switch (input) { | |
| 231 case usb::RECIPIENT_DEVICE: | |
| 232 *output = UsbDeviceHandle::DEVICE; | |
| 233 return true; | |
| 234 case usb::RECIPIENT_INTERFACE: | |
| 235 *output = UsbDeviceHandle::INTERFACE; | |
| 236 return true; | |
| 237 case usb::RECIPIENT_ENDPOINT: | |
| 238 *output = UsbDeviceHandle::ENDPOINT; | |
| 239 return true; | |
| 240 case usb::RECIPIENT_OTHER: | |
| 241 *output = UsbDeviceHandle::OTHER; | |
| 242 return true; | |
| 243 default: | |
| 244 NOTREACHED(); | |
| 245 return false; | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 template<class T> | |
| 250 bool GetTransferSize(const T& input, size_t* output) { | |
| 251 if (input.direction == usb::DIRECTION_IN) { | |
| 252 const int* length = input.length.get(); | |
| 253 if (length && *length >= 0 && | |
| 254 static_cast<size_t>(*length) < kMaxTransferLength) { | |
| 255 *output = *length; | |
| 256 return true; | |
| 257 } | |
| 258 } else if (input.direction == usb::DIRECTION_OUT) { | |
| 259 if (input.data.get()) { | |
| 260 *output = input.data->size(); | |
| 261 return true; | |
| 262 } | |
| 263 } | |
| 264 return false; | |
| 265 } | |
| 266 | |
| 267 template<class T> | |
| 268 scoped_refptr<net::IOBuffer> CreateBufferForTransfer( | |
| 269 const T& input, UsbEndpointDirection direction, size_t size) { | |
| 270 | |
| 271 if (size >= kMaxTransferLength) | |
| 272 return NULL; | |
| 273 | |
| 274 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This | |
| 275 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer | |
| 276 // cannot represent a zero-length buffer, while an URB can. | |
| 277 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( | |
| 278 static_cast<size_t>(1), size)); | |
| 279 | |
| 280 if (direction == usb_service::USB_DIRECTION_INBOUND) { | |
| 281 return buffer; | |
| 282 } else if (direction == usb_service::USB_DIRECTION_OUTBOUND) { | |
| 283 if (input.data.get() && size <= input.data->size()) { | |
| 284 memcpy(buffer->data(), input.data->data(), size); | |
| 285 return buffer; | |
| 286 } | |
| 287 } | |
| 288 NOTREACHED(); | |
| 289 return NULL; | |
| 290 } | |
| 291 | |
| 292 const char* ConvertTransferStatusToErrorString(const UsbTransferStatus status) { | |
| 293 switch (status) { | |
| 294 case usb_service::USB_TRANSFER_COMPLETED: | |
| 295 return ""; | |
| 296 case usb_service::USB_TRANSFER_ERROR: | |
| 297 return kErrorGeneric; | |
| 298 case usb_service::USB_TRANSFER_TIMEOUT: | |
| 299 return kErrorTimeout; | |
| 300 case usb_service::USB_TRANSFER_CANCELLED: | |
| 301 return kErrorCancelled; | |
| 302 case usb_service::USB_TRANSFER_STALLED: | |
| 303 return kErrorStalled; | |
| 304 case usb_service::USB_TRANSFER_DISCONNECT: | |
| 305 return kErrorDisconnect; | |
| 306 case usb_service::USB_TRANSFER_OVERFLOW: | |
| 307 return kErrorOverflow; | |
| 308 case usb_service::USB_TRANSFER_LENGTH_SHORT: | |
| 309 return kErrorTransferLength; | |
| 310 default: | |
| 311 NOTREACHED(); | |
| 312 return ""; | |
| 313 } | |
| 314 } | |
| 315 | |
| 316 #if defined(OS_CHROMEOS) | |
| 317 void RequestUsbDevicesAccessHelper( | |
| 318 ScopedDeviceVector devices, | |
| 319 std::vector<scoped_refptr<UsbDevice> >::iterator i, | |
| 320 int interface_id, | |
| 321 const base::Callback<void(ScopedDeviceVector result)>& callback, | |
| 322 bool success) { | |
| 323 if (success) { | |
| 324 ++i; | |
| 325 } else { | |
| 326 i = devices->erase(i); | |
| 327 } | |
| 328 if (i == devices->end()) { | |
| 329 callback.Run(devices.Pass()); | |
| 330 return; | |
| 331 } | |
| 332 (*i)->RequestUsbAcess(interface_id, base::Bind(RequestUsbDevicesAccessHelper, | |
| 333 base::Passed(devices.Pass()), | |
| 334 i, interface_id, callback)); | |
| 335 } | |
| 336 | |
| 337 void RequestUsbDevicesAccess( | |
| 338 ScopedDeviceVector devices, | |
| 339 int interface_id, | |
| 340 const base::Callback<void(ScopedDeviceVector result)>& callback) { | |
| 341 if (devices->empty()) { | |
| 342 callback.Run(devices.Pass()); | |
| 343 return; | |
| 344 } | |
| 345 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin(); | |
| 346 (*i)->RequestUsbAcess( | |
| 347 interface_id, | |
| 348 base::Bind(RequestUsbDevicesAccessHelper, base::Passed(devices.Pass()), | |
| 349 i, interface_id, callback)); | |
| 350 } | |
| 351 #endif // OS_CHROMEOS | |
| 352 | |
| 353 base::DictionaryValue* CreateTransferInfo( | |
| 354 UsbTransferStatus status, | |
| 355 scoped_refptr<net::IOBuffer> data, | |
| 356 size_t length) { | |
| 357 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 358 result->SetInteger(kResultCodeKey, status); | |
| 359 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(), | |
| 360 length)); | |
| 361 return result; | |
| 362 } | |
| 363 | |
| 364 base::Value* PopulateConnectionHandle(int handle, int vendor_id, | |
| 365 int product_id) { | |
| 366 ConnectionHandle result; | |
| 367 result.handle = handle; | |
| 368 result.vendor_id = vendor_id; | |
| 369 result.product_id = product_id; | |
| 370 return result.ToValue().release(); | |
| 371 } | |
| 372 | |
| 373 base::Value* PopulateDevice(UsbDevice* device) { | |
| 374 Device result; | |
| 375 result.device = device->unique_id(); | |
| 376 result.vendor_id = device->vendor_id(); | |
| 377 result.product_id = device->product_id(); | |
| 378 return result.ToValue().release(); | |
| 379 } | |
| 380 | |
| 381 base::Value* PopulateInterfaceDescriptor( | |
| 382 int interface_number, | |
| 383 int alternate_setting, | |
| 384 int interface_class, | |
| 385 int interface_subclass, | |
| 386 int interface_protocol, | |
| 387 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) { | |
| 388 InterfaceDescriptor descriptor; | |
| 389 descriptor.interface_number = interface_number; | |
| 390 descriptor.alternate_setting = alternate_setting; | |
| 391 descriptor.interface_class = interface_class; | |
| 392 descriptor.interface_subclass = interface_subclass; | |
| 393 descriptor.interface_protocol = interface_protocol; | |
| 394 descriptor.endpoints = *endpoints; | |
| 395 return descriptor.ToValue().release(); | |
| 396 } | |
| 397 | |
| 398 } // namespace | |
| 399 | |
| 400 namespace extensions { | |
| 401 | |
| 402 UsbAsyncApiFunction::UsbAsyncApiFunction() | |
| 403 : manager_(NULL) { | |
| 404 } | |
| 405 | |
| 406 UsbAsyncApiFunction::~UsbAsyncApiFunction() { | |
| 407 } | |
| 408 | |
| 409 bool UsbAsyncApiFunction::PrePrepare() { | |
| 410 manager_ = ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | |
| 411 set_work_thread_id(BrowserThread::FILE); | |
| 412 return manager_ != NULL; | |
| 413 } | |
| 414 | |
| 415 bool UsbAsyncApiFunction::Respond() { | |
| 416 return error_.empty(); | |
| 417 } | |
| 418 | |
| 419 scoped_refptr<UsbDevice> | |
| 420 UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError( | |
| 421 const Device& input_device) { | |
| 422 if (g_device_for_test) | |
| 423 return g_device_for_test; | |
| 424 | |
| 425 const uint16_t vendor_id = input_device.vendor_id; | |
| 426 const uint16_t product_id = input_device.product_id; | |
| 427 UsbDevicePermission::CheckParam param( | |
| 428 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE); | |
| 429 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 430 GetExtension(), APIPermission::kUsbDevice, ¶m)) { | |
| 431 LOG(WARNING) << "Insufficient permissions to access device."; | |
| 432 CompleteWithError(kErrorPermissionDenied); | |
| 433 return NULL; | |
| 434 } | |
| 435 | |
| 436 UsbService* service = UsbService::GetInstance(); | |
| 437 if (!service) { | |
| 438 CompleteWithError(kErrorInitService); | |
| 439 return NULL; | |
| 440 } | |
| 441 scoped_refptr<UsbDevice> device; | |
| 442 | |
| 443 device = service->GetDeviceById(input_device.device); | |
| 444 | |
| 445 if (!device) { | |
| 446 CompleteWithError(kErrorNoDevice); | |
| 447 return NULL; | |
| 448 } | |
| 449 | |
| 450 if (device->vendor_id() != input_device.vendor_id || | |
| 451 device->product_id() != input_device.product_id) { | |
| 452 // Must act as if there is no such a device. | |
| 453 // Otherwise can be used to finger print unauthorized devices. | |
| 454 CompleteWithError(kErrorNoDevice); | |
| 455 return NULL; | |
| 456 } | |
| 457 | |
| 458 return device; | |
| 459 } | |
| 460 | |
| 461 scoped_refptr<UsbDeviceHandle> | |
| 462 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError( | |
| 463 const ConnectionHandle& input_device_handle) { | |
| 464 UsbDeviceResource* resource = | |
| 465 manager_->Get(extension_->id(), input_device_handle.handle); | |
| 466 if (!resource) { | |
| 467 CompleteWithError(kErrorNoDevice); | |
| 468 return NULL; | |
| 469 } | |
| 470 | |
| 471 if (!resource->device() || !resource->device()->device()) { | |
| 472 CompleteWithError(kErrorDisconnect); | |
| 473 manager_->Remove(extension_->id(), input_device_handle.handle); | |
| 474 return NULL; | |
| 475 } | |
| 476 | |
| 477 if (resource->device()->device()->vendor_id() != | |
| 478 input_device_handle.vendor_id || | |
| 479 resource->device()->device()->product_id() != | |
| 480 input_device_handle.product_id) { | |
| 481 CompleteWithError(kErrorNoDevice); | |
| 482 return NULL; | |
| 483 } | |
| 484 | |
| 485 return resource->device(); | |
| 486 } | |
| 487 | |
| 488 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) { | |
| 489 manager_->Remove(extension_->id(), api_resource_id); | |
| 490 } | |
| 491 | |
| 492 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) { | |
| 493 SetError(error); | |
| 494 AsyncWorkCompleted(); | |
| 495 } | |
| 496 | |
| 497 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {} | |
| 498 | |
| 499 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {} | |
| 500 | |
| 501 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status, | |
| 502 scoped_refptr<net::IOBuffer> data, | |
| 503 size_t length) { | |
| 504 if (status != usb_service::USB_TRANSFER_COMPLETED) | |
| 505 SetError(ConvertTransferStatusToErrorString(status)); | |
| 506 | |
| 507 SetResult(CreateTransferInfo(status, data, length)); | |
| 508 AsyncWorkCompleted(); | |
| 509 } | |
| 510 | |
| 511 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely( | |
| 512 const Direction& input, UsbEndpointDirection* output) { | |
| 513 const bool converted = ConvertDirection(input, output); | |
| 514 if (!converted) | |
| 515 SetError(kErrorConvertDirection); | |
| 516 return converted; | |
| 517 } | |
| 518 | |
| 519 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely( | |
| 520 const RequestType& input, UsbDeviceHandle::TransferRequestType* output) { | |
| 521 const bool converted = ConvertRequestType(input, output); | |
| 522 if (!converted) | |
| 523 SetError(kErrorConvertRequestType); | |
| 524 return converted; | |
| 525 } | |
| 526 | |
| 527 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely( | |
| 528 const Recipient& input, UsbDeviceHandle::TransferRecipient* output) { | |
| 529 const bool converted = ConvertRecipient(input, output); | |
| 530 if (!converted) | |
| 531 SetError(kErrorConvertRecipient); | |
| 532 return converted; | |
| 533 } | |
| 534 | |
| 535 UsbFindDevicesFunction::UsbFindDevicesFunction() {} | |
| 536 | |
| 537 UsbFindDevicesFunction::~UsbFindDevicesFunction() {} | |
| 538 | |
| 539 bool UsbFindDevicesFunction::Prepare() { | |
| 540 parameters_ = FindDevices::Params::Create(*args_); | |
| 541 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 542 return true; | |
| 543 } | |
| 544 | |
| 545 void UsbFindDevicesFunction::AsyncWorkStart() { | |
| 546 scoped_ptr<base::ListValue> result(new base::ListValue()); | |
| 547 | |
| 548 if (g_device_for_test) { | |
| 549 UsbDeviceResource* const resource = new UsbDeviceResource( | |
| 550 extension_->id(), | |
| 551 g_device_for_test->Open()); | |
| 552 | |
| 553 result->Append(PopulateConnectionHandle(manager_->Add(resource), 0, 0)); | |
| 554 SetResult(result.release()); | |
| 555 AsyncWorkCompleted(); | |
| 556 return; | |
| 557 } | |
| 558 | |
| 559 const uint16_t vendor_id = parameters_->options.vendor_id; | |
| 560 const uint16_t product_id = parameters_->options.product_id; | |
| 561 int interface_id = parameters_->options.interface_id.get() ? | |
| 562 *parameters_->options.interface_id.get() : | |
| 563 UsbDevicePermissionData::ANY_INTERFACE; | |
| 564 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id); | |
| 565 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 566 GetExtension(), APIPermission::kUsbDevice, ¶m)) { | |
| 567 LOG(WARNING) << "Insufficient permissions to access device."; | |
| 568 CompleteWithError(kErrorPermissionDenied); | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 UsbService *service = UsbService::GetInstance(); | |
| 573 if (!service) { | |
| 574 CompleteWithError(kErrorInitService); | |
| 575 return; | |
| 576 } | |
| 577 | |
| 578 ScopedDeviceVector devices(new DeviceVector()); | |
| 579 service->GetDevices(devices.get()); | |
| 580 | |
| 581 for (DeviceVector::iterator it = devices->begin(); | |
| 582 it != devices->end();) { | |
| 583 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) { | |
| 584 it = devices->erase(it); | |
| 585 } else { | |
| 586 ++it; | |
| 587 } | |
| 588 } | |
| 589 | |
| 590 #if defined(OS_CHROMEOS) | |
| 591 RequestUsbDevicesAccess( | |
| 592 devices.Pass(), interface_id, | |
| 593 base::Bind(&UsbFindDevicesFunction::OpenDevices, this)); | |
| 594 #else | |
| 595 OpenDevices(devices.Pass()); | |
| 596 #endif // OS_CHROMEOS | |
| 597 } | |
| 598 | |
| 599 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) { | |
| 600 base::ListValue* result = new base::ListValue(); | |
| 601 | |
| 602 for (size_t i = 0; i < devices->size(); ++i) { | |
| 603 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 604 devices->at(i)->Open(); | |
| 605 if (device_handle) | |
| 606 device_handles_.push_back(device_handle); | |
| 607 } | |
| 608 | |
| 609 for (size_t i = 0; i < device_handles_.size(); ++i) { | |
| 610 UsbDeviceHandle* const device_handle = device_handles_[i].get(); | |
| 611 UsbDeviceResource* const resource = | |
| 612 new UsbDeviceResource(extension_->id(), device_handle); | |
| 613 | |
| 614 result->Append(PopulateConnectionHandle(manager_->Add(resource), | |
| 615 parameters_->options.vendor_id, | |
| 616 parameters_->options.product_id)); | |
| 617 } | |
| 618 | |
| 619 SetResult(result); | |
| 620 AsyncWorkCompleted(); | |
| 621 } | |
| 622 | |
| 623 UsbGetDevicesFunction::UsbGetDevicesFunction() { | |
| 624 } | |
| 625 | |
| 626 UsbGetDevicesFunction::~UsbGetDevicesFunction() { | |
| 627 } | |
| 628 | |
| 629 void UsbGetDevicesFunction::SetDeviceForTest(UsbDevice* device) { | |
| 630 g_device_for_test = device; | |
| 631 } | |
| 632 | |
| 633 bool UsbGetDevicesFunction::Prepare() { | |
| 634 parameters_ = GetDevices::Params::Create(*args_); | |
| 635 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 636 return true; | |
| 637 } | |
| 638 | |
| 639 void UsbGetDevicesFunction::AsyncWorkStart() { | |
| 640 scoped_ptr<base::ListValue> result(new base::ListValue()); | |
| 641 | |
| 642 if (g_device_for_test) { | |
| 643 result->Append(PopulateDevice(g_device_for_test)); | |
| 644 SetResult(result.release()); | |
| 645 AsyncWorkCompleted(); | |
| 646 return; | |
| 647 } | |
| 648 | |
| 649 const uint16_t vendor_id = parameters_->options.vendor_id; | |
| 650 const uint16_t product_id = parameters_->options.product_id; | |
| 651 UsbDevicePermission::CheckParam param( | |
| 652 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE); | |
| 653 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 654 GetExtension(), APIPermission::kUsbDevice, ¶m)) { | |
| 655 LOG(WARNING) << "Insufficient permissions to access device."; | |
| 656 CompleteWithError(kErrorPermissionDenied); | |
| 657 return; | |
| 658 } | |
| 659 | |
| 660 UsbService* service = UsbService::GetInstance(); | |
| 661 if (!service) { | |
| 662 CompleteWithError(kErrorInitService); | |
| 663 return; | |
| 664 } | |
| 665 | |
| 666 DeviceVector devices; | |
| 667 service->GetDevices(&devices); | |
| 668 | |
| 669 for (DeviceVector::iterator it = devices.begin(); it != devices.end();) { | |
| 670 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) { | |
| 671 it = devices.erase(it); | |
| 672 } else { | |
| 673 ++it; | |
| 674 } | |
| 675 } | |
| 676 | |
| 677 for (size_t i = 0; i < devices.size(); ++i) { | |
| 678 result->Append(PopulateDevice(devices[i].get())); | |
| 679 } | |
| 680 | |
| 681 SetResult(result.release()); | |
| 682 AsyncWorkCompleted(); | |
| 683 } | |
| 684 | |
| 685 UsbRequestAccessFunction::UsbRequestAccessFunction() {} | |
| 686 | |
| 687 UsbRequestAccessFunction::~UsbRequestAccessFunction() {} | |
| 688 | |
| 689 bool UsbRequestAccessFunction::Prepare() { | |
| 690 parameters_ = RequestAccess::Params::Create(*args_); | |
| 691 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 692 return true; | |
| 693 } | |
| 694 | |
| 695 void UsbRequestAccessFunction::AsyncWorkStart() { | |
| 696 #if defined(OS_CHROMEOS) | |
| 697 scoped_refptr<UsbDevice> device = | |
| 698 GetDeviceOrOrCompleteWithError(parameters_->device); | |
| 699 if (!device) return; | |
| 700 | |
| 701 device->RequestUsbAcess(parameters_->interface_id, | |
| 702 base::Bind(&UsbRequestAccessFunction::OnCompleted, | |
| 703 this)); | |
| 704 #else | |
| 705 SetResult(new base::FundamentalValue(false)); | |
| 706 CompleteWithError(kErrorNotSupported); | |
| 707 #endif // OS_CHROMEOS | |
| 708 } | |
| 709 | |
| 710 void UsbRequestAccessFunction::OnCompleted(bool success) { | |
| 711 SetResult(new base::FundamentalValue(success)); | |
| 712 AsyncWorkCompleted(); | |
| 713 } | |
| 714 | |
| 715 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {} | |
| 716 | |
| 717 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {} | |
| 718 | |
| 719 bool UsbOpenDeviceFunction::Prepare() { | |
| 720 parameters_ = OpenDevice::Params::Create(*args_); | |
| 721 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 722 return true; | |
| 723 } | |
| 724 | |
| 725 void UsbOpenDeviceFunction::AsyncWorkStart() { | |
| 726 scoped_refptr<UsbDevice> device = | |
| 727 GetDeviceOrOrCompleteWithError(parameters_->device); | |
| 728 if (!device) return; | |
| 729 | |
| 730 handle_ = device->Open(); | |
| 731 if (!handle_) { | |
| 732 SetError(kErrorOpen); | |
| 733 AsyncWorkCompleted(); | |
| 734 return; | |
| 735 } | |
| 736 | |
| 737 SetResult(PopulateConnectionHandle( | |
| 738 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)), | |
| 739 handle_->device()->vendor_id(), | |
| 740 handle_->device()->product_id())); | |
| 741 AsyncWorkCompleted(); | |
| 742 } | |
| 743 | |
| 744 UsbListInterfacesFunction::UsbListInterfacesFunction() {} | |
| 745 | |
| 746 UsbListInterfacesFunction::~UsbListInterfacesFunction() {} | |
| 747 | |
| 748 bool UsbListInterfacesFunction::Prepare() { | |
| 749 parameters_ = ListInterfaces::Params::Create(*args_); | |
| 750 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 751 return true; | |
| 752 } | |
| 753 | |
| 754 void UsbListInterfacesFunction::AsyncWorkStart() { | |
| 755 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 756 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 757 if (!device_handle) return; | |
| 758 | |
| 759 scoped_refptr<UsbConfigDescriptor> config = | |
| 760 device_handle->device()->ListInterfaces(); | |
| 761 | |
| 762 if (!config) { | |
| 763 SetError(kErrorCannotListInterfaces); | |
| 764 AsyncWorkCompleted(); | |
| 765 return; | |
| 766 } | |
| 767 | |
| 768 result_.reset(new base::ListValue()); | |
| 769 | |
| 770 for (size_t i = 0, num_interfaces = config->GetNumInterfaces(); | |
| 771 i < num_interfaces; ++i) { | |
| 772 scoped_refptr<const UsbInterfaceDescriptor> | |
| 773 usb_interface(config->GetInterface(i)); | |
| 774 for (size_t j = 0, num_descriptors = usb_interface->GetNumAltSettings(); | |
| 775 j < num_descriptors; ++j) { | |
| 776 scoped_refptr<const UsbInterfaceAltSettingDescriptor> descriptor | |
| 777 = usb_interface->GetAltSetting(j); | |
| 778 std::vector<linked_ptr<EndpointDescriptor> > endpoints; | |
| 779 for (size_t k = 0, num_endpoints = descriptor->GetNumEndpoints(); | |
| 780 k < num_endpoints; k++) { | |
| 781 scoped_refptr<const UsbEndpointDescriptor> endpoint | |
| 782 = descriptor->GetEndpoint(k); | |
| 783 linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor()); | |
| 784 | |
| 785 TransferType type; | |
| 786 Direction direction; | |
| 787 SynchronizationType synchronization; | |
| 788 UsageType usage; | |
| 789 | |
| 790 if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) || | |
| 791 !ConvertDirectionSafely(endpoint->GetDirection(), &direction) || | |
| 792 !ConvertSynchronizationTypeSafely( | |
| 793 endpoint->GetSynchronizationType(), &synchronization) || | |
| 794 !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) { | |
| 795 SetError(kErrorCannotListInterfaces); | |
| 796 AsyncWorkCompleted(); | |
| 797 return; | |
| 798 } | |
| 799 | |
| 800 endpoint_desc->address = endpoint->GetAddress(); | |
| 801 endpoint_desc->type = type; | |
| 802 endpoint_desc->direction = direction; | |
| 803 endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize(); | |
| 804 endpoint_desc->synchronization = synchronization; | |
| 805 endpoint_desc->usage = usage; | |
| 806 | |
| 807 int* polling_interval = new int; | |
| 808 endpoint_desc->polling_interval.reset(polling_interval); | |
| 809 *polling_interval = endpoint->GetPollingInterval(); | |
| 810 | |
| 811 endpoints.push_back(endpoint_desc); | |
| 812 } | |
| 813 | |
| 814 result_->Append(PopulateInterfaceDescriptor( | |
| 815 descriptor->GetInterfaceNumber(), | |
| 816 descriptor->GetAlternateSetting(), | |
| 817 descriptor->GetInterfaceClass(), | |
| 818 descriptor->GetInterfaceSubclass(), | |
| 819 descriptor->GetInterfaceProtocol(), | |
| 820 &endpoints)); | |
| 821 } | |
| 822 } | |
| 823 | |
| 824 SetResult(result_.release()); | |
| 825 AsyncWorkCompleted(); | |
| 826 } | |
| 827 | |
| 828 bool UsbListInterfacesFunction::ConvertDirectionSafely( | |
| 829 const UsbEndpointDirection& input, | |
| 830 usb::Direction* output) { | |
| 831 const bool converted = ConvertDirectionToApi(input, output); | |
| 832 if (!converted) | |
| 833 SetError(kErrorConvertDirection); | |
| 834 return converted; | |
| 835 } | |
| 836 | |
| 837 bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely( | |
| 838 const UsbSynchronizationType& input, | |
| 839 usb::SynchronizationType* output) { | |
| 840 const bool converted = ConvertSynchronizationTypeToApi(input, output); | |
| 841 if (!converted) | |
| 842 SetError(kErrorConvertSynchronizationType); | |
| 843 return converted; | |
| 844 } | |
| 845 | |
| 846 bool UsbListInterfacesFunction::ConvertTransferTypeSafely( | |
| 847 const UsbTransferType& input, | |
| 848 usb::TransferType* output) { | |
| 849 const bool converted = ConvertTransferTypeToApi(input, output); | |
| 850 if (!converted) | |
| 851 SetError(kErrorConvertTransferType); | |
| 852 return converted; | |
| 853 } | |
| 854 | |
| 855 bool UsbListInterfacesFunction::ConvertUsageTypeSafely( | |
| 856 const UsbUsageType& input, | |
| 857 usb::UsageType* output) { | |
| 858 const bool converted = ConvertUsageTypeToApi(input, output); | |
| 859 if (!converted) | |
| 860 SetError(kErrorConvertUsageType); | |
| 861 return converted; | |
| 862 } | |
| 863 | |
| 864 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {} | |
| 865 | |
| 866 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {} | |
| 867 | |
| 868 bool UsbCloseDeviceFunction::Prepare() { | |
| 869 parameters_ = CloseDevice::Params::Create(*args_); | |
| 870 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 871 return true; | |
| 872 } | |
| 873 | |
| 874 void UsbCloseDeviceFunction::AsyncWorkStart() { | |
| 875 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 876 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 877 if (!device_handle) return; | |
| 878 | |
| 879 device_handle->Close(); | |
| 880 RemoveUsbDeviceResource(parameters_->handle.handle); | |
| 881 AsyncWorkCompleted(); | |
| 882 } | |
| 883 | |
| 884 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {} | |
| 885 | |
| 886 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {} | |
| 887 | |
| 888 bool UsbClaimInterfaceFunction::Prepare() { | |
| 889 parameters_ = ClaimInterface::Params::Create(*args_); | |
| 890 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 891 return true; | |
| 892 } | |
| 893 | |
| 894 void UsbClaimInterfaceFunction::AsyncWorkStart() { | |
| 895 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 896 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 897 if (!device_handle) return; | |
| 898 | |
| 899 bool success = device_handle->ClaimInterface(parameters_->interface_number); | |
| 900 | |
| 901 if (!success) | |
| 902 SetError(kErrorCannotClaimInterface); | |
| 903 AsyncWorkCompleted(); | |
| 904 } | |
| 905 | |
| 906 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {} | |
| 907 | |
| 908 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {} | |
| 909 | |
| 910 bool UsbReleaseInterfaceFunction::Prepare() { | |
| 911 parameters_ = ReleaseInterface::Params::Create(*args_); | |
| 912 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 913 return true; | |
| 914 } | |
| 915 | |
| 916 void UsbReleaseInterfaceFunction::AsyncWorkStart() { | |
| 917 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 918 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 919 if (!device_handle) return; | |
| 920 | |
| 921 bool success = device_handle->ReleaseInterface(parameters_->interface_number); | |
| 922 if (!success) | |
| 923 SetError(kErrorCannotReleaseInterface); | |
| 924 AsyncWorkCompleted(); | |
| 925 } | |
| 926 | |
| 927 UsbSetInterfaceAlternateSettingFunction:: | |
| 928 UsbSetInterfaceAlternateSettingFunction() {} | |
| 929 | |
| 930 UsbSetInterfaceAlternateSettingFunction:: | |
| 931 ~UsbSetInterfaceAlternateSettingFunction() {} | |
| 932 | |
| 933 bool UsbSetInterfaceAlternateSettingFunction::Prepare() { | |
| 934 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_); | |
| 935 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 936 return true; | |
| 937 } | |
| 938 | |
| 939 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() { | |
| 940 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 941 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 942 if (!device_handle) return; | |
| 943 | |
| 944 bool success = device_handle->SetInterfaceAlternateSetting( | |
| 945 parameters_->interface_number, | |
| 946 parameters_->alternate_setting); | |
| 947 if (!success) | |
| 948 SetError(kErrorCannotSetInterfaceAlternateSetting); | |
| 949 | |
| 950 AsyncWorkCompleted(); | |
| 951 } | |
| 952 | |
| 953 UsbControlTransferFunction::UsbControlTransferFunction() {} | |
| 954 | |
| 955 UsbControlTransferFunction::~UsbControlTransferFunction() {} | |
| 956 | |
| 957 bool UsbControlTransferFunction::Prepare() { | |
| 958 parameters_ = ControlTransfer::Params::Create(*args_); | |
| 959 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 960 return true; | |
| 961 } | |
| 962 | |
| 963 void UsbControlTransferFunction::AsyncWorkStart() { | |
| 964 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 965 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 966 if (!device_handle) return; | |
| 967 | |
| 968 const ControlTransferInfo& transfer = parameters_->transfer_info; | |
| 969 | |
| 970 UsbEndpointDirection direction; | |
| 971 UsbDeviceHandle::TransferRequestType request_type; | |
| 972 UsbDeviceHandle::TransferRecipient recipient; | |
| 973 size_t size = 0; | |
| 974 | |
| 975 if (!ConvertDirectionSafely(transfer.direction, &direction) || | |
| 976 !ConvertRequestTypeSafely(transfer.request_type, &request_type) || | |
| 977 !ConvertRecipientSafely(transfer.recipient, &recipient)) { | |
| 978 AsyncWorkCompleted(); | |
| 979 return; | |
| 980 } | |
| 981 | |
| 982 if (!GetTransferSize(transfer, &size)) { | |
| 983 CompleteWithError(kErrorInvalidTransferLength); | |
| 984 return; | |
| 985 } | |
| 986 | |
| 987 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
| 988 transfer, direction, size); | |
| 989 if (!buffer.get()) { | |
| 990 CompleteWithError(kErrorMalformedParameters); | |
| 991 return; | |
| 992 } | |
| 993 | |
| 994 device_handle->ControlTransfer( | |
| 995 direction, | |
| 996 request_type, | |
| 997 recipient, | |
| 998 transfer.request, | |
| 999 transfer.value, | |
| 1000 transfer.index, | |
| 1001 buffer.get(), | |
| 1002 size, | |
| 1003 0, | |
| 1004 base::Bind(&UsbControlTransferFunction::OnCompleted, this)); | |
| 1005 } | |
| 1006 | |
| 1007 UsbBulkTransferFunction::UsbBulkTransferFunction() {} | |
| 1008 | |
| 1009 UsbBulkTransferFunction::~UsbBulkTransferFunction() {} | |
| 1010 | |
| 1011 bool UsbBulkTransferFunction::Prepare() { | |
| 1012 parameters_ = BulkTransfer::Params::Create(*args_); | |
| 1013 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 1014 return true; | |
| 1015 } | |
| 1016 | |
| 1017 void UsbBulkTransferFunction::AsyncWorkStart() { | |
| 1018 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 1019 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 1020 if (!device_handle) return; | |
| 1021 | |
| 1022 const GenericTransferInfo& transfer = parameters_->transfer_info; | |
| 1023 | |
| 1024 UsbEndpointDirection direction; | |
| 1025 size_t size = 0; | |
| 1026 | |
| 1027 if (!ConvertDirectionSafely(transfer.direction, &direction)) { | |
| 1028 AsyncWorkCompleted(); | |
| 1029 return; | |
| 1030 } | |
| 1031 | |
| 1032 if (!GetTransferSize(transfer, &size)) { | |
| 1033 CompleteWithError(kErrorInvalidTransferLength); | |
| 1034 return; | |
| 1035 } | |
| 1036 | |
| 1037 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
| 1038 transfer, direction, size); | |
| 1039 if (!buffer.get()) { | |
| 1040 CompleteWithError(kErrorMalformedParameters); | |
| 1041 return; | |
| 1042 } | |
| 1043 | |
| 1044 device_handle->BulkTransfer( | |
| 1045 direction, | |
| 1046 transfer.endpoint, | |
| 1047 buffer.get(), | |
| 1048 size, | |
| 1049 0, | |
| 1050 base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); | |
| 1051 } | |
| 1052 | |
| 1053 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {} | |
| 1054 | |
| 1055 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {} | |
| 1056 | |
| 1057 bool UsbInterruptTransferFunction::Prepare() { | |
| 1058 parameters_ = InterruptTransfer::Params::Create(*args_); | |
| 1059 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 1060 return true; | |
| 1061 } | |
| 1062 | |
| 1063 void UsbInterruptTransferFunction::AsyncWorkStart() { | |
| 1064 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 1065 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 1066 if (!device_handle) return; | |
| 1067 | |
| 1068 const GenericTransferInfo& transfer = parameters_->transfer_info; | |
| 1069 | |
| 1070 UsbEndpointDirection direction; | |
| 1071 size_t size = 0; | |
| 1072 | |
| 1073 if (!ConvertDirectionSafely(transfer.direction, &direction)) { | |
| 1074 AsyncWorkCompleted(); | |
| 1075 return; | |
| 1076 } | |
| 1077 | |
| 1078 if (!GetTransferSize(transfer, &size)) { | |
| 1079 CompleteWithError(kErrorInvalidTransferLength); | |
| 1080 return; | |
| 1081 } | |
| 1082 | |
| 1083 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
| 1084 transfer, direction, size); | |
| 1085 if (!buffer.get()) { | |
| 1086 CompleteWithError(kErrorMalformedParameters); | |
| 1087 return; | |
| 1088 } | |
| 1089 | |
| 1090 device_handle->InterruptTransfer( | |
| 1091 direction, | |
| 1092 transfer.endpoint, | |
| 1093 buffer.get(), | |
| 1094 size, | |
| 1095 0, | |
| 1096 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); | |
| 1097 } | |
| 1098 | |
| 1099 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {} | |
| 1100 | |
| 1101 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {} | |
| 1102 | |
| 1103 bool UsbIsochronousTransferFunction::Prepare() { | |
| 1104 parameters_ = IsochronousTransfer::Params::Create(*args_); | |
| 1105 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 1106 return true; | |
| 1107 } | |
| 1108 | |
| 1109 void UsbIsochronousTransferFunction::AsyncWorkStart() { | |
| 1110 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 1111 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 1112 if (!device_handle) return; | |
| 1113 | |
| 1114 const IsochronousTransferInfo& transfer = parameters_->transfer_info; | |
| 1115 const GenericTransferInfo& generic_transfer = transfer.transfer_info; | |
| 1116 | |
| 1117 size_t size = 0; | |
| 1118 UsbEndpointDirection direction; | |
| 1119 | |
| 1120 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { | |
| 1121 AsyncWorkCompleted(); | |
| 1122 return; | |
| 1123 } | |
| 1124 if (!GetTransferSize(generic_transfer, &size)) { | |
| 1125 CompleteWithError(kErrorInvalidTransferLength); | |
| 1126 return; | |
| 1127 } | |
| 1128 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) { | |
| 1129 CompleteWithError(kErrorInvalidNumberOfPackets); | |
| 1130 return; | |
| 1131 } | |
| 1132 unsigned int packets = transfer.packets; | |
| 1133 if (transfer.packet_length < 0 || | |
| 1134 transfer.packet_length >= kMaxPacketLength) { | |
| 1135 CompleteWithError(kErrorInvalidPacketLength); | |
| 1136 return; | |
| 1137 } | |
| 1138 unsigned int packet_length = transfer.packet_length; | |
| 1139 const uint64 total_length = packets * packet_length; | |
| 1140 if (packets > size || total_length > size) { | |
| 1141 CompleteWithError(kErrorTransferLength); | |
| 1142 return; | |
| 1143 } | |
| 1144 | |
| 1145 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer( | |
| 1146 generic_transfer, direction, size); | |
| 1147 if (!buffer.get()) { | |
| 1148 CompleteWithError(kErrorMalformedParameters); | |
| 1149 return; | |
| 1150 } | |
| 1151 | |
| 1152 device_handle->IsochronousTransfer( | |
| 1153 direction, | |
| 1154 generic_transfer.endpoint, | |
| 1155 buffer.get(), | |
| 1156 size, | |
| 1157 packets, | |
| 1158 packet_length, | |
| 1159 0, | |
| 1160 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); | |
| 1161 } | |
| 1162 | |
| 1163 UsbResetDeviceFunction::UsbResetDeviceFunction() {} | |
| 1164 | |
| 1165 UsbResetDeviceFunction::~UsbResetDeviceFunction() {} | |
| 1166 | |
| 1167 bool UsbResetDeviceFunction::Prepare() { | |
| 1168 parameters_ = ResetDevice::Params::Create(*args_); | |
| 1169 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
| 1170 return true; | |
| 1171 } | |
| 1172 | |
| 1173 void UsbResetDeviceFunction::AsyncWorkStart() { | |
| 1174 scoped_refptr<UsbDeviceHandle> device_handle = | |
| 1175 GetDeviceHandleOrCompleteWithError(parameters_->handle); | |
| 1176 if (!device_handle) return; | |
| 1177 | |
| 1178 bool success = device_handle->ResetDevice(); | |
| 1179 if (!success) { | |
| 1180 device_handle->Close(); | |
| 1181 RemoveUsbDeviceResource(parameters_->handle.handle); | |
| 1182 SetResult(new base::FundamentalValue(false)); | |
| 1183 CompleteWithError(kErrorResetDevice); | |
| 1184 return; | |
| 1185 } | |
| 1186 | |
| 1187 SetResult(new base::FundamentalValue(true)); | |
| 1188 AsyncWorkCompleted(); | |
| 1189 } | |
| 1190 | |
| 1191 } // namespace extensions | |
| OLD | NEW |