Implementation of leveldb-backed PrefStore.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob428439a06c5b5e4204d81fbd16b75fccd97f22da
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.
5 #include "extensions/browser/api/usb/usb_api.h"
7 #include <string>
8 #include <vector>
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "components/usb_service/usb_device_handle.h"
13 #include "components/usb_service/usb_service.h"
14 #include "extensions/browser/api/usb/usb_device_resource.h"
15 #include "extensions/browser/extension_system.h"
16 #include "extensions/common/api/usb.h"
17 #include "extensions/common/permissions/permissions_data.h"
18 #include "extensions/common/permissions/usb_device_permission.h"
20 namespace usb = extensions::core_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;
37 using std::string;
38 using std::vector;
39 using usb::ControlTransferInfo;
40 using usb::ConnectionHandle;
41 using usb::Device;
42 using usb::Direction;
43 using usb::EndpointDescriptor;
44 using usb::GenericTransferInfo;
45 using usb::InterfaceDescriptor;
46 using usb::IsochronousTransferInfo;
47 using usb::Recipient;
48 using usb::RequestType;
49 using usb::SynchronizationType;
50 using usb::TransferType;
51 using usb::UsageType;
52 using usb_service::UsbConfigDescriptor;
53 using usb_service::UsbDevice;
54 using usb_service::UsbDeviceHandle;
55 using usb_service::UsbEndpointDescriptor;
56 using usb_service::UsbEndpointDirection;
57 using usb_service::UsbInterfaceAltSettingDescriptor;
58 using usb_service::UsbInterfaceDescriptor;
59 using usb_service::UsbService;
60 using usb_service::UsbSynchronizationType;
61 using usb_service::UsbTransferStatus;
62 using usb_service::UsbTransferType;
63 using usb_service::UsbUsageType;
65 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
66 typedef scoped_ptr<DeviceVector> ScopedDeviceVector;
68 namespace {
70 const char kDataKey[] = "data";
71 const char kResultCodeKey[] = "resultCode";
73 const char kErrorInitService[] = "Failed to initialize USB service.";
75 const char kErrorOpen[] = "Failed to open device.";
76 const char kErrorCancelled[] = "Transfer was cancelled.";
77 const char kErrorDisconnect[] = "Device disconnected.";
78 const char kErrorGeneric[] = "Transfer failed.";
79 #if !defined(OS_CHROMEOS)
80 const char kErrorNotSupported[] = "Not supported on this platform.";
81 #endif
82 const char kErrorOverflow[] = "Inbound transfer overflow.";
83 const char kErrorStalled[] = "Transfer stalled.";
84 const char kErrorTimeout[] = "Transfer timed out.";
85 const char kErrorTransferLength[] = "Transfer length is insufficient.";
87 const char kErrorCannotListInterfaces[] = "Error listing interfaces.";
88 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
89 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
90 const char kErrorCannotSetInterfaceAlternateSetting[] =
91 "Error setting alternate interface setting.";
92 const char kErrorConvertDirection[] = "Invalid transfer direction.";
93 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
94 const char kErrorConvertRequestType[] = "Invalid request type.";
95 const char kErrorConvertSynchronizationType[] = "Invalid synchronization type";
96 const char kErrorConvertTransferType[] = "Invalid endpoint type.";
97 const char kErrorConvertUsageType[] = "Invalid usage type.";
98 const char kErrorMalformedParameters[] = "Error parsing parameters.";
99 const char kErrorNoDevice[] = "No such device.";
100 const char kErrorPermissionDenied[] = "Permission to access device was denied";
101 const char kErrorInvalidTransferLength[] =
102 "Transfer length must be a positive number less than 104,857,600.";
103 const char kErrorInvalidNumberOfPackets[] =
104 "Number of packets must be a positive number less than 4,194,304.";
105 const char kErrorInvalidPacketLength[] =
106 "Packet length must be a positive number less than 65,536.";
107 const char kErrorResetDevice[] =
108 "Error resetting the device. The device has been closed.";
110 const size_t kMaxTransferLength = 100 * 1024 * 1024;
111 const int kMaxPackets = 4 * 1024 * 1024;
112 const int kMaxPacketLength = 64 * 1024;
114 bool ConvertDirectionToApi(const UsbEndpointDirection& input,
115 Direction* output) {
116 switch (input) {
117 case usb_service::USB_DIRECTION_INBOUND:
118 *output = usb::DIRECTION_IN;
119 return true;
120 case usb_service::USB_DIRECTION_OUTBOUND:
121 *output = usb::DIRECTION_OUT;
122 return true;
123 default:
124 NOTREACHED();
125 return false;
129 bool ConvertSynchronizationTypeToApi(const UsbSynchronizationType& input,
130 usb::SynchronizationType* output) {
131 switch (input) {
132 case usb_service::USB_SYNCHRONIZATION_NONE:
133 *output = usb::SYNCHRONIZATION_TYPE_NONE;
134 return true;
135 case usb_service::USB_SYNCHRONIZATION_ASYNCHRONOUS:
136 *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
137 return true;
138 case usb_service::USB_SYNCHRONIZATION_ADAPTIVE:
139 *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
140 return true;
141 case usb_service::USB_SYNCHRONIZATION_SYNCHRONOUS:
142 *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
143 return true;
144 default:
145 NOTREACHED();
146 return false;
150 bool ConvertTransferTypeToApi(const UsbTransferType& input,
151 usb::TransferType* output) {
152 switch (input) {
153 case usb_service::USB_TRANSFER_CONTROL:
154 *output = usb::TRANSFER_TYPE_CONTROL;
155 return true;
156 case usb_service::USB_TRANSFER_INTERRUPT:
157 *output = usb::TRANSFER_TYPE_INTERRUPT;
158 return true;
159 case usb_service::USB_TRANSFER_ISOCHRONOUS:
160 *output = usb::TRANSFER_TYPE_ISOCHRONOUS;
161 return true;
162 case usb_service::USB_TRANSFER_BULK:
163 *output = usb::TRANSFER_TYPE_BULK;
164 return true;
165 default:
166 NOTREACHED();
167 return false;
171 bool ConvertUsageTypeToApi(const UsbUsageType& input, usb::UsageType* output) {
172 switch (input) {
173 case usb_service::USB_USAGE_DATA:
174 *output = usb::USAGE_TYPE_DATA;
175 return true;
176 case usb_service::USB_USAGE_FEEDBACK:
177 *output = usb::USAGE_TYPE_FEEDBACK;
178 return true;
179 case usb_service::USB_USAGE_EXPLICIT_FEEDBACK:
180 *output = usb::USAGE_TYPE_EXPLICITFEEDBACK;
181 return true;
182 default:
183 NOTREACHED();
184 return false;
188 bool ConvertDirection(const Direction& input, UsbEndpointDirection* output) {
189 switch (input) {
190 case usb::DIRECTION_IN:
191 *output = usb_service::USB_DIRECTION_INBOUND;
192 return true;
193 case usb::DIRECTION_OUT:
194 *output = usb_service::USB_DIRECTION_OUTBOUND;
195 return true;
196 default:
197 NOTREACHED();
198 return false;
202 bool ConvertRequestType(const RequestType& input,
203 UsbDeviceHandle::TransferRequestType* output) {
204 switch (input) {
205 case usb::REQUEST_TYPE_STANDARD:
206 *output = UsbDeviceHandle::STANDARD;
207 return true;
208 case usb::REQUEST_TYPE_CLASS:
209 *output = UsbDeviceHandle::CLASS;
210 return true;
211 case usb::REQUEST_TYPE_VENDOR:
212 *output = UsbDeviceHandle::VENDOR;
213 return true;
214 case usb::REQUEST_TYPE_RESERVED:
215 *output = UsbDeviceHandle::RESERVED;
216 return true;
217 default:
218 NOTREACHED();
219 return false;
223 bool ConvertRecipient(const Recipient& input,
224 UsbDeviceHandle::TransferRecipient* output) {
225 switch (input) {
226 case usb::RECIPIENT_DEVICE:
227 *output = UsbDeviceHandle::DEVICE;
228 return true;
229 case usb::RECIPIENT_INTERFACE:
230 *output = UsbDeviceHandle::INTERFACE;
231 return true;
232 case usb::RECIPIENT_ENDPOINT:
233 *output = UsbDeviceHandle::ENDPOINT;
234 return true;
235 case usb::RECIPIENT_OTHER:
236 *output = UsbDeviceHandle::OTHER;
237 return true;
238 default:
239 NOTREACHED();
240 return false;
244 template <class T>
245 bool GetTransferSize(const T& input, size_t* output) {
246 if (input.direction == usb::DIRECTION_IN) {
247 const int* length = input.length.get();
248 if (length && *length >= 0 &&
249 static_cast<size_t>(*length) < kMaxTransferLength) {
250 *output = *length;
251 return true;
253 } else if (input.direction == usb::DIRECTION_OUT) {
254 if (input.data.get()) {
255 *output = input.data->size();
256 return true;
259 return false;
262 template <class T>
263 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
264 const T& input,
265 UsbEndpointDirection direction,
266 size_t size) {
267 if (size >= kMaxTransferLength)
268 return NULL;
270 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
271 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
272 // cannot represent a zero-length buffer, while an URB can.
273 scoped_refptr<net::IOBuffer> buffer =
274 new net::IOBuffer(std::max(static_cast<size_t>(1), size));
276 if (direction == usb_service::USB_DIRECTION_INBOUND) {
277 return buffer;
278 } else if (direction == usb_service::USB_DIRECTION_OUTBOUND) {
279 if (input.data.get() && size <= input.data->size()) {
280 memcpy(buffer->data(), input.data->data(), size);
281 return buffer;
284 NOTREACHED();
285 return NULL;
288 const char* ConvertTransferStatusToErrorString(const UsbTransferStatus status) {
289 switch (status) {
290 case usb_service::USB_TRANSFER_COMPLETED:
291 return "";
292 case usb_service::USB_TRANSFER_ERROR:
293 return kErrorGeneric;
294 case usb_service::USB_TRANSFER_TIMEOUT:
295 return kErrorTimeout;
296 case usb_service::USB_TRANSFER_CANCELLED:
297 return kErrorCancelled;
298 case usb_service::USB_TRANSFER_STALLED:
299 return kErrorStalled;
300 case usb_service::USB_TRANSFER_DISCONNECT:
301 return kErrorDisconnect;
302 case usb_service::USB_TRANSFER_OVERFLOW:
303 return kErrorOverflow;
304 case usb_service::USB_TRANSFER_LENGTH_SHORT:
305 return kErrorTransferLength;
306 default:
307 NOTREACHED();
308 return "";
312 #if defined(OS_CHROMEOS)
313 void RequestUsbDevicesAccessHelper(
314 ScopedDeviceVector devices,
315 std::vector<scoped_refptr<UsbDevice> >::iterator i,
316 int interface_id,
317 const base::Callback<void(ScopedDeviceVector result)>& callback,
318 bool success) {
319 if (success) {
320 ++i;
321 } else {
322 i = devices->erase(i);
324 if (i == devices->end()) {
325 callback.Run(devices.Pass());
326 return;
328 (*i)->RequestUsbAcess(interface_id,
329 base::Bind(RequestUsbDevicesAccessHelper,
330 base::Passed(devices.Pass()),
332 interface_id,
333 callback));
336 void RequestUsbDevicesAccess(
337 ScopedDeviceVector devices,
338 int interface_id,
339 const base::Callback<void(ScopedDeviceVector result)>& callback) {
340 if (devices->empty()) {
341 callback.Run(devices.Pass());
342 return;
344 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
345 (*i)->RequestUsbAcess(interface_id,
346 base::Bind(RequestUsbDevicesAccessHelper,
347 base::Passed(devices.Pass()),
349 interface_id,
350 callback));
352 #endif // OS_CHROMEOS
354 base::DictionaryValue* CreateTransferInfo(UsbTransferStatus status,
355 scoped_refptr<net::IOBuffer> data,
356 size_t length) {
357 base::DictionaryValue* result = new base::DictionaryValue();
358 result->SetInteger(kResultCodeKey, status);
359 result->Set(kDataKey,
360 base::BinaryValue::CreateWithCopiedBuffer(data->data(), length));
361 return result;
364 base::Value* PopulateConnectionHandle(int handle,
365 int vendor_id,
366 int product_id) {
367 ConnectionHandle result;
368 result.handle = handle;
369 result.vendor_id = vendor_id;
370 result.product_id = product_id;
371 return result.ToValue().release();
374 base::Value* PopulateDevice(UsbDevice* device) {
375 Device result;
376 result.device = device->unique_id();
377 result.vendor_id = device->vendor_id();
378 result.product_id = device->product_id();
379 return result.ToValue().release();
382 base::Value* PopulateInterfaceDescriptor(
383 int interface_number,
384 int alternate_setting,
385 int interface_class,
386 int interface_subclass,
387 int interface_protocol,
388 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) {
389 InterfaceDescriptor descriptor;
390 descriptor.interface_number = interface_number;
391 descriptor.alternate_setting = alternate_setting;
392 descriptor.interface_class = interface_class;
393 descriptor.interface_subclass = interface_subclass;
394 descriptor.interface_protocol = interface_protocol;
395 descriptor.endpoints = *endpoints;
396 return descriptor.ToValue().release();
399 } // namespace
401 namespace extensions {
403 UsbAsyncApiFunction::UsbAsyncApiFunction() : manager_(NULL) {
406 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
409 bool UsbAsyncApiFunction::PrePrepare() {
410 manager_ = ApiResourceManager<UsbDeviceResource>::Get(browser_context());
411 set_work_thread_id(BrowserThread::FILE);
412 return manager_ != NULL;
415 bool UsbAsyncApiFunction::Respond() {
416 return error_.empty();
419 scoped_refptr<UsbDevice> UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError(
420 const Device& input_device) {
421 const uint16_t vendor_id = input_device.vendor_id;
422 const uint16_t product_id = input_device.product_id;
423 UsbDevicePermission::CheckParam param(
424 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
425 if (!PermissionsData::CheckAPIPermissionWithParam(
426 GetExtension(), APIPermission::kUsbDevice, &param)) {
427 LOG(WARNING) << "Insufficient permissions to access device.";
428 CompleteWithError(kErrorPermissionDenied);
429 return NULL;
432 UsbService* service = UsbService::GetInstance();
433 if (!service) {
434 CompleteWithError(kErrorInitService);
435 return NULL;
437 scoped_refptr<UsbDevice> device;
439 device = service->GetDeviceById(input_device.device);
441 if (!device) {
442 CompleteWithError(kErrorNoDevice);
443 return NULL;
446 if (device->vendor_id() != input_device.vendor_id ||
447 device->product_id() != input_device.product_id) {
448 // Must act as if there is no such a device.
449 // Otherwise can be used to finger print unauthorized devices.
450 CompleteWithError(kErrorNoDevice);
451 return NULL;
454 return device;
457 scoped_refptr<UsbDeviceHandle>
458 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
459 const ConnectionHandle& input_device_handle) {
460 UsbDeviceResource* resource =
461 manager_->Get(extension_->id(), input_device_handle.handle);
462 if (!resource) {
463 CompleteWithError(kErrorNoDevice);
464 return NULL;
467 if (!resource->device() || !resource->device()->GetDevice()) {
468 CompleteWithError(kErrorDisconnect);
469 manager_->Remove(extension_->id(), input_device_handle.handle);
470 return NULL;
473 if (resource->device()->GetDevice()->vendor_id() !=
474 input_device_handle.vendor_id ||
475 resource->device()->GetDevice()->product_id() !=
476 input_device_handle.product_id) {
477 CompleteWithError(kErrorNoDevice);
478 return NULL;
481 return resource->device();
484 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
485 manager_->Remove(extension_->id(), api_resource_id);
488 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) {
489 SetError(error);
490 AsyncWorkCompleted();
493 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {
496 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {
499 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
500 scoped_refptr<net::IOBuffer> data,
501 size_t length) {
502 if (status != usb_service::USB_TRANSFER_COMPLETED)
503 SetError(ConvertTransferStatusToErrorString(status));
505 SetResult(CreateTransferInfo(status, data, length));
506 AsyncWorkCompleted();
509 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
510 const Direction& input,
511 UsbEndpointDirection* output) {
512 const bool converted = ConvertDirection(input, output);
513 if (!converted)
514 SetError(kErrorConvertDirection);
515 return converted;
518 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
519 const RequestType& input,
520 UsbDeviceHandle::TransferRequestType* output) {
521 const bool converted = ConvertRequestType(input, output);
522 if (!converted)
523 SetError(kErrorConvertRequestType);
524 return converted;
527 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
528 const Recipient& input,
529 UsbDeviceHandle::TransferRecipient* output) {
530 const bool converted = ConvertRecipient(input, output);
531 if (!converted)
532 SetError(kErrorConvertRecipient);
533 return converted;
536 UsbFindDevicesFunction::UsbFindDevicesFunction() {
539 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
542 bool UsbFindDevicesFunction::Prepare() {
543 parameters_ = FindDevices::Params::Create(*args_);
544 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
545 return true;
548 void UsbFindDevicesFunction::AsyncWorkStart() {
549 scoped_ptr<base::ListValue> result(new base::ListValue());
550 const uint16_t vendor_id = parameters_->options.vendor_id;
551 const uint16_t product_id = parameters_->options.product_id;
552 int interface_id = parameters_->options.interface_id.get()
553 ? *parameters_->options.interface_id.get()
554 : UsbDevicePermissionData::ANY_INTERFACE;
555 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
556 if (!PermissionsData::CheckAPIPermissionWithParam(
557 GetExtension(), APIPermission::kUsbDevice, &param)) {
558 LOG(WARNING) << "Insufficient permissions to access device.";
559 CompleteWithError(kErrorPermissionDenied);
560 return;
563 UsbService* service = UsbService::GetInstance();
564 if (!service) {
565 CompleteWithError(kErrorInitService);
566 return;
569 ScopedDeviceVector devices(new DeviceVector());
570 service->GetDevices(devices.get());
572 for (DeviceVector::iterator it = devices->begin(); it != devices->end();) {
573 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
574 it = devices->erase(it);
575 } else {
576 ++it;
580 #if defined(OS_CHROMEOS)
581 RequestUsbDevicesAccess(
582 devices.Pass(),
583 interface_id,
584 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
585 #else
586 OpenDevices(devices.Pass());
587 #endif // OS_CHROMEOS
590 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) {
591 base::ListValue* result = new base::ListValue();
593 for (size_t i = 0; i < devices->size(); ++i) {
594 scoped_refptr<UsbDeviceHandle> device_handle = devices->at(i)->Open();
595 if (device_handle)
596 device_handles_.push_back(device_handle);
599 for (size_t i = 0; i < device_handles_.size(); ++i) {
600 UsbDeviceHandle* const device_handle = device_handles_[i].get();
601 UsbDeviceResource* const resource =
602 new UsbDeviceResource(extension_->id(), device_handle);
604 result->Append(PopulateConnectionHandle(manager_->Add(resource),
605 parameters_->options.vendor_id,
606 parameters_->options.product_id));
609 SetResult(result);
610 AsyncWorkCompleted();
613 UsbGetDevicesFunction::UsbGetDevicesFunction() {
616 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
619 bool UsbGetDevicesFunction::Prepare() {
620 parameters_ = GetDevices::Params::Create(*args_);
621 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
622 return true;
625 void UsbGetDevicesFunction::AsyncWorkStart() {
626 scoped_ptr<base::ListValue> result(new base::ListValue());
628 const uint16_t vendor_id = parameters_->options.vendor_id;
629 const uint16_t product_id = parameters_->options.product_id;
630 UsbDevicePermission::CheckParam param(
631 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
632 if (!PermissionsData::CheckAPIPermissionWithParam(
633 GetExtension(), APIPermission::kUsbDevice, &param)) {
634 LOG(WARNING) << "Insufficient permissions to access device.";
635 CompleteWithError(kErrorPermissionDenied);
636 return;
639 UsbService* service = UsbService::GetInstance();
640 if (!service) {
641 CompleteWithError(kErrorInitService);
642 return;
645 DeviceVector devices;
646 service->GetDevices(&devices);
648 for (DeviceVector::iterator it = devices.begin(); it != devices.end();) {
649 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
650 it = devices.erase(it);
651 } else {
652 ++it;
656 for (size_t i = 0; i < devices.size(); ++i) {
657 result->Append(PopulateDevice(devices[i].get()));
660 SetResult(result.release());
661 AsyncWorkCompleted();
664 UsbRequestAccessFunction::UsbRequestAccessFunction() {
667 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
670 bool UsbRequestAccessFunction::Prepare() {
671 parameters_ = RequestAccess::Params::Create(*args_);
672 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
673 return true;
676 void UsbRequestAccessFunction::AsyncWorkStart() {
677 #if defined(OS_CHROMEOS)
678 scoped_refptr<UsbDevice> device =
679 GetDeviceOrOrCompleteWithError(parameters_->device);
680 if (!device)
681 return;
683 device->RequestUsbAcess(
684 parameters_->interface_id,
685 base::Bind(&UsbRequestAccessFunction::OnCompleted, this));
686 #else
687 SetResult(new base::FundamentalValue(false));
688 CompleteWithError(kErrorNotSupported);
689 #endif // OS_CHROMEOS
692 void UsbRequestAccessFunction::OnCompleted(bool success) {
693 SetResult(new base::FundamentalValue(success));
694 AsyncWorkCompleted();
697 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
700 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
703 bool UsbOpenDeviceFunction::Prepare() {
704 parameters_ = OpenDevice::Params::Create(*args_);
705 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
706 return true;
709 void UsbOpenDeviceFunction::AsyncWorkStart() {
710 scoped_refptr<UsbDevice> device =
711 GetDeviceOrOrCompleteWithError(parameters_->device);
712 if (!device)
713 return;
715 handle_ = device->Open();
716 if (!handle_) {
717 SetError(kErrorOpen);
718 AsyncWorkCompleted();
719 return;
722 SetResult(PopulateConnectionHandle(
723 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)),
724 handle_->GetDevice()->vendor_id(),
725 handle_->GetDevice()->product_id()));
726 AsyncWorkCompleted();
729 UsbListInterfacesFunction::UsbListInterfacesFunction() {
732 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
735 bool UsbListInterfacesFunction::Prepare() {
736 parameters_ = ListInterfaces::Params::Create(*args_);
737 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
738 return true;
741 void UsbListInterfacesFunction::AsyncWorkStart() {
742 scoped_refptr<UsbDeviceHandle> device_handle =
743 GetDeviceHandleOrCompleteWithError(parameters_->handle);
744 if (!device_handle)
745 return;
747 scoped_refptr<UsbConfigDescriptor> config =
748 device_handle->GetDevice()->ListInterfaces();
750 if (!config) {
751 SetError(kErrorCannotListInterfaces);
752 AsyncWorkCompleted();
753 return;
756 result_.reset(new base::ListValue());
758 for (size_t i = 0, num_interfaces = config->GetNumInterfaces();
759 i < num_interfaces;
760 ++i) {
761 scoped_refptr<const UsbInterfaceDescriptor> usb_interface(
762 config->GetInterface(i));
763 for (size_t j = 0, num_descriptors = usb_interface->GetNumAltSettings();
764 j < num_descriptors;
765 ++j) {
766 scoped_refptr<const UsbInterfaceAltSettingDescriptor> descriptor =
767 usb_interface->GetAltSetting(j);
768 std::vector<linked_ptr<EndpointDescriptor> > endpoints;
769 for (size_t k = 0, num_endpoints = descriptor->GetNumEndpoints();
770 k < num_endpoints;
771 k++) {
772 scoped_refptr<const UsbEndpointDescriptor> endpoint =
773 descriptor->GetEndpoint(k);
774 linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor());
776 TransferType type;
777 Direction direction;
778 SynchronizationType synchronization;
779 UsageType usage;
781 if (!ConvertTransferTypeSafely(endpoint->GetTransferType(), &type) ||
782 !ConvertDirectionSafely(endpoint->GetDirection(), &direction) ||
783 !ConvertSynchronizationTypeSafely(
784 endpoint->GetSynchronizationType(), &synchronization) ||
785 !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) {
786 SetError(kErrorCannotListInterfaces);
787 AsyncWorkCompleted();
788 return;
791 endpoint_desc->address = endpoint->GetAddress();
792 endpoint_desc->type = type;
793 endpoint_desc->direction = direction;
794 endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize();
795 endpoint_desc->synchronization = synchronization;
796 endpoint_desc->usage = usage;
798 int* polling_interval = new int;
799 endpoint_desc->polling_interval.reset(polling_interval);
800 *polling_interval = endpoint->GetPollingInterval();
802 endpoints.push_back(endpoint_desc);
805 result_->Append(
806 PopulateInterfaceDescriptor(descriptor->GetInterfaceNumber(),
807 descriptor->GetAlternateSetting(),
808 descriptor->GetInterfaceClass(),
809 descriptor->GetInterfaceSubclass(),
810 descriptor->GetInterfaceProtocol(),
811 &endpoints));
815 SetResult(result_.release());
816 AsyncWorkCompleted();
819 bool UsbListInterfacesFunction::ConvertDirectionSafely(
820 const UsbEndpointDirection& input,
821 usb::Direction* output) {
822 const bool converted = ConvertDirectionToApi(input, output);
823 if (!converted)
824 SetError(kErrorConvertDirection);
825 return converted;
828 bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely(
829 const UsbSynchronizationType& input,
830 usb::SynchronizationType* output) {
831 const bool converted = ConvertSynchronizationTypeToApi(input, output);
832 if (!converted)
833 SetError(kErrorConvertSynchronizationType);
834 return converted;
837 bool UsbListInterfacesFunction::ConvertTransferTypeSafely(
838 const UsbTransferType& input,
839 usb::TransferType* output) {
840 const bool converted = ConvertTransferTypeToApi(input, output);
841 if (!converted)
842 SetError(kErrorConvertTransferType);
843 return converted;
846 bool UsbListInterfacesFunction::ConvertUsageTypeSafely(
847 const UsbUsageType& input,
848 usb::UsageType* output) {
849 const bool converted = ConvertUsageTypeToApi(input, output);
850 if (!converted)
851 SetError(kErrorConvertUsageType);
852 return converted;
855 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
858 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
861 bool UsbCloseDeviceFunction::Prepare() {
862 parameters_ = CloseDevice::Params::Create(*args_);
863 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
864 return true;
867 void UsbCloseDeviceFunction::AsyncWorkStart() {
868 scoped_refptr<UsbDeviceHandle> device_handle =
869 GetDeviceHandleOrCompleteWithError(parameters_->handle);
870 if (!device_handle)
871 return;
873 device_handle->Close();
874 RemoveUsbDeviceResource(parameters_->handle.handle);
875 AsyncWorkCompleted();
878 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
881 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
884 bool UsbClaimInterfaceFunction::Prepare() {
885 parameters_ = ClaimInterface::Params::Create(*args_);
886 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
887 return true;
890 void UsbClaimInterfaceFunction::AsyncWorkStart() {
891 scoped_refptr<UsbDeviceHandle> device_handle =
892 GetDeviceHandleOrCompleteWithError(parameters_->handle);
893 if (!device_handle)
894 return;
896 bool success = device_handle->ClaimInterface(parameters_->interface_number);
898 if (!success)
899 SetError(kErrorCannotClaimInterface);
900 AsyncWorkCompleted();
903 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
906 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
909 bool UsbReleaseInterfaceFunction::Prepare() {
910 parameters_ = ReleaseInterface::Params::Create(*args_);
911 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
912 return true;
915 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
916 scoped_refptr<UsbDeviceHandle> device_handle =
917 GetDeviceHandleOrCompleteWithError(parameters_->handle);
918 if (!device_handle)
919 return;
921 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
922 if (!success)
923 SetError(kErrorCannotReleaseInterface);
924 AsyncWorkCompleted();
927 UsbSetInterfaceAlternateSettingFunction::
928 UsbSetInterfaceAlternateSettingFunction() {
931 UsbSetInterfaceAlternateSettingFunction::
932 ~UsbSetInterfaceAlternateSettingFunction() {
935 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
936 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
937 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
938 return true;
941 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
942 scoped_refptr<UsbDeviceHandle> device_handle =
943 GetDeviceHandleOrCompleteWithError(parameters_->handle);
944 if (!device_handle)
945 return;
947 bool success = device_handle->SetInterfaceAlternateSetting(
948 parameters_->interface_number, parameters_->alternate_setting);
949 if (!success)
950 SetError(kErrorCannotSetInterfaceAlternateSetting);
952 AsyncWorkCompleted();
955 UsbControlTransferFunction::UsbControlTransferFunction() {
958 UsbControlTransferFunction::~UsbControlTransferFunction() {
961 bool UsbControlTransferFunction::Prepare() {
962 parameters_ = ControlTransfer::Params::Create(*args_);
963 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
964 return true;
967 void UsbControlTransferFunction::AsyncWorkStart() {
968 scoped_refptr<UsbDeviceHandle> device_handle =
969 GetDeviceHandleOrCompleteWithError(parameters_->handle);
970 if (!device_handle)
971 return;
973 const ControlTransferInfo& transfer = parameters_->transfer_info;
975 UsbEndpointDirection direction;
976 UsbDeviceHandle::TransferRequestType request_type;
977 UsbDeviceHandle::TransferRecipient recipient;
978 size_t size = 0;
980 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
981 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
982 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
983 AsyncWorkCompleted();
984 return;
987 if (!GetTransferSize(transfer, &size)) {
988 CompleteWithError(kErrorInvalidTransferLength);
989 return;
992 scoped_refptr<net::IOBuffer> buffer =
993 CreateBufferForTransfer(transfer, direction, size);
994 if (!buffer.get()) {
995 CompleteWithError(kErrorMalformedParameters);
996 return;
999 device_handle->ControlTransfer(
1000 direction,
1001 request_type,
1002 recipient,
1003 transfer.request,
1004 transfer.value,
1005 transfer.index,
1006 buffer.get(),
1007 size,
1009 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
1012 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1015 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1018 bool UsbBulkTransferFunction::Prepare() {
1019 parameters_ = BulkTransfer::Params::Create(*args_);
1020 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1021 return true;
1024 void UsbBulkTransferFunction::AsyncWorkStart() {
1025 scoped_refptr<UsbDeviceHandle> device_handle =
1026 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1027 if (!device_handle)
1028 return;
1030 const GenericTransferInfo& transfer = parameters_->transfer_info;
1032 UsbEndpointDirection direction;
1033 size_t size = 0;
1035 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1036 AsyncWorkCompleted();
1037 return;
1040 if (!GetTransferSize(transfer, &size)) {
1041 CompleteWithError(kErrorInvalidTransferLength);
1042 return;
1045 scoped_refptr<net::IOBuffer> buffer =
1046 CreateBufferForTransfer(transfer, direction, size);
1047 if (!buffer.get()) {
1048 CompleteWithError(kErrorMalformedParameters);
1049 return;
1052 device_handle->BulkTransfer(
1053 direction,
1054 transfer.endpoint,
1055 buffer.get(),
1056 size,
1058 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1061 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1064 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1067 bool UsbInterruptTransferFunction::Prepare() {
1068 parameters_ = InterruptTransfer::Params::Create(*args_);
1069 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1070 return true;
1073 void UsbInterruptTransferFunction::AsyncWorkStart() {
1074 scoped_refptr<UsbDeviceHandle> device_handle =
1075 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1076 if (!device_handle)
1077 return;
1079 const GenericTransferInfo& transfer = parameters_->transfer_info;
1081 UsbEndpointDirection direction;
1082 size_t size = 0;
1084 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1085 AsyncWorkCompleted();
1086 return;
1089 if (!GetTransferSize(transfer, &size)) {
1090 CompleteWithError(kErrorInvalidTransferLength);
1091 return;
1094 scoped_refptr<net::IOBuffer> buffer =
1095 CreateBufferForTransfer(transfer, direction, size);
1096 if (!buffer.get()) {
1097 CompleteWithError(kErrorMalformedParameters);
1098 return;
1101 device_handle->InterruptTransfer(
1102 direction,
1103 transfer.endpoint,
1104 buffer.get(),
1105 size,
1107 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1110 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1113 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1116 bool UsbIsochronousTransferFunction::Prepare() {
1117 parameters_ = IsochronousTransfer::Params::Create(*args_);
1118 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1119 return true;
1122 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1123 scoped_refptr<UsbDeviceHandle> device_handle =
1124 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1125 if (!device_handle)
1126 return;
1128 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1129 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1131 size_t size = 0;
1132 UsbEndpointDirection direction;
1134 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1135 AsyncWorkCompleted();
1136 return;
1138 if (!GetTransferSize(generic_transfer, &size)) {
1139 CompleteWithError(kErrorInvalidTransferLength);
1140 return;
1142 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1143 CompleteWithError(kErrorInvalidNumberOfPackets);
1144 return;
1146 unsigned int packets = transfer.packets;
1147 if (transfer.packet_length < 0 ||
1148 transfer.packet_length >= kMaxPacketLength) {
1149 CompleteWithError(kErrorInvalidPacketLength);
1150 return;
1152 unsigned int packet_length = transfer.packet_length;
1153 const uint64 total_length = packets * packet_length;
1154 if (packets > size || total_length > size) {
1155 CompleteWithError(kErrorTransferLength);
1156 return;
1159 scoped_refptr<net::IOBuffer> buffer =
1160 CreateBufferForTransfer(generic_transfer, direction, size);
1161 if (!buffer.get()) {
1162 CompleteWithError(kErrorMalformedParameters);
1163 return;
1166 device_handle->IsochronousTransfer(
1167 direction,
1168 generic_transfer.endpoint,
1169 buffer.get(),
1170 size,
1171 packets,
1172 packet_length,
1174 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1177 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1180 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1183 bool UsbResetDeviceFunction::Prepare() {
1184 parameters_ = ResetDevice::Params::Create(*args_);
1185 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1186 return true;
1189 void UsbResetDeviceFunction::AsyncWorkStart() {
1190 scoped_refptr<UsbDeviceHandle> device_handle =
1191 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1192 if (!device_handle)
1193 return;
1195 bool success = device_handle->ResetDevice();
1196 if (!success) {
1197 device_handle->Close();
1198 RemoveUsbDeviceResource(parameters_->handle.handle);
1199 SetResult(new base::FundamentalValue(false));
1200 CompleteWithError(kErrorResetDevice);
1201 return;
1204 SetResult(new base::FundamentalValue(true));
1205 AsyncWorkCompleted();
1208 } // namespace extensions