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