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/usb/usb_device_handle.h"
14 #include "chrome/browser/usb/usb_service.h"
15 #include "chrome/common/extensions/api/usb.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/common/permissions/permissions_data.h"
18 #include "extensions/common/permissions/usb_device_permission.h"
20 namespace usb = extensions::api::usb;
21 namespace BulkTransfer = usb::BulkTransfer;
22 namespace ClaimInterface = usb::ClaimInterface;
23 namespace CloseDevice = usb::CloseDevice;
24 namespace ControlTransfer = usb::ControlTransfer;
25 namespace FindDevices = usb::FindDevices;
26 namespace GetDevices = usb::GetDevices;
27 namespace InterruptTransfer = usb::InterruptTransfer;
28 namespace IsochronousTransfer = usb::IsochronousTransfer;
29 namespace ListInterfaces = usb::ListInterfaces;
30 namespace OpenDevice = usb::OpenDevice;
31 namespace ReleaseInterface = usb::ReleaseInterface;
32 namespace RequestAccess = usb::RequestAccess;
33 namespace ResetDevice = usb::ResetDevice;
34 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
36 using content::BrowserThread;
39 using usb::ControlTransferInfo;
40 using usb::ConnectionHandle;
43 using usb::EndpointDescriptor;
44 using usb::GenericTransferInfo;
45 using usb::InterfaceDescriptor;
46 using usb::IsochronousTransferInfo;
48 using usb::RequestType;
49 using usb::SynchronizationType;
50 using usb::TransferType;
53 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
54 typedef scoped_ptr<DeviceVector> ScopedDeviceVector;
58 const char kDataKey[] = "data";
59 const char kResultCodeKey[] = "resultCode";
61 const char kErrorInitService[] = "Failed to initialize USB service.";
63 const char kErrorOpen[] = "Failed to open device.";
64 const char kErrorCancelled[] = "Transfer was cancelled.";
65 const char kErrorDisconnect[] = "Device disconnected.";
66 const char kErrorGeneric[] = "Transfer failed.";
67 #if !defined(OS_CHROMEOS)
68 const char kErrorNotSupported[] = "Not supported on this platform.";
70 const char kErrorOverflow[] = "Inbound transfer overflow.";
71 const char kErrorStalled[] = "Transfer stalled.";
72 const char kErrorTimeout[] = "Transfer timed out.";
73 const char kErrorTransferLength[] = "Transfer length is insufficient.";
75 const char kErrorCannotListInterfaces[] = "Error listing interfaces.";
76 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
77 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
78 const char kErrorCannotSetInterfaceAlternateSetting[] =
79 "Error setting alternate interface setting.";
80 const char kErrorConvertDirection[] = "Invalid transfer direction.";
81 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
82 const char kErrorConvertRequestType[] = "Invalid request type.";
83 const char kErrorConvertSynchronizationType[] = "Invalid synchronization type";
84 const char kErrorConvertTransferType[] = "Invalid endpoint type.";
85 const char kErrorConvertUsageType[] = "Invalid usage type.";
86 const char kErrorMalformedParameters[] = "Error parsing parameters.";
87 const char kErrorNoDevice[] = "No such device.";
88 const char kErrorPermissionDenied[] =
89 "Permission to access device was denied";
90 const char kErrorInvalidTransferLength[] =
91 "Transfer length must be a positive number less than 104,857,600.";
92 const char kErrorInvalidNumberOfPackets[] =
93 "Number of packets must be a positive number less than 4,194,304.";
94 const char kErrorInvalidPacketLength[] = "Packet length must be a "
95 "positive number less than 65,536.";
96 const char kErrorResetDevice[] =
97 "Error resetting the device. The device has been closed.";
99 const size_t kMaxTransferLength = 100 * 1024 * 1024;
100 const int kMaxPackets = 4 * 1024 * 1024;
101 const int kMaxPacketLength = 64 * 1024;
103 UsbDevice* g_device_for_test = NULL;
105 bool ConvertDirectionToApi(const UsbEndpointDirection& input,
108 case USB_DIRECTION_INBOUND:
109 *output = usb::DIRECTION_IN;
111 case USB_DIRECTION_OUTBOUND:
112 *output = usb::DIRECTION_OUT;
120 bool ConvertSynchronizationTypeToApi(const UsbSynchronizationType& input,
121 usb::SynchronizationType* output) {
123 case USB_SYNCHRONIZATION_NONE:
124 *output = usb::SYNCHRONIZATION_TYPE_NONE;
126 case USB_SYNCHRONIZATION_ASYNCHRONOUS:
127 *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
129 case USB_SYNCHRONIZATION_ADAPTIVE:
130 *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
132 case USB_SYNCHRONIZATION_SYNCHRONOUS:
133 *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
141 bool ConvertTransferTypeToApi(
142 const UsbTransferType& input,
143 usb::TransferType* output) {
145 case USB_TRANSFER_CONTROL:
146 *output = usb::TRANSFER_TYPE_CONTROL;
148 case USB_TRANSFER_INTERRUPT:
149 *output = usb::TRANSFER_TYPE_INTERRUPT;
151 case USB_TRANSFER_ISOCHRONOUS:
152 *output = usb::TRANSFER_TYPE_ISOCHRONOUS;
154 case USB_TRANSFER_BULK:
155 *output = usb::TRANSFER_TYPE_BULK;
163 bool ConvertUsageTypeToApi(const UsbUsageType& input, usb::UsageType* output) {
166 *output = usb::USAGE_TYPE_DATA;
168 case USB_USAGE_FEEDBACK:
169 *output = usb::USAGE_TYPE_FEEDBACK;
171 case USB_USAGE_EXPLICIT_FEEDBACK:
172 *output = usb::USAGE_TYPE_EXPLICITFEEDBACK;
180 bool ConvertDirection(const Direction& input,
181 UsbEndpointDirection* output) {
183 case usb::DIRECTION_IN:
184 *output = USB_DIRECTION_INBOUND;
186 case usb::DIRECTION_OUT:
187 *output = USB_DIRECTION_OUTBOUND;
195 bool ConvertRequestType(const RequestType& input,
196 UsbDeviceHandle::TransferRequestType* output) {
198 case usb::REQUEST_TYPE_STANDARD:
199 *output = UsbDeviceHandle::STANDARD;
201 case usb::REQUEST_TYPE_CLASS:
202 *output = UsbDeviceHandle::CLASS;
204 case usb::REQUEST_TYPE_VENDOR:
205 *output = UsbDeviceHandle::VENDOR;
207 case usb::REQUEST_TYPE_RESERVED:
208 *output = UsbDeviceHandle::RESERVED;
216 bool ConvertRecipient(const Recipient& input,
217 UsbDeviceHandle::TransferRecipient* output) {
219 case usb::RECIPIENT_DEVICE:
220 *output = UsbDeviceHandle::DEVICE;
222 case usb::RECIPIENT_INTERFACE:
223 *output = UsbDeviceHandle::INTERFACE;
225 case usb::RECIPIENT_ENDPOINT:
226 *output = UsbDeviceHandle::ENDPOINT;
228 case usb::RECIPIENT_OTHER:
229 *output = UsbDeviceHandle::OTHER;
238 bool GetTransferSize(const T& input, size_t* output) {
239 if (input.direction == usb::DIRECTION_IN) {
240 const int* length = input.length.get();
241 if (length && *length >= 0 &&
242 static_cast<size_t>(*length) < kMaxTransferLength) {
246 } else if (input.direction == usb::DIRECTION_OUT) {
247 if (input.data.get()) {
248 *output = input.data->size();
256 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
257 const T& input, UsbEndpointDirection direction, size_t size) {
259 if (size >= kMaxTransferLength)
262 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
263 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
264 // cannot represent a zero-length buffer, while an URB can.
265 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max(
266 static_cast<size_t>(1), size));
268 if (direction == USB_DIRECTION_INBOUND) {
270 } else if (direction == USB_DIRECTION_OUTBOUND) {
271 if (input.data.get() && size <= input.data->size()) {
272 memcpy(buffer->data(), input.data->data(), size);
280 const char* ConvertTransferStatusToErrorString(const UsbTransferStatus status) {
282 case USB_TRANSFER_COMPLETED:
284 case USB_TRANSFER_ERROR:
285 return kErrorGeneric;
286 case USB_TRANSFER_TIMEOUT:
287 return kErrorTimeout;
288 case USB_TRANSFER_CANCELLED:
289 return kErrorCancelled;
290 case USB_TRANSFER_STALLED:
291 return kErrorStalled;
292 case USB_TRANSFER_DISCONNECT:
293 return kErrorDisconnect;
294 case USB_TRANSFER_OVERFLOW:
295 return kErrorOverflow;
296 case USB_TRANSFER_LENGTH_SHORT:
297 return kErrorTransferLength;
304 #if defined(OS_CHROMEOS)
305 void RequestUsbDevicesAccessHelper(
306 ScopedDeviceVector devices,
307 std::vector<scoped_refptr<UsbDevice> >::iterator i,
309 const base::Callback<void(ScopedDeviceVector result)>& callback,
314 i = devices->erase(i);
316 if (i == devices->end()) {
317 callback.Run(devices.Pass());
320 (*i)->RequestUsbAcess(interface_id, base::Bind(RequestUsbDevicesAccessHelper,
321 base::Passed(devices.Pass()),
322 i, interface_id, callback));
325 void RequestUsbDevicesAccess(
326 ScopedDeviceVector devices,
328 const base::Callback<void(ScopedDeviceVector result)>& callback) {
329 if (devices->empty()) {
330 callback.Run(devices.Pass());
333 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
334 (*i)->RequestUsbAcess(
336 base::Bind(RequestUsbDevicesAccessHelper, base::Passed(devices.Pass()),
337 i, interface_id, callback));
339 #endif // OS_CHROMEOS
341 base::DictionaryValue* CreateTransferInfo(
342 UsbTransferStatus status,
343 scoped_refptr<net::IOBuffer> data,
345 base::DictionaryValue* result = new base::DictionaryValue();
346 result->SetInteger(kResultCodeKey, status);
347 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(),
352 base::Value* PopulateConnectionHandle(int handle, int vendor_id,
354 ConnectionHandle result;
355 result.handle = handle;
356 result.vendor_id = vendor_id;
357 result.product_id = product_id;
358 return result.ToValue().release();
361 base::Value* PopulateDevice(UsbDevice* device) {
363 result.device = device->unique_id();
364 result.vendor_id = device->vendor_id();
365 result.product_id = device->product_id();
366 return result.ToValue().release();
369 base::Value* PopulateInterfaceDescriptor(
370 int interface_number,
371 int alternate_setting,
373 int interface_subclass,
374 int interface_protocol,
375 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) {
376 InterfaceDescriptor descriptor;
377 descriptor.interface_number = interface_number;
378 descriptor.alternate_setting = alternate_setting;
379 descriptor.interface_class = interface_class;
380 descriptor.interface_subclass = interface_subclass;
381 descriptor.interface_protocol = interface_protocol;
382 descriptor.endpoints = *endpoints;
383 return descriptor.ToValue().release();
388 namespace extensions {
390 UsbAsyncApiFunction::UsbAsyncApiFunction()
394 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
397 bool UsbAsyncApiFunction::PrePrepare() {
398 manager_ = ApiResourceManager<UsbDeviceResource>::Get(browser_context());
399 set_work_thread_id(BrowserThread::FILE);
400 return manager_ != NULL;
403 bool UsbAsyncApiFunction::Respond() {
404 return error_.empty();
407 scoped_refptr<UsbDevice>
408 UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError(
409 const Device& input_device) {
410 if (g_device_for_test)
411 return g_device_for_test;
413 const uint16_t vendor_id = input_device.vendor_id;
414 const uint16_t product_id = input_device.product_id;
415 UsbDevicePermission::CheckParam param(
416 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
417 if (!PermissionsData::CheckAPIPermissionWithParam(
418 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
419 LOG(WARNING) << "Insufficient permissions to access device.";
420 CompleteWithError(kErrorPermissionDenied);
424 UsbService* service = UsbService::GetInstance();
426 CompleteWithError(kErrorInitService);
429 scoped_refptr<UsbDevice> device;
431 device = service->GetDeviceById(input_device.device);
434 CompleteWithError(kErrorNoDevice);
438 if (device->vendor_id() != input_device.vendor_id ||
439 device->product_id() != input_device.product_id) {
440 // Must act as if there is no such a device.
441 // Otherwise can be used to finger print unauthorized devices.
442 CompleteWithError(kErrorNoDevice);
449 scoped_refptr<UsbDeviceHandle>
450 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
451 const ConnectionHandle& input_device_handle) {
452 UsbDeviceResource* resource =
453 manager_->Get(extension_->id(), input_device_handle.handle);
455 CompleteWithError(kErrorNoDevice);
459 if (!resource->device() || !resource->device()->device()) {
460 CompleteWithError(kErrorDisconnect);
461 manager_->Remove(extension_->id(), input_device_handle.handle);
465 if (resource->device()->device()->vendor_id() !=
466 input_device_handle.vendor_id ||
467 resource->device()->device()->product_id() !=
468 input_device_handle.product_id) {
469 CompleteWithError(kErrorNoDevice);
473 return resource->device();
476 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
477 manager_->Remove(extension_->id(), api_resource_id);
480 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) {
482 AsyncWorkCompleted();
485 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {}
487 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {}
489 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
490 scoped_refptr<net::IOBuffer> data,
492 if (status != USB_TRANSFER_COMPLETED)
493 SetError(ConvertTransferStatusToErrorString(status));
495 SetResult(CreateTransferInfo(status, data, length));
496 AsyncWorkCompleted();
499 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
500 const Direction& input, UsbEndpointDirection* output) {
501 const bool converted = ConvertDirection(input, output);
503 SetError(kErrorConvertDirection);
507 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
508 const RequestType& input, UsbDeviceHandle::TransferRequestType* output) {
509 const bool converted = ConvertRequestType(input, output);
511 SetError(kErrorConvertRequestType);
515 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
516 const Recipient& input, UsbDeviceHandle::TransferRecipient* output) {
517 const bool converted = ConvertRecipient(input, output);
519 SetError(kErrorConvertRecipient);
523 UsbFindDevicesFunction::UsbFindDevicesFunction() {}
525 UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
527 bool UsbFindDevicesFunction::Prepare() {
528 parameters_ = FindDevices::Params::Create(*args_);
529 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
533 void UsbFindDevicesFunction::AsyncWorkStart() {
534 scoped_ptr<base::ListValue> result(new base::ListValue());
536 if (g_device_for_test) {
537 UsbDeviceResource* const resource = new UsbDeviceResource(
539 g_device_for_test->Open());
541 result->Append(PopulateConnectionHandle(manager_->Add(resource), 0, 0));
542 SetResult(result.release());
543 AsyncWorkCompleted();
547 const uint16_t vendor_id = parameters_->options.vendor_id;
548 const uint16_t product_id = parameters_->options.product_id;
549 int interface_id = parameters_->options.interface_id.get() ?
550 *parameters_->options.interface_id.get() :
551 UsbDevicePermissionData::ANY_INTERFACE;
552 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
553 if (!PermissionsData::CheckAPIPermissionWithParam(
554 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
555 LOG(WARNING) << "Insufficient permissions to access device.";
556 CompleteWithError(kErrorPermissionDenied);
560 UsbService *service = UsbService::GetInstance();
562 CompleteWithError(kErrorInitService);
566 ScopedDeviceVector devices(new DeviceVector());
567 service->GetDevices(devices.get());
569 for (DeviceVector::iterator it = devices->begin();
570 it != devices->end();) {
571 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
572 it = devices->erase(it);
578 #if defined(OS_CHROMEOS)
579 RequestUsbDevicesAccess(
580 devices.Pass(), interface_id,
581 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
583 OpenDevices(devices.Pass());
584 #endif // OS_CHROMEOS
587 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) {
588 base::ListValue* result = new base::ListValue();
590 for (size_t i = 0; i < devices->size(); ++i) {
591 scoped_refptr<UsbDeviceHandle> device_handle =
592 devices->at(i)->Open();
594 device_handles_.push_back(device_handle);
597 for (size_t i = 0; i < device_handles_.size(); ++i) {
598 UsbDeviceHandle* const device_handle = device_handles_[i].get();
599 UsbDeviceResource* const resource =
600 new UsbDeviceResource(extension_->id(), device_handle);
602 result->Append(PopulateConnectionHandle(manager_->Add(resource),
603 parameters_->options.vendor_id,
604 parameters_->options.product_id));
608 AsyncWorkCompleted();
611 UsbGetDevicesFunction::UsbGetDevicesFunction() {
614 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
617 void UsbGetDevicesFunction::SetDeviceForTest(UsbDevice* device) {
618 g_device_for_test = device;
621 bool UsbGetDevicesFunction::Prepare() {
622 parameters_ = GetDevices::Params::Create(*args_);
623 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
627 void UsbGetDevicesFunction::AsyncWorkStart() {
628 scoped_ptr<base::ListValue> result(new base::ListValue());
630 if (g_device_for_test) {
631 result->Append(PopulateDevice(g_device_for_test));
632 SetResult(result.release());
633 AsyncWorkCompleted();
637 const uint16_t vendor_id = parameters_->options.vendor_id;
638 const uint16_t product_id = parameters_->options.product_id;
639 UsbDevicePermission::CheckParam param(
640 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
641 if (!PermissionsData::CheckAPIPermissionWithParam(
642 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
643 LOG(WARNING) << "Insufficient permissions to access device.";
644 CompleteWithError(kErrorPermissionDenied);
648 UsbService* service = UsbService::GetInstance();
650 CompleteWithError(kErrorInitService);
654 DeviceVector devices;
655 service->GetDevices(&devices);
657 for (DeviceVector::iterator it = devices.begin(); it != devices.end();) {
658 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
659 it = devices.erase(it);
665 for (size_t i = 0; i < devices.size(); ++i) {
666 result->Append(PopulateDevice(devices[i].get()));
669 SetResult(result.release());
670 AsyncWorkCompleted();
673 UsbRequestAccessFunction::UsbRequestAccessFunction() {}
675 UsbRequestAccessFunction::~UsbRequestAccessFunction() {}
677 bool UsbRequestAccessFunction::Prepare() {
678 parameters_ = RequestAccess::Params::Create(*args_);
679 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
683 void UsbRequestAccessFunction::AsyncWorkStart() {
684 #if defined(OS_CHROMEOS)
685 scoped_refptr<UsbDevice> device =
686 GetDeviceOrOrCompleteWithError(parameters_->device);
689 device->RequestUsbAcess(parameters_->interface_id,
690 base::Bind(&UsbRequestAccessFunction::OnCompleted,
693 SetResult(new base::FundamentalValue(false));
694 CompleteWithError(kErrorNotSupported);
695 #endif // OS_CHROMEOS
698 void UsbRequestAccessFunction::OnCompleted(bool success) {
699 SetResult(new base::FundamentalValue(success));
700 AsyncWorkCompleted();
703 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {}
705 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {}
707 bool UsbOpenDeviceFunction::Prepare() {
708 parameters_ = OpenDevice::Params::Create(*args_);
709 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
713 void UsbOpenDeviceFunction::AsyncWorkStart() {
714 scoped_refptr<UsbDevice> device =
715 GetDeviceOrOrCompleteWithError(parameters_->device);
718 handle_ = device->Open();
720 SetError(kErrorOpen);
721 AsyncWorkCompleted();
725 SetResult(PopulateConnectionHandle(
726 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)),
727 handle_->device()->vendor_id(),
728 handle_->device()->product_id()));
729 AsyncWorkCompleted();
732 UsbListInterfacesFunction::UsbListInterfacesFunction() {}
734 UsbListInterfacesFunction::~UsbListInterfacesFunction() {}
736 bool UsbListInterfacesFunction::Prepare() {
737 parameters_ = ListInterfaces::Params::Create(*args_);
738 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
742 void UsbListInterfacesFunction::AsyncWorkStart() {
743 scoped_refptr<UsbDeviceHandle> device_handle =
744 GetDeviceHandleOrCompleteWithError(parameters_->handle);
745 if (!device_handle) return;
747 scoped_refptr<UsbConfigDescriptor> config =
748 device_handle->device()->ListInterfaces();
751 SetError(kErrorCannotListInterfaces);
752 AsyncWorkCompleted();
756 result_.reset(new base::ListValue());
758 for (size_t i = 0, num_interfaces = config->GetNumInterfaces();
759 i < num_interfaces; ++i) {
760 scoped_refptr<const UsbInterfaceDescriptor>
761 usb_interface(config->GetInterface(i));
762 for (size_t j = 0, num_descriptors = usb_interface->GetNumAltSettings();
763 j < num_descriptors; ++j) {
764 scoped_refptr<const UsbInterfaceAltSettingDescriptor> descriptor
765 = usb_interface->GetAltSetting(j);
766 std::vector<linked_ptr<EndpointDescriptor> > endpoints;
767 for (size_t k = 0, num_endpoints = descriptor->GetNumEndpoints();
768 k < num_endpoints; k++) {
769 scoped_refptr<const UsbEndpointDescriptor> endpoint
770 = descriptor->GetEndpoint(k);
771 linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor());
775 SynchronizationType synchronization;
778 if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) ||
779 !ConvertDirectionSafely(endpoint->GetDirection(), &direction) ||
780 !ConvertSynchronizationTypeSafely(
781 endpoint->GetSynchronizationType(), &synchronization) ||
782 !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) {
783 SetError(kErrorCannotListInterfaces);
784 AsyncWorkCompleted();
788 endpoint_desc->address = endpoint->GetAddress();
789 endpoint_desc->type = type;
790 endpoint_desc->direction = direction;
791 endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize();
792 endpoint_desc->synchronization = synchronization;
793 endpoint_desc->usage = usage;
795 int* polling_interval = new int;
796 endpoint_desc->polling_interval.reset(polling_interval);
797 *polling_interval = endpoint->GetPollingInterval();
799 endpoints.push_back(endpoint_desc);
802 result_->Append(PopulateInterfaceDescriptor(
803 descriptor->GetInterfaceNumber(),
804 descriptor->GetAlternateSetting(),
805 descriptor->GetInterfaceClass(),
806 descriptor->GetInterfaceSubclass(),
807 descriptor->GetInterfaceProtocol(),
812 SetResult(result_.release());
813 AsyncWorkCompleted();
816 bool UsbListInterfacesFunction::ConvertDirectionSafely(
817 const UsbEndpointDirection& input,
818 usb::Direction* output) {
819 const bool converted = ConvertDirectionToApi(input, output);
821 SetError(kErrorConvertDirection);
825 bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely(
826 const UsbSynchronizationType& input,
827 usb::SynchronizationType* output) {
828 const bool converted = ConvertSynchronizationTypeToApi(input, output);
830 SetError(kErrorConvertSynchronizationType);
834 bool UsbListInterfacesFunction::ConvertTransferTypeSafely(
835 const UsbTransferType& input,
836 usb::TransferType* output) {
837 const bool converted = ConvertTransferTypeToApi(input, output);
839 SetError(kErrorConvertTransferType);
843 bool UsbListInterfacesFunction::ConvertUsageTypeSafely(
844 const UsbUsageType& input,
845 usb::UsageType* output) {
846 const bool converted = ConvertUsageTypeToApi(input, output);
848 SetError(kErrorConvertUsageType);
852 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {}
854 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {}
856 bool UsbCloseDeviceFunction::Prepare() {
857 parameters_ = CloseDevice::Params::Create(*args_);
858 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
862 void UsbCloseDeviceFunction::AsyncWorkStart() {
863 scoped_refptr<UsbDeviceHandle> device_handle =
864 GetDeviceHandleOrCompleteWithError(parameters_->handle);
865 if (!device_handle) return;
867 device_handle->Close();
868 RemoveUsbDeviceResource(parameters_->handle.handle);
869 AsyncWorkCompleted();
872 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {}
874 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {}
876 bool UsbClaimInterfaceFunction::Prepare() {
877 parameters_ = ClaimInterface::Params::Create(*args_);
878 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
882 void UsbClaimInterfaceFunction::AsyncWorkStart() {
883 scoped_refptr<UsbDeviceHandle> device_handle =
884 GetDeviceHandleOrCompleteWithError(parameters_->handle);
885 if (!device_handle) return;
887 bool success = device_handle->ClaimInterface(parameters_->interface_number);
890 SetError(kErrorCannotClaimInterface);
891 AsyncWorkCompleted();
894 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {}
896 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {}
898 bool UsbReleaseInterfaceFunction::Prepare() {
899 parameters_ = ReleaseInterface::Params::Create(*args_);
900 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
904 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
905 scoped_refptr<UsbDeviceHandle> device_handle =
906 GetDeviceHandleOrCompleteWithError(parameters_->handle);
907 if (!device_handle) return;
909 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
911 SetError(kErrorCannotReleaseInterface);
912 AsyncWorkCompleted();
915 UsbSetInterfaceAlternateSettingFunction::
916 UsbSetInterfaceAlternateSettingFunction() {}
918 UsbSetInterfaceAlternateSettingFunction::
919 ~UsbSetInterfaceAlternateSettingFunction() {}
921 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
922 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
923 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
927 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
928 scoped_refptr<UsbDeviceHandle> device_handle =
929 GetDeviceHandleOrCompleteWithError(parameters_->handle);
930 if (!device_handle) return;
932 bool success = device_handle->SetInterfaceAlternateSetting(
933 parameters_->interface_number,
934 parameters_->alternate_setting);
936 SetError(kErrorCannotSetInterfaceAlternateSetting);
938 AsyncWorkCompleted();
941 UsbControlTransferFunction::UsbControlTransferFunction() {}
943 UsbControlTransferFunction::~UsbControlTransferFunction() {}
945 bool UsbControlTransferFunction::Prepare() {
946 parameters_ = ControlTransfer::Params::Create(*args_);
947 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
951 void UsbControlTransferFunction::AsyncWorkStart() {
952 scoped_refptr<UsbDeviceHandle> device_handle =
953 GetDeviceHandleOrCompleteWithError(parameters_->handle);
954 if (!device_handle) return;
956 const ControlTransferInfo& transfer = parameters_->transfer_info;
958 UsbEndpointDirection direction;
959 UsbDeviceHandle::TransferRequestType request_type;
960 UsbDeviceHandle::TransferRecipient recipient;
963 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
964 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
965 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
966 AsyncWorkCompleted();
970 if (!GetTransferSize(transfer, &size)) {
971 CompleteWithError(kErrorInvalidTransferLength);
975 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
976 transfer, direction, size);
978 CompleteWithError(kErrorMalformedParameters);
982 device_handle->ControlTransfer(
992 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
995 UsbBulkTransferFunction::UsbBulkTransferFunction() {}
997 UsbBulkTransferFunction::~UsbBulkTransferFunction() {}
999 bool UsbBulkTransferFunction::Prepare() {
1000 parameters_ = BulkTransfer::Params::Create(*args_);
1001 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1005 void UsbBulkTransferFunction::AsyncWorkStart() {
1006 scoped_refptr<UsbDeviceHandle> device_handle =
1007 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1008 if (!device_handle) return;
1010 const GenericTransferInfo& transfer = parameters_->transfer_info;
1012 UsbEndpointDirection direction;
1015 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1016 AsyncWorkCompleted();
1020 if (!GetTransferSize(transfer, &size)) {
1021 CompleteWithError(kErrorInvalidTransferLength);
1025 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1026 transfer, direction, size);
1027 if (!buffer.get()) {
1028 CompleteWithError(kErrorMalformedParameters);
1032 device_handle->BulkTransfer(
1038 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1041 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {}
1043 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {}
1045 bool UsbInterruptTransferFunction::Prepare() {
1046 parameters_ = InterruptTransfer::Params::Create(*args_);
1047 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1051 void UsbInterruptTransferFunction::AsyncWorkStart() {
1052 scoped_refptr<UsbDeviceHandle> device_handle =
1053 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1054 if (!device_handle) return;
1056 const GenericTransferInfo& transfer = parameters_->transfer_info;
1058 UsbEndpointDirection direction;
1061 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1062 AsyncWorkCompleted();
1066 if (!GetTransferSize(transfer, &size)) {
1067 CompleteWithError(kErrorInvalidTransferLength);
1071 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1072 transfer, direction, size);
1073 if (!buffer.get()) {
1074 CompleteWithError(kErrorMalformedParameters);
1078 device_handle->InterruptTransfer(
1084 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1087 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {}
1089 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {}
1091 bool UsbIsochronousTransferFunction::Prepare() {
1092 parameters_ = IsochronousTransfer::Params::Create(*args_);
1093 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1097 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1098 scoped_refptr<UsbDeviceHandle> device_handle =
1099 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1100 if (!device_handle) return;
1102 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1103 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1106 UsbEndpointDirection direction;
1108 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1109 AsyncWorkCompleted();
1112 if (!GetTransferSize(generic_transfer, &size)) {
1113 CompleteWithError(kErrorInvalidTransferLength);
1116 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1117 CompleteWithError(kErrorInvalidNumberOfPackets);
1120 unsigned int packets = transfer.packets;
1121 if (transfer.packet_length < 0 ||
1122 transfer.packet_length >= kMaxPacketLength) {
1123 CompleteWithError(kErrorInvalidPacketLength);
1126 unsigned int packet_length = transfer.packet_length;
1127 const uint64 total_length = packets * packet_length;
1128 if (packets > size || total_length > size) {
1129 CompleteWithError(kErrorTransferLength);
1133 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(
1134 generic_transfer, direction, size);
1135 if (!buffer.get()) {
1136 CompleteWithError(kErrorMalformedParameters);
1140 device_handle->IsochronousTransfer(
1142 generic_transfer.endpoint,
1148 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1151 UsbResetDeviceFunction::UsbResetDeviceFunction() {}
1153 UsbResetDeviceFunction::~UsbResetDeviceFunction() {}
1155 bool UsbResetDeviceFunction::Prepare() {
1156 parameters_ = ResetDevice::Params::Create(*args_);
1157 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1161 void UsbResetDeviceFunction::AsyncWorkStart() {
1162 scoped_refptr<UsbDeviceHandle> device_handle =
1163 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1164 if (!device_handle) return;
1166 bool success = device_handle->ResetDevice();
1168 device_handle->Close();
1169 RemoveUsbDeviceResource(parameters_->handle.handle);
1170 SetResult(new base::FundamentalValue(false));
1171 CompleteWithError(kErrorResetDevice);
1175 SetResult(new base::FundamentalValue(true));
1176 AsyncWorkCompleted();
1179 } // namespace extensions