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