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