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