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, ¶m);
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, ¶m)) {
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