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.
5 #include "chrome/browser/extensions/api/usb/usb_api.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "chrome/browser/extensions/api/usb/usb_device_resource.h"
13 #include "chrome/browser/extensions/extension_system.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/usb/usb_device_handle.h"
16 #include "chrome/browser/usb/usb_service.h"
17 #include "chrome/common/extensions/api/usb.h"
18 #include "chrome/common/extensions/permissions/usb_device_permission.h"
19 #include "extensions/common/permissions/permissions_data.h"
21 namespace usb = extensions::api::usb;
22 namespace BulkTransfer = usb::BulkTransfer;
23 namespace ClaimInterface = usb::ClaimInterface;
24 namespace CloseDevice = usb::CloseDevice;
25 namespace ControlTransfer = usb::ControlTransfer;
26 namespace FindDevices = usb::FindDevices;
27 namespace GetDevices = usb::GetDevices;
28 namespace InterruptTransfer = usb::InterruptTransfer;
29 namespace IsochronousTransfer = usb::IsochronousTransfer;
30 namespace ListInterfaces = usb::ListInterfaces;
31 namespace OpenDevice = usb::OpenDevice;
32 namespace ReleaseInterface = usb::ReleaseInterface;
33 namespace RequestAccess = usb::RequestAccess;
34 namespace ResetDevice = usb::ResetDevice;
35 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
37 using content::BrowserThread;
40 using usb::ControlTransferInfo;
41 using usb::ConnectionHandle;
44 using usb::EndpointDescriptor;
45 using usb::GenericTransferInfo;
46 using usb::InterfaceDescriptor;
47 using usb::IsochronousTransferInfo;
49 using usb::RequestType;
50 using usb::SynchronizationType;
51 using usb::TransferType;
54 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
55 typedef scoped_ptr<DeviceVector> ScopedDeviceVector;
59 const char kDataKey[] = "data";
60 const char kResultCodeKey[] = "resultCode";
62 const char kErrorInitService[] = "Failed to initialize USB service.";
64 const char kErrorOpen[] = "Failed to open device.";
65 const char kErrorCancelled[] = "Transfer was cancelled.";
66 const char kErrorDisconnect[] = "Device disconnected.";
67 const char kErrorGeneric[] = "Transfer failed.";
68 #if !defined(OS_CHROMEOS)
69 const char kErrorNotSupported[] = "Not supported on this platform.";
71 const char kErrorOverflow[] = "Inbound transfer overflow.";
72 const char kErrorStalled[] = "Transfer stalled.";
73 const char kErrorTimeout[] = "Transfer timed out.";
74 const char kErrorTransferLength[] = "Transfer length is insufficient.";
76 const char kErrorCannotListInterfaces[] = "Error listing interfaces.";
77 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
78 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
79 const char kErrorCannotSetInterfaceAlternateSetting[] =
80 "Error setting alternate interface setting.";
81 const char kErrorConvertDirection[] = "Invalid transfer direction.";
82 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
83 const char kErrorConvertRequestType[] = "Invalid request type.";
84 const char kErrorConvertSynchronizationType[] = "Invalid synchronization type";
85 const char kErrorConvertTransferType[] = "Invalid endpoint type.";
86 const char kErrorConvertUsageType[] = "Invalid usage type.";
87 const char kErrorMalformedParameters[] = "Error parsing parameters.";
88 const char kErrorNoDevice[] = "No such device.";
89 const char kErrorPermissionDenied[] =
90 "Permission to access device was denied";
91 const char kErrorInvalidTransferLength[] =
92 "Transfer length must be a positive number less than 104,857,600.";
93 const char kErrorInvalidNumberOfPackets[] =
94 "Number of packets must be a positive number less than 4,194,304.";
95 const char kErrorInvalidPacketLength[] = "Packet length must be a "
96 "positive number less than 65,536.";
97 const char kErrorResetDevice[] =
98 "Error resetting the device. The device has been closed.";
100 const size_t kMaxTransferLength = 100 * 1024 * 1024;
101 const int kMaxPackets = 4 * 1024 * 1024;
102 const int kMaxPacketLength = 64 * 1024;
104 UsbDevice* g_device_for_test = NULL;
106 bool ConvertDirectionToApi(const UsbEndpointDirection& input,
109 case USB_DIRECTION_INBOUND:
110 *output = usb::DIRECTION_IN;
112 case USB_DIRECTION_OUTBOUND:
113 *output = usb::DIRECTION_OUT;
121 bool ConvertSynchronizationTypeToApi(const UsbSynchronizationType& input,
122 usb::SynchronizationType* output) {
124 case USB_SYNCHRONIZATION_NONE:
125 *output = usb::SYNCHRONIZATION_TYPE_NONE;
127 case USB_SYNCHRONIZATION_ASYNCHRONOUS:
128 *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
130 case USB_SYNCHRONIZATION_ADAPTIVE:
131 *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
133 case USB_SYNCHRONIZATION_SYNCHRONOUS:
134 *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
142 bool ConvertTransferTypeToApi(
143 const UsbTransferType& input,
144 usb::TransferType* output) {
146 case USB_TRANSFER_CONTROL:
147 *output = usb::TRANSFER_TYPE_CONTROL;
149 case USB_TRANSFER_INTERRUPT:
150 *output = usb::TRANSFER_TYPE_INTERRUPT;
152 case USB_TRANSFER_ISOCHRONOUS:
153 *output = usb::TRANSFER_TYPE_ISOCHRONOUS;
155 case USB_TRANSFER_BULK:
156 *output = usb::TRANSFER_TYPE_BULK;
164 bool ConvertUsageTypeToApi(const UsbUsageType& input, usb::UsageType* output) {
167 *output = usb::USAGE_TYPE_DATA;
169 case USB_USAGE_FEEDBACK:
170 *output = usb::USAGE_TYPE_FEEDBACK;
172 case USB_USAGE_EXPLICIT_FEEDBACK:
173 *output = usb::USAGE_TYPE_EXPLICITFEEDBACK;
181 bool ConvertDirection(const Direction& input,
182 UsbEndpointDirection* output) {
184 case usb::DIRECTION_IN:
185 *output = USB_DIRECTION_INBOUND;
187 case usb::DIRECTION_OUT:
188 *output = USB_DIRECTION_OUTBOUND;
196 bool ConvertRequestType(const RequestType& input,
197 UsbDeviceHandle::TransferRequestType* output) {
199 case usb::REQUEST_TYPE_STANDARD:
200 *output = UsbDeviceHandle::STANDARD;
202 case usb::REQUEST_TYPE_CLASS:
203 *output = UsbDeviceHandle::CLASS;
205 case usb::REQUEST_TYPE_VENDOR:
206 *output = UsbDeviceHandle::VENDOR;
208 case usb::REQUEST_TYPE_RESERVED:
209 *output = UsbDeviceHandle::RESERVED;
217 bool ConvertRecipient(const Recipient& input,
218 UsbDeviceHandle::TransferRecipient* output) {
220 case usb::RECIPIENT_DEVICE:
221 *output = UsbDeviceHandle::DEVICE;
223 case usb::RECIPIENT_INTERFACE:
224 *output = UsbDeviceHandle::INTERFACE;
226 case usb::RECIPIENT_ENDPOINT:
227 *output = UsbDeviceHandle::ENDPOINT;
229 case usb::RECIPIENT_OTHER:
230 *output = UsbDeviceHandle::OTHER;
239 bool GetTransferSize(const T& input, size_t* output) {
240 if (input.direction == usb::DIRECTION_IN) {
241 const int* length = input.length.get();
242 if (length && *length >= 0 &&
243 static_cast<size_t>(*length) < kMaxTransferLength) {
247 } else if (input.direction == usb::DIRECTION_OUT) {
248 if (input.data.get()) {
249 *output = input.data->size();
257 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
258 const T& input, UsbEndpointDirection direction, size_t size) {
260 if (size >= kMaxTransferLength)
263 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
264 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
265 // cannot represent a zero-length buffer, while an URB can.
266 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max(
267 static_cast<size_t>(1), size));
269 if (direction == USB_DIRECTION_INBOUND) {
271 } else if (direction == USB_DIRECTION_OUTBOUND) {
272 if (input.data.get() && size <= input.data->size()) {
273 memcpy(buffer->data(), input.data->data(), size);
281 const char* ConvertTransferStatusToErrorString(const UsbTransferStatus status) {
283 case USB_TRANSFER_COMPLETED:
285 case USB_TRANSFER_ERROR:
286 return kErrorGeneric;
287 case USB_TRANSFER_TIMEOUT:
288 return kErrorTimeout;
289 case USB_TRANSFER_CANCELLED:
290 return kErrorCancelled;
291 case USB_TRANSFER_STALLED:
292 return kErrorStalled;
293 case USB_TRANSFER_DISCONNECT:
294 return kErrorDisconnect;
295 case USB_TRANSFER_OVERFLOW:
296 return kErrorOverflow;
297 case USB_TRANSFER_LENGTH_SHORT:
298 return kErrorTransferLength;
305 #if defined(OS_CHROMEOS)
306 void RequestUsbDevicesAccessHelper(
307 ScopedDeviceVector devices,
308 std::vector<scoped_refptr<UsbDevice> >::iterator i,
310 const base::Callback<void(ScopedDeviceVector result)>& callback,
315 i = devices->erase(i);
317 if (i == devices->end()) {
318 callback.Run(devices.Pass());
321 (*i)->RequestUsbAcess(interface_id, base::Bind(RequestUsbDevicesAccessHelper,
322 base::Passed(devices.Pass()),
323 i, interface_id, callback));
326 void RequestUsbDevicesAccess(
327 ScopedDeviceVector devices,
329 const base::Callback<void(ScopedDeviceVector result)>& callback) {
330 if (devices->empty()) {
331 callback.Run(devices.Pass());
334 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
335 (*i)->RequestUsbAcess(
337 base::Bind(RequestUsbDevicesAccessHelper, base::Passed(devices.Pass()),
338 i, interface_id, callback));
340 #endif // OS_CHROMEOS
342 base::DictionaryValue* CreateTransferInfo(
343 UsbTransferStatus status,
344 scoped_refptr<net::IOBuffer> data,
346 base::DictionaryValue* result = new base::DictionaryValue();
347 result->SetInteger(kResultCodeKey, status);
348 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(),
353 base::Value* PopulateConnectionHandle(int handle, int vendor_id,
355 ConnectionHandle result;
356 result.handle = handle;
357 result.vendor_id = vendor_id;
358 result.product_id = product_id;
359 return result.ToValue().release();
362 base::Value* PopulateDevice(UsbDevice* device) {
364 result.device = device->unique_id();
365 result.vendor_id = device->vendor_id();
366 result.product_id = device->product_id();
367 return result.ToValue().release();
370 base::Value* PopulateInterfaceDescriptor(
371 int interface_number,
372 int alternate_setting,
374 int interface_subclass,
375 int interface_protocol,
376 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) {
377 InterfaceDescriptor descriptor;
378 descriptor.interface_number = interface_number;
379 descriptor.alternate_setting = alternate_setting;
380 descriptor.interface_class = interface_class;
381 descriptor.interface_subclass = interface_subclass;
382 descriptor.interface_protocol = interface_protocol;
383 descriptor.endpoints = *endpoints;
384 return descriptor.ToValue().release();
389 namespace extensions {
391 UsbAsyncApiFunction::UsbAsyncApiFunction()
395 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
398 bool UsbAsyncApiFunction::PrePrepare() {
399 manager_ = ApiResourceManager<UsbDeviceResource>::Get(GetProfile());
400 set_work_thread_id(BrowserThread::FILE);
401 return manager_ != NULL;
404 bool UsbAsyncApiFunction::Respond() {
405 return error_.empty();
408 scoped_refptr<UsbDevice>
409 UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError(
410 const Device& input_device) {
411 if (g_device_for_test)
412 return g_device_for_test;
414 const uint16_t vendor_id = input_device.vendor_id;
415 const uint16_t product_id = input_device.product_id;
416 UsbDevicePermission::CheckParam param(
417 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
418 if (!PermissionsData::CheckAPIPermissionWithParam(
419 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
420 LOG(WARNING) << "Insufficient permissions to access device.";
421 CompleteWithError(kErrorPermissionDenied);
425 UsbService* service = UsbService::GetInstance();
427 CompleteWithError(kErrorInitService);
430 scoped_refptr<UsbDevice> device;
432 device = service->GetDeviceById(input_device.device);
435 CompleteWithError(kErrorNoDevice);
439 if (device->vendor_id() != input_device.vendor_id ||
440 device->product_id() != input_device.product_id) {
441 // Must act as if there is no such a device.
442 // Otherwise can be used to finger print unauthorized devices.
443 CompleteWithError(kErrorNoDevice);
450 scoped_refptr<UsbDeviceHandle>
451 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
452 const ConnectionHandle& input_device_handle) {
453 UsbDeviceResource* resource =
454 manager_->Get(extension_->id(), input_device_handle.handle);
456 CompleteWithError(kErrorNoDevice);
460 if (!resource->device() || !resource->device()->device()) {
461 CompleteWithError(kErrorDisconnect);
462 manager_->Remove(extension_->id(), input_device_handle.handle);
466 if (resource->device()->device()->vendor_id() !=
467 input_device_handle.vendor_id ||
468 resource->device()->device()->product_id() !=
469 input_device_handle.product_id) {
470 CompleteWithError(kErrorNoDevice);
474 return resource->device();
477 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
478 manager_->Remove(extension_->id(), api_resource_id);
481 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) {
483 AsyncWorkCompleted();
486 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {}
488 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {}
490 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
491 scoped_refptr<net::IOBuffer> data,
493 if (status != USB_TRANSFER_COMPLETED)
494 SetError(ConvertTransferStatusToErrorString(status));
496 SetResult(CreateTransferInfo(status, data, length));
497 AsyncWorkCompleted();
500 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
501 const Direction& input, UsbEndpointDirection* output) {
502 const bool converted = ConvertDirection(input, output);
504 SetError(kErrorConvertDirection);
508 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
509 const RequestType& input, UsbDeviceHandle::TransferRequestType* output) {
510 const bool converted = ConvertRequestType(input, output);
512 SetError(kErrorConvertRequestType);
516 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
517 const Recipient& input, UsbDeviceHandle::TransferRecipient* output) {
518 const bool converted = ConvertRecipient(input, output);
520 SetError(kErrorConvertRecipient);
524 UsbFindDevicesFunction::UsbFindDevicesFunction() {}
526 UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
528 bool UsbFindDevicesFunction::Prepare() {
529 parameters_ = FindDevices::Params::Create(*args_);
530 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
534 void UsbFindDevicesFunction::AsyncWorkStart() {
535 scoped_ptr<base::ListValue> result(new base::ListValue());
537 if (g_device_for_test) {
538 UsbDeviceResource* const resource = new UsbDeviceResource(
540 g_device_for_test->Open());
542 result->Append(PopulateConnectionHandle(manager_->Add(resource), 0, 0));
543 SetResult(result.release());
544 AsyncWorkCompleted();
548 const uint16_t vendor_id = parameters_->options.vendor_id;
549 const uint16_t product_id = parameters_->options.product_id;
550 int interface_id = parameters_->options.interface_id.get() ?
551 *parameters_->options.interface_id.get() :
552 UsbDevicePermissionData::ANY_INTERFACE;
553 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
554 if (!PermissionsData::CheckAPIPermissionWithParam(
555 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
556 LOG(WARNING) << "Insufficient permissions to access device.";
557 CompleteWithError(kErrorPermissionDenied);
561 UsbService *service = UsbService::GetInstance();
563 CompleteWithError(kErrorInitService);
567 ScopedDeviceVector devices(new DeviceVector());
568 service->GetDevices(devices.get());
570 for (DeviceVector::iterator it = devices->begin();
571 it != devices->end();) {
572 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
573 it = devices->erase(it);
579 #if defined(OS_CHROMEOS)
580 RequestUsbDevicesAccess(
581 devices.Pass(), interface_id,
582 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
584 OpenDevices(devices.Pass());
585 #endif // OS_CHROMEOS
588 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) {
589 base::ListValue* result = new base::ListValue();
591 for (size_t i = 0; i < devices->size(); ++i) {
592 scoped_refptr<UsbDeviceHandle> device_handle =
593 devices->at(i)->Open();
595 device_handles_.push_back(device_handle);
598 for (size_t i = 0; i < device_handles_.size(); ++i) {
599 UsbDeviceHandle* const device_handle = device_handles_[i].get();
600 UsbDeviceResource* const resource =
601 new UsbDeviceResource(extension_->id(), device_handle);
603 result->Append(PopulateConnectionHandle(manager_->Add(resource),
604 parameters_->options.vendor_id,
605 parameters_->options.product_id));
609 AsyncWorkCompleted();
612 UsbGetDevicesFunction::UsbGetDevicesFunction() {
615 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
618 void UsbGetDevicesFunction::SetDeviceForTest(UsbDevice* device) {
619 g_device_for_test = device;
622 bool UsbGetDevicesFunction::Prepare() {
623 parameters_ = GetDevices::Params::Create(*args_);
624 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
628 void UsbGetDevicesFunction::AsyncWorkStart() {
629 scoped_ptr<base::ListValue> result(new base::ListValue());
631 if (g_device_for_test) {
632 result->Append(PopulateDevice(g_device_for_test));
633 SetResult(result.release());
634 AsyncWorkCompleted();
638 const uint16_t vendor_id = parameters_->options.vendor_id;
639 const uint16_t product_id = parameters_->options.product_id;
640 UsbDevicePermission::CheckParam param(
641 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
642 if (!PermissionsData::CheckAPIPermissionWithParam(
643 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
644 LOG(WARNING) << "Insufficient permissions to access device.";
645 CompleteWithError(kErrorPermissionDenied);
649 UsbService* service = UsbService::GetInstance();
651 CompleteWithError(kErrorInitService);
655 DeviceVector devices;
656 service->GetDevices(&devices);
658 for (DeviceVector::iterator it = devices.begin(); it != devices.end();) {
659 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
660 it = devices.erase(it);
666 for (size_t i = 0; i < devices.size(); ++i) {
667 result->Append(PopulateDevice(devices[i].get()));
670 SetResult(result.release());
671 AsyncWorkCompleted();
674 UsbRequestAccessFunction::UsbRequestAccessFunction() {}
676 UsbRequestAccessFunction::~UsbRequestAccessFunction() {}
678 bool UsbRequestAccessFunction::Prepare() {
679 parameters_ = RequestAccess::Params::Create(*args_);
680 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
684 void UsbRequestAccessFunction::AsyncWorkStart() {
685 #if defined(OS_CHROMEOS)
686 scoped_refptr<UsbDevice> device =
687 GetDeviceOrOrCompleteWithError(parameters_->device);
690 device->RequestUsbAcess(parameters_->interface_id,
691 base::Bind(&UsbRequestAccessFunction::OnCompleted,
694 SetResult(new base::FundamentalValue(false));
695 CompleteWithError(kErrorNotSupported);
696 #endif // OS_CHROMEOS
699 void UsbRequestAccessFunction::OnCompleted(bool success) {
700 SetResult(new base::FundamentalValue(success));
701 AsyncWorkCompleted();
704 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {}
706 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {}
708 bool UsbOpenDeviceFunction::Prepare() {
709 parameters_ = OpenDevice::Params::Create(*args_);
710 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
714 void UsbOpenDeviceFunction::AsyncWorkStart() {
715 scoped_refptr<UsbDevice> device =
716 GetDeviceOrOrCompleteWithError(parameters_->device);
719 handle_ = device->Open();
721 SetError(kErrorOpen);
722 AsyncWorkCompleted();
726 SetResult(PopulateConnectionHandle(
727 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)),
728 handle_->device()->vendor_id(),
729 handle_->device()->product_id()));
730 AsyncWorkCompleted();
733 UsbListInterfacesFunction::UsbListInterfacesFunction() {}
735 UsbListInterfacesFunction::~UsbListInterfacesFunction() {}
737 bool UsbListInterfacesFunction::Prepare() {
738 parameters_ = ListInterfaces::Params::Create(*args_);
739 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
743 void UsbListInterfacesFunction::AsyncWorkStart() {
744 scoped_refptr<UsbDeviceHandle> device_handle =
745 GetDeviceHandleOrCompleteWithError(parameters_->handle);
746 if (!device_handle) return;
748 scoped_refptr<UsbConfigDescriptor> config =
749 device_handle->device()->ListInterfaces();
752 SetError(kErrorCannotListInterfaces);
753 AsyncWorkCompleted();
757 result_.reset(new base::ListValue());
759 for (size_t i = 0, num_interfaces = config->GetNumInterfaces();
760 i < num_interfaces; ++i) {
761 scoped_refptr<const UsbInterfaceDescriptor>
762 usb_interface(config->GetInterface(i));
763 for (size_t j = 0, num_descriptors = usb_interface->GetNumAltSettings();
764 j < num_descriptors; ++j) {
765 scoped_refptr<const UsbInterfaceAltSettingDescriptor> descriptor
766 = usb_interface->GetAltSetting(j);
767 std::vector<linked_ptr<EndpointDescriptor> > endpoints;
768 for (size_t k = 0, num_endpoints = descriptor->GetNumEndpoints();
769 k < num_endpoints; k++) {
770 scoped_refptr<const UsbEndpointDescriptor> endpoint
771 = descriptor->GetEndpoint(k);
772 linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor());
776 SynchronizationType synchronization;
779 if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) ||
780 !ConvertDirectionSafely(endpoint->GetDirection(), &direction) ||
781 !ConvertSynchronizationTypeSafely(
782 endpoint->GetSynchronizationType(), &synchronization) ||
783 !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) {
784 SetError(kErrorCannotListInterfaces);
785 AsyncWorkCompleted();
789 endpoint_desc->address = endpoint->GetAddress();
790 endpoint_desc->type = type;
791 endpoint_desc->direction = direction;
792 endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize();
793 endpoint_desc->synchronization = synchronization;
794 endpoint_desc->usage = usage;
796 int* polling_interval = new int;
797 endpoint_desc->polling_interval.reset(polling_interval);
798 *polling_interval = endpoint->GetPollingInterval();
800 endpoints.push_back(endpoint_desc);
803 result_->Append(PopulateInterfaceDescriptor(
804 descriptor->GetInterfaceNumber(),
805 descriptor->GetAlternateSetting(),
806 descriptor->GetInterfaceClass(),
807 descriptor->GetInterfaceSubclass(),
808 descriptor->GetInterfaceProtocol(),
813 SetResult(result_.release());
814 AsyncWorkCompleted();
817 bool UsbListInterfacesFunction::ConvertDirectionSafely(
818 const UsbEndpointDirection& input,
819 usb::Direction* output) {
820 const bool converted = ConvertDirectionToApi(input, output);
822 SetError(kErrorConvertDirection);
826 bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely(
827 const UsbSynchronizationType& input,
828 usb::SynchronizationType* output) {
829 const bool converted = ConvertSynchronizationTypeToApi(input, output);
831 SetError(kErrorConvertSynchronizationType);
835 bool UsbListInterfacesFunction::ConvertTransferTypeSafely(
836 const UsbTransferType& input,
837 usb::TransferType* output) {
838 const bool converted = ConvertTransferTypeToApi(input, output);
840 SetError(kErrorConvertTransferType);
844 bool UsbListInterfacesFunction::ConvertUsageTypeSafely(
845 const UsbUsageType& input,
846 usb::UsageType* output) {
847 const bool converted = ConvertUsageTypeToApi(input, output);
849 SetError(kErrorConvertUsageType);
853 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {}
855 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {}
857 bool UsbCloseDeviceFunction::Prepare() {
858 parameters_ = CloseDevice::Params::Create(*args_);
859 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
863 void UsbCloseDeviceFunction::AsyncWorkStart() {
864 scoped_refptr<UsbDeviceHandle> device_handle =
865 GetDeviceHandleOrCompleteWithError(parameters_->handle);
866 if (!device_handle) return;
868 device_handle->Close();
869 RemoveUsbDeviceResource(parameters_->handle.handle);
870 AsyncWorkCompleted();
873 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {}
875 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {}
877 bool UsbClaimInterfaceFunction::Prepare() {
878 parameters_ = ClaimInterface::Params::Create(*args_);
879 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
883 void UsbClaimInterfaceFunction::AsyncWorkStart() {
884 scoped_refptr<UsbDeviceHandle> device_handle =
885 GetDeviceHandleOrCompleteWithError(parameters_->handle);
886 if (!device_handle) return;
888 bool success = device_handle->ClaimInterface(parameters_->interface_number);
891 SetError(kErrorCannotClaimInterface);
892 AsyncWorkCompleted();
895 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {}
897 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {}
899 bool UsbReleaseInterfaceFunction::Prepare() {
900 parameters_ = ReleaseInterface::Params::Create(*args_);
901 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
905 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
906 scoped_refptr<UsbDeviceHandle> device_handle =
907 GetDeviceHandleOrCompleteWithError(parameters_->handle);
908 if (!device_handle) return;
910 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
912 SetError(kErrorCannotReleaseInterface);
913 AsyncWorkCompleted();
916 UsbSetInterfaceAlternateSettingFunction::
917 UsbSetInterfaceAlternateSettingFunction() {}
919 UsbSetInterfaceAlternateSettingFunction::
920 ~UsbSetInterfaceAlternateSettingFunction() {}
922 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
923 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
924 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
928 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
929 scoped_refptr<UsbDeviceHandle> device_handle =
930 GetDeviceHandleOrCompleteWithError(parameters_->handle);
931 if (!device_handle) return;
933 bool success = device_handle->SetInterfaceAlternateSetting(
934 parameters_->interface_number,
935 parameters_->alternate_setting);
937 SetError(kErrorCannotSetInterfaceAlternateSetting);
939 AsyncWorkCompleted();
942 UsbControlTransferFunction::UsbControlTransferFunction() {}
944 UsbControlTransferFunction::~UsbControlTransferFunction() {}
946 bool UsbControlTransferFunction::Prepare() {
947 parameters_ = ControlTransfer::Params::Create(*args_);
948 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
952 void UsbControlTransferFunction::AsyncWorkStart() {
953 scoped_refptr<UsbDeviceHandle> device_handle =
954 GetDeviceHandleOrCompleteWithError(parameters_->handle);
955 if (!device_handle) return;
957 const ControlTransferInfo& transfer = parameters_->transfer_info;
959 UsbEndpointDirection direction;
960 UsbDeviceHandle::TransferRequestType request_type;
961 UsbDeviceHandle::TransferRecipient recipient;
964 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
965 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
966 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
967 AsyncWorkCompleted();
971 if (!GetTransferSize(transfer, &size)) {
972 CompleteWithError(kErrorInvalidTransferLength);
976 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
977 transfer, direction, size);
979 CompleteWithError(kErrorMalformedParameters);
983 device_handle->ControlTransfer(
993 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
996 UsbBulkTransferFunction::UsbBulkTransferFunction() {}
998 UsbBulkTransferFunction::~UsbBulkTransferFunction() {}
1000 bool UsbBulkTransferFunction::Prepare() {
1001 parameters_ = BulkTransfer::Params::Create(*args_);
1002 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1006 void UsbBulkTransferFunction::AsyncWorkStart() {
1007 scoped_refptr<UsbDeviceHandle> device_handle =
1008 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1009 if (!device_handle) return;
1011 const GenericTransferInfo& transfer = parameters_->transfer_info;
1013 UsbEndpointDirection direction;
1016 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1017 AsyncWorkCompleted();
1021 if (!GetTransferSize(transfer, &size)) {
1022 CompleteWithError(kErrorInvalidTransferLength);
1026 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1027 transfer, direction, size);
1028 if (!buffer.get()) {
1029 CompleteWithError(kErrorMalformedParameters);
1033 device_handle->BulkTransfer(
1039 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1042 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {}
1044 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {}
1046 bool UsbInterruptTransferFunction::Prepare() {
1047 parameters_ = InterruptTransfer::Params::Create(*args_);
1048 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1052 void UsbInterruptTransferFunction::AsyncWorkStart() {
1053 scoped_refptr<UsbDeviceHandle> device_handle =
1054 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1055 if (!device_handle) return;
1057 const GenericTransferInfo& transfer = parameters_->transfer_info;
1059 UsbEndpointDirection direction;
1062 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1063 AsyncWorkCompleted();
1067 if (!GetTransferSize(transfer, &size)) {
1068 CompleteWithError(kErrorInvalidTransferLength);
1072 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1073 transfer, direction, size);
1074 if (!buffer.get()) {
1075 CompleteWithError(kErrorMalformedParameters);
1079 device_handle->InterruptTransfer(
1085 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1088 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {}
1090 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {}
1092 bool UsbIsochronousTransferFunction::Prepare() {
1093 parameters_ = IsochronousTransfer::Params::Create(*args_);
1094 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1098 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1099 scoped_refptr<UsbDeviceHandle> device_handle =
1100 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1101 if (!device_handle) return;
1103 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1104 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1107 UsbEndpointDirection direction;
1109 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1110 AsyncWorkCompleted();
1113 if (!GetTransferSize(generic_transfer, &size)) {
1114 CompleteWithError(kErrorInvalidTransferLength);
1117 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1118 CompleteWithError(kErrorInvalidNumberOfPackets);
1121 unsigned int packets = transfer.packets;
1122 if (transfer.packet_length < 0 ||
1123 transfer.packet_length >= kMaxPacketLength) {
1124 CompleteWithError(kErrorInvalidPacketLength);
1127 unsigned int packet_length = transfer.packet_length;
1128 const uint64 total_length = packets * packet_length;
1129 if (packets > size || total_length > size) {
1130 CompleteWithError(kErrorTransferLength);
1134 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1135 generic_transfer, direction, size);
1136 if (!buffer.get()) {
1137 CompleteWithError(kErrorMalformedParameters);
1141 device_handle->IsochronousTransfer(
1143 generic_transfer.endpoint,
1149 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1152 UsbResetDeviceFunction::UsbResetDeviceFunction() {}
1154 UsbResetDeviceFunction::~UsbResetDeviceFunction() {}
1156 bool UsbResetDeviceFunction::Prepare() {
1157 parameters_ = ResetDevice::Params::Create(*args_);
1158 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1162 void UsbResetDeviceFunction::AsyncWorkStart() {
1163 scoped_refptr<UsbDeviceHandle> device_handle =
1164 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1165 if (!device_handle) return;
1167 bool success = device_handle->ResetDevice();
1169 device_handle->Close();
1170 RemoveUsbDeviceResource(parameters_->handle.handle);
1171 SetResult(new base::FundamentalValue(false));
1172 CompleteWithError(kErrorResetDevice);
1176 SetResult(new base::FundamentalValue(true));
1177 AsyncWorkCompleted();
1180 } // namespace extensions