Add chrome.usb.getConfiguration and expose extra descriptors.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob2c2b4903953b883327a63f9c25cde8b3590495fa
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 "device/core/device_client.h"
13 #include "device/usb/usb_device_handle.h"
14 #include "device/usb/usb_service.h"
15 #include "extensions/browser/api/usb/usb_device_resource.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/common/api/usb.h"
18 #include "extensions/common/permissions/permissions_data.h"
19 #include "extensions/common/permissions/usb_device_permission.h"
21 namespace usb = extensions::core_api::usb;
22 namespace BulkTransfer = usb::BulkTransfer;
23 namespace ClaimInterface = usb::ClaimInterface;
24 namespace CloseDevice = usb::CloseDevice;
25 namespace ControlTransfer = usb::ControlTransfer;
26 namespace FindDevices = usb::FindDevices;
27 namespace GetDevices = usb::GetDevices;
28 namespace InterruptTransfer = usb::InterruptTransfer;
29 namespace IsochronousTransfer = usb::IsochronousTransfer;
30 namespace GetConfiguration = usb::GetConfiguration;
31 namespace ListInterfaces = usb::ListInterfaces;
32 namespace OpenDevice = usb::OpenDevice;
33 namespace ReleaseInterface = usb::ReleaseInterface;
34 namespace RequestAccess = usb::RequestAccess;
35 namespace ResetDevice = usb::ResetDevice;
36 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
38 using content::BrowserThread;
39 using usb::ConfigDescriptor;
40 using usb::ControlTransferInfo;
41 using usb::ConnectionHandle;
42 using usb::Device;
43 using usb::Direction;
44 using usb::EndpointDescriptor;
45 using usb::GenericTransferInfo;
46 using usb::InterfaceDescriptor;
47 using usb::IsochronousTransferInfo;
48 using usb::Recipient;
49 using usb::RequestType;
50 using usb::SynchronizationType;
51 using usb::TransferType;
52 using usb::UsageType;
53 using device::UsbConfigDescriptor;
54 using device::UsbDevice;
55 using device::UsbDeviceFilter;
56 using device::UsbDeviceHandle;
57 using device::UsbEndpointDescriptor;
58 using device::UsbEndpointDirection;
59 using device::UsbInterfaceDescriptor;
60 using device::UsbService;
61 using device::UsbSynchronizationType;
62 using device::UsbTransferStatus;
63 using device::UsbTransferType;
64 using device::UsbUsageType;
66 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
67 typedef scoped_ptr<DeviceVector> ScopedDeviceVector;
69 namespace {
71 const char kDataKey[] = "data";
72 const char kResultCodeKey[] = "resultCode";
74 const char kErrorInitService[] = "Failed to initialize USB service.";
76 const char kErrorOpen[] = "Failed to open device.";
77 const char kErrorCancelled[] = "Transfer was cancelled.";
78 const char kErrorDisconnect[] = "Device disconnected.";
79 const char kErrorGeneric[] = "Transfer failed.";
80 #if !defined(OS_CHROMEOS)
81 const char kErrorNotSupported[] = "Not supported on this platform.";
82 #endif
83 const char kErrorOverflow[] = "Inbound transfer overflow.";
84 const char kErrorStalled[] = "Transfer stalled.";
85 const char kErrorTimeout[] = "Transfer timed out.";
86 const char kErrorTransferLength[] = "Transfer length is insufficient.";
87 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
88 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
89 const char kErrorCannotSetInterfaceAlternateSetting[] =
90 "Error setting alternate interface setting.";
91 const char kErrorConvertDirection[] = "Invalid transfer direction.";
92 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
93 const char kErrorConvertRequestType[] = "Invalid request type.";
94 const char kErrorMalformedParameters[] = "Error parsing parameters.";
95 const char kErrorNoDevice[] = "No such device.";
96 const char kErrorPermissionDenied[] = "Permission to access device was denied";
97 const char kErrorInvalidTransferLength[] =
98 "Transfer length must be a positive number less than 104,857,600.";
99 const char kErrorInvalidNumberOfPackets[] =
100 "Number of packets must be a positive number less than 4,194,304.";
101 const char kErrorInvalidPacketLength[] =
102 "Packet length must be a positive number less than 65,536.";
103 const char kErrorResetDevice[] =
104 "Error resetting the device. The device has been closed.";
106 const size_t kMaxTransferLength = 100 * 1024 * 1024;
107 const int kMaxPackets = 4 * 1024 * 1024;
108 const int kMaxPacketLength = 64 * 1024;
110 bool ConvertDirectionFromApi(const Direction& input,
111 UsbEndpointDirection* output) {
112 switch (input) {
113 case usb::DIRECTION_IN:
114 *output = device::USB_DIRECTION_INBOUND;
115 return true;
116 case usb::DIRECTION_OUT:
117 *output = device::USB_DIRECTION_OUTBOUND;
118 return true;
119 default:
120 NOTREACHED();
121 return false;
125 bool ConvertRequestTypeFromApi(const RequestType& input,
126 UsbDeviceHandle::TransferRequestType* output) {
127 switch (input) {
128 case usb::REQUEST_TYPE_STANDARD:
129 *output = UsbDeviceHandle::STANDARD;
130 return true;
131 case usb::REQUEST_TYPE_CLASS:
132 *output = UsbDeviceHandle::CLASS;
133 return true;
134 case usb::REQUEST_TYPE_VENDOR:
135 *output = UsbDeviceHandle::VENDOR;
136 return true;
137 case usb::REQUEST_TYPE_RESERVED:
138 *output = UsbDeviceHandle::RESERVED;
139 return true;
140 default:
141 NOTREACHED();
142 return false;
146 bool ConvertRecipientFromApi(const Recipient& input,
147 UsbDeviceHandle::TransferRecipient* output) {
148 switch (input) {
149 case usb::RECIPIENT_DEVICE:
150 *output = UsbDeviceHandle::DEVICE;
151 return true;
152 case usb::RECIPIENT_INTERFACE:
153 *output = UsbDeviceHandle::INTERFACE;
154 return true;
155 case usb::RECIPIENT_ENDPOINT:
156 *output = UsbDeviceHandle::ENDPOINT;
157 return true;
158 case usb::RECIPIENT_OTHER:
159 *output = UsbDeviceHandle::OTHER;
160 return true;
161 default:
162 NOTREACHED();
163 return false;
167 template <class T>
168 bool GetTransferSize(const T& input, size_t* output) {
169 if (input.direction == usb::DIRECTION_IN) {
170 const int* length = input.length.get();
171 if (length && *length >= 0 &&
172 static_cast<size_t>(*length) < kMaxTransferLength) {
173 *output = *length;
174 return true;
176 } else if (input.direction == usb::DIRECTION_OUT) {
177 if (input.data.get()) {
178 *output = input.data->size();
179 return true;
182 return false;
185 template <class T>
186 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
187 const T& input,
188 UsbEndpointDirection direction,
189 size_t size) {
190 if (size >= kMaxTransferLength)
191 return NULL;
193 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
194 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
195 // cannot represent a zero-length buffer, while an URB can.
196 scoped_refptr<net::IOBuffer> buffer =
197 new net::IOBuffer(std::max(static_cast<size_t>(1), size));
199 if (direction == device::USB_DIRECTION_INBOUND) {
200 return buffer;
201 } else if (direction == device::USB_DIRECTION_OUTBOUND) {
202 if (input.data.get() && size <= input.data->size()) {
203 memcpy(buffer->data(), input.data->data(), size);
204 return buffer;
207 NOTREACHED();
208 return NULL;
211 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
212 switch (status) {
213 case device::USB_TRANSFER_COMPLETED:
214 return "";
215 case device::USB_TRANSFER_ERROR:
216 return kErrorGeneric;
217 case device::USB_TRANSFER_TIMEOUT:
218 return kErrorTimeout;
219 case device::USB_TRANSFER_CANCELLED:
220 return kErrorCancelled;
221 case device::USB_TRANSFER_STALLED:
222 return kErrorStalled;
223 case device::USB_TRANSFER_DISCONNECT:
224 return kErrorDisconnect;
225 case device::USB_TRANSFER_OVERFLOW:
226 return kErrorOverflow;
227 case device::USB_TRANSFER_LENGTH_SHORT:
228 return kErrorTransferLength;
229 default:
230 NOTREACHED();
231 return "";
235 #if defined(OS_CHROMEOS)
236 void RequestUsbDevicesAccessHelper(
237 ScopedDeviceVector devices,
238 std::vector<scoped_refptr<UsbDevice> >::iterator i,
239 int interface_id,
240 const base::Callback<void(ScopedDeviceVector result)>& callback,
241 bool success) {
242 if (success) {
243 ++i;
244 } else {
245 i = devices->erase(i);
247 if (i == devices->end()) {
248 callback.Run(devices.Pass());
249 return;
251 (*i)->RequestUsbAccess(interface_id,
252 base::Bind(RequestUsbDevicesAccessHelper,
253 base::Passed(devices.Pass()),
255 interface_id,
256 callback));
259 void RequestUsbDevicesAccess(
260 ScopedDeviceVector devices,
261 int interface_id,
262 const base::Callback<void(ScopedDeviceVector result)>& callback) {
263 if (devices->empty()) {
264 callback.Run(devices.Pass());
265 return;
267 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
268 (*i)->RequestUsbAccess(interface_id,
269 base::Bind(RequestUsbDevicesAccessHelper,
270 base::Passed(devices.Pass()),
272 interface_id,
273 callback));
275 #endif // OS_CHROMEOS
277 base::DictionaryValue* CreateTransferInfo(UsbTransferStatus status,
278 scoped_refptr<net::IOBuffer> data,
279 size_t length) {
280 base::DictionaryValue* result = new base::DictionaryValue();
281 result->SetInteger(kResultCodeKey, status);
282 result->Set(kDataKey,
283 base::BinaryValue::CreateWithCopiedBuffer(data->data(), length));
284 return result;
287 base::Value* PopulateConnectionHandle(int handle,
288 int vendor_id,
289 int product_id) {
290 ConnectionHandle result;
291 result.handle = handle;
292 result.vendor_id = vendor_id;
293 result.product_id = product_id;
294 return result.ToValue().release();
297 base::Value* PopulateDevice(UsbDevice* device) {
298 Device result;
299 result.device = device->unique_id();
300 result.vendor_id = device->vendor_id();
301 result.product_id = device->product_id();
302 return result.ToValue().release();
305 TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
306 switch (input) {
307 case device::USB_TRANSFER_CONTROL:
308 return usb::TRANSFER_TYPE_CONTROL;
309 case device::USB_TRANSFER_INTERRUPT:
310 return usb::TRANSFER_TYPE_INTERRUPT;
311 case device::USB_TRANSFER_ISOCHRONOUS:
312 return usb::TRANSFER_TYPE_ISOCHRONOUS;
313 case device::USB_TRANSFER_BULK:
314 return usb::TRANSFER_TYPE_BULK;
315 default:
316 NOTREACHED();
317 return usb::TRANSFER_TYPE_NONE;
321 Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
322 switch (input) {
323 case device::USB_DIRECTION_INBOUND:
324 return usb::DIRECTION_IN;
325 case device::USB_DIRECTION_OUTBOUND:
326 return usb::DIRECTION_OUT;
327 default:
328 NOTREACHED();
329 return usb::DIRECTION_NONE;
333 SynchronizationType ConvertSynchronizationTypeToApi(
334 const UsbSynchronizationType& input) {
335 switch (input) {
336 case device::USB_SYNCHRONIZATION_NONE:
337 return usb::SYNCHRONIZATION_TYPE_NONE;
338 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS:
339 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
340 case device::USB_SYNCHRONIZATION_ADAPTIVE:
341 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
342 case device::USB_SYNCHRONIZATION_SYNCHRONOUS:
343 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
344 default:
345 NOTREACHED();
346 return usb::SYNCHRONIZATION_TYPE_NONE;
350 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
351 switch (input) {
352 case device::USB_USAGE_DATA:
353 return usb::USAGE_TYPE_DATA;
354 case device::USB_USAGE_FEEDBACK:
355 return usb::USAGE_TYPE_FEEDBACK;
356 case device::USB_USAGE_EXPLICIT_FEEDBACK:
357 return usb::USAGE_TYPE_EXPLICITFEEDBACK;
358 default:
359 NOTREACHED();
360 return usb::USAGE_TYPE_NONE;
364 void ConvertEndpointDescriptor(const UsbEndpointDescriptor& input,
365 EndpointDescriptor* output) {
366 output->address = input.address;
367 output->type = ConvertTransferTypeToApi(input.transfer_type);
368 output->direction = ConvertDirectionToApi(input.direction);
369 output->maximum_packet_size = input.maximum_packet_size;
370 output->synchronization =
371 ConvertSynchronizationTypeToApi(input.synchronization_type);
372 output->usage = ConvertUsageTypeToApi(input.usage_type);
373 output->polling_interval.reset(new int(input.polling_interval));
374 if (input.extra_data.size() > 0) {
375 output->extra_data =
376 std::string(reinterpret_cast<const char*>(&input.extra_data[0]),
377 input.extra_data.size());
381 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor& input,
382 InterfaceDescriptor* output) {
383 output->interface_number = input.interface_number;
384 output->alternate_setting = input.alternate_setting;
385 output->interface_class = input.interface_class;
386 output->interface_subclass = input.interface_subclass;
387 output->interface_protocol = input.interface_protocol;
388 for (UsbEndpointDescriptor::Iterator endpointIt = input.endpoints.begin();
389 endpointIt != input.endpoints.end();
390 ++endpointIt) {
391 linked_ptr<EndpointDescriptor> endpoint(new EndpointDescriptor);
392 ConvertEndpointDescriptor(*endpointIt, endpoint.get());
393 output->endpoints.push_back(endpoint);
395 if (input.extra_data.size() > 0) {
396 output->extra_data =
397 std::string(reinterpret_cast<const char*>(&input.extra_data[0]),
398 input.extra_data.size());
402 void ConvertConfigDescriptor(const UsbConfigDescriptor& input,
403 ConfigDescriptor* output) {
404 output->configuration_value = input.configuration_value;
405 output->self_powered = input.self_powered;
406 output->remote_wakeup = input.remote_wakeup;
407 output->max_power = input.maximum_power;
408 for (UsbInterfaceDescriptor::Iterator interfaceIt = input.interfaces.begin();
409 interfaceIt != input.interfaces.end();
410 ++interfaceIt) {
411 linked_ptr<InterfaceDescriptor> interface(new InterfaceDescriptor);
412 ConvertInterfaceDescriptor(*interfaceIt, interface.get());
413 output->interfaces.push_back(interface);
415 if (input.extra_data.size() > 0) {
416 output->extra_data =
417 std::string(reinterpret_cast<const char*>(&input.extra_data[0]),
418 input.extra_data.size());
422 } // namespace
424 namespace extensions {
426 UsbAsyncApiFunction::UsbAsyncApiFunction() : manager_(NULL) {
429 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
432 bool UsbAsyncApiFunction::PrePrepare() {
433 manager_ = ApiResourceManager<UsbDeviceResource>::Get(browser_context());
434 set_work_thread_id(BrowserThread::FILE);
435 return manager_ != NULL;
438 bool UsbAsyncApiFunction::Respond() {
439 return error_.empty();
442 // static
443 void UsbAsyncApiFunction::CreateDeviceFilter(const usb::DeviceFilter& input,
444 UsbDeviceFilter* output) {
445 if (input.vendor_id) {
446 output->SetVendorId(*input.vendor_id);
448 if (input.product_id) {
449 output->SetProductId(*input.product_id);
451 if (input.interface_class) {
452 output->SetInterfaceClass(*input.interface_class);
454 if (input.interface_subclass) {
455 output->SetInterfaceSubclass(*input.interface_subclass);
457 if (input.interface_protocol) {
458 output->SetInterfaceProtocol(*input.interface_protocol);
462 bool UsbAsyncApiFunction::HasDevicePermission(scoped_refptr<UsbDevice> device) {
463 UsbDevicePermission::CheckParam param(
464 device->vendor_id(),
465 device->product_id(),
466 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
467 return extension()->permissions_data()->CheckAPIPermissionWithParam(
468 APIPermission::kUsbDevice, &param);
471 scoped_refptr<UsbDevice> UsbAsyncApiFunction::GetDeviceOrCompleteWithError(
472 const Device& input_device) {
473 UsbService* service = device::DeviceClient::Get()->GetUsbService();
474 if (!service) {
475 CompleteWithError(kErrorInitService);
476 return NULL;
479 scoped_refptr<UsbDevice> device = service->GetDeviceById(input_device.device);
480 if (!device.get()) {
481 CompleteWithError(kErrorNoDevice);
482 return NULL;
485 if (!HasDevicePermission(device)) {
486 // Must act as if there is no such a device.
487 // Otherwise can be used to finger print unauthorized devices.
488 CompleteWithError(kErrorNoDevice);
489 return NULL;
492 return device;
495 scoped_refptr<UsbDeviceHandle>
496 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
497 const ConnectionHandle& input_device_handle) {
498 UsbDeviceResource* resource =
499 manager_->Get(extension_->id(), input_device_handle.handle);
500 if (!resource) {
501 CompleteWithError(kErrorNoDevice);
502 return NULL;
505 if (!resource->device().get() || !resource->device()->GetDevice().get()) {
506 CompleteWithError(kErrorDisconnect);
507 manager_->Remove(extension_->id(), input_device_handle.handle);
508 return NULL;
511 if (resource->device()->GetDevice()->vendor_id() !=
512 input_device_handle.vendor_id ||
513 resource->device()->GetDevice()->product_id() !=
514 input_device_handle.product_id) {
515 CompleteWithError(kErrorNoDevice);
516 return NULL;
519 return resource->device();
522 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
523 manager_->Remove(extension_->id(), api_resource_id);
526 void UsbAsyncApiFunction::CompleteWithError(const std::string& error) {
527 SetError(error);
528 AsyncWorkCompleted();
531 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {
534 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {
537 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
538 scoped_refptr<net::IOBuffer> data,
539 size_t length) {
540 if (status != device::USB_TRANSFER_COMPLETED)
541 SetError(ConvertTransferStatusToApi(status));
543 SetResult(CreateTransferInfo(status, data, length));
544 AsyncWorkCompleted();
547 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
548 const Direction& input,
549 UsbEndpointDirection* output) {
550 const bool converted = ConvertDirectionFromApi(input, output);
551 if (!converted)
552 SetError(kErrorConvertDirection);
553 return converted;
556 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
557 const RequestType& input,
558 UsbDeviceHandle::TransferRequestType* output) {
559 const bool converted = ConvertRequestTypeFromApi(input, output);
560 if (!converted)
561 SetError(kErrorConvertRequestType);
562 return converted;
565 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
566 const Recipient& input,
567 UsbDeviceHandle::TransferRecipient* output) {
568 const bool converted = ConvertRecipientFromApi(input, output);
569 if (!converted)
570 SetError(kErrorConvertRecipient);
571 return converted;
574 UsbFindDevicesFunction::UsbFindDevicesFunction() {
577 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
580 bool UsbFindDevicesFunction::Prepare() {
581 parameters_ = FindDevices::Params::Create(*args_);
582 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
583 return true;
586 void UsbFindDevicesFunction::AsyncWorkStart() {
587 scoped_ptr<base::ListValue> result(new base::ListValue());
588 const uint16_t vendor_id = parameters_->options.vendor_id;
589 const uint16_t product_id = parameters_->options.product_id;
590 int interface_id = parameters_->options.interface_id.get()
591 ? *parameters_->options.interface_id.get()
592 : UsbDevicePermissionData::ANY_INTERFACE;
593 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
594 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
595 APIPermission::kUsbDevice, &param)) {
596 LOG(WARNING) << "Insufficient permissions to access device.";
597 CompleteWithError(kErrorPermissionDenied);
598 return;
601 UsbService* service = device::DeviceClient::Get()->GetUsbService();
602 if (!service) {
603 CompleteWithError(kErrorInitService);
604 return;
607 ScopedDeviceVector devices(new DeviceVector());
608 service->GetDevices(devices.get());
610 for (DeviceVector::iterator it = devices->begin(); it != devices->end();) {
611 if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) {
612 it = devices->erase(it);
613 } else {
614 ++it;
618 #if defined(OS_CHROMEOS)
619 RequestUsbDevicesAccess(
620 devices.Pass(),
621 interface_id,
622 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
623 #else
624 OpenDevices(devices.Pass());
625 #endif // OS_CHROMEOS
628 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) {
629 base::ListValue* result = new base::ListValue();
631 for (size_t i = 0; i < devices->size(); ++i) {
632 scoped_refptr<UsbDeviceHandle> device_handle = devices->at(i)->Open();
633 if (device_handle.get())
634 device_handles_.push_back(device_handle);
637 for (size_t i = 0; i < device_handles_.size(); ++i) {
638 UsbDeviceHandle* const device_handle = device_handles_[i].get();
639 UsbDeviceResource* const resource =
640 new UsbDeviceResource(extension_->id(), device_handle);
642 result->Append(PopulateConnectionHandle(manager_->Add(resource),
643 parameters_->options.vendor_id,
644 parameters_->options.product_id));
647 SetResult(result);
648 AsyncWorkCompleted();
651 UsbGetDevicesFunction::UsbGetDevicesFunction() {
654 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
657 bool UsbGetDevicesFunction::Prepare() {
658 parameters_ = GetDevices::Params::Create(*args_);
659 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
660 return true;
663 void UsbGetDevicesFunction::AsyncWorkStart() {
664 std::vector<UsbDeviceFilter> filters;
665 if (parameters_->options.filters) {
666 filters.resize(parameters_->options.filters->size());
667 for (size_t i = 0; i < parameters_->options.filters->size(); ++i) {
668 CreateDeviceFilter(*parameters_->options.filters->at(i).get(),
669 &filters[i]);
672 if (parameters_->options.vendor_id) {
673 filters.resize(filters.size() + 1);
674 filters.back().SetVendorId(*parameters_->options.vendor_id);
675 if (parameters_->options.product_id) {
676 filters.back().SetProductId(*parameters_->options.product_id);
680 UsbService* service = device::DeviceClient::Get()->GetUsbService();
681 if (!service) {
682 CompleteWithError(kErrorInitService);
683 return;
686 DeviceVector devices;
687 service->GetDevices(&devices);
689 scoped_ptr<base::ListValue> result(new base::ListValue());
690 for (DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) {
691 scoped_refptr<UsbDevice> device = *it;
692 if ((filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) &&
693 HasDevicePermission(device)) {
694 result->Append(PopulateDevice(it->get()));
698 SetResult(result.release());
699 AsyncWorkCompleted();
702 UsbRequestAccessFunction::UsbRequestAccessFunction() {
705 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
708 bool UsbRequestAccessFunction::Prepare() {
709 parameters_ = RequestAccess::Params::Create(*args_);
710 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
711 return true;
714 void UsbRequestAccessFunction::AsyncWorkStart() {
715 #if defined(OS_CHROMEOS)
716 scoped_refptr<UsbDevice> device =
717 GetDeviceOrCompleteWithError(parameters_->device);
718 if (!device)
719 return;
721 device->RequestUsbAccess(
722 parameters_->interface_id,
723 base::Bind(&UsbRequestAccessFunction::OnCompleted, this));
724 #else
725 SetResult(new base::FundamentalValue(false));
726 CompleteWithError(kErrorNotSupported);
727 #endif // OS_CHROMEOS
730 void UsbRequestAccessFunction::OnCompleted(bool success) {
731 SetResult(new base::FundamentalValue(success));
732 AsyncWorkCompleted();
735 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
738 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
741 bool UsbOpenDeviceFunction::Prepare() {
742 parameters_ = OpenDevice::Params::Create(*args_);
743 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
744 return true;
747 void UsbOpenDeviceFunction::AsyncWorkStart() {
748 scoped_refptr<UsbDevice> device =
749 GetDeviceOrCompleteWithError(parameters_->device);
750 if (!device.get())
751 return;
753 handle_ = device->Open();
754 if (!handle_.get()) {
755 SetError(kErrorOpen);
756 AsyncWorkCompleted();
757 return;
760 SetResult(PopulateConnectionHandle(
761 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)),
762 handle_->GetDevice()->vendor_id(),
763 handle_->GetDevice()->product_id()));
764 AsyncWorkCompleted();
767 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
770 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
773 bool UsbGetConfigurationFunction::Prepare() {
774 parameters_ = GetConfiguration::Params::Create(*args_);
775 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
776 return true;
779 void UsbGetConfigurationFunction::AsyncWorkStart() {
780 scoped_refptr<UsbDeviceHandle> device_handle =
781 GetDeviceHandleOrCompleteWithError(parameters_->handle);
782 if (!device_handle.get()) {
783 return;
786 ConfigDescriptor config;
787 ConvertConfigDescriptor(device_handle->GetDevice()->GetConfiguration(),
788 &config);
790 SetResult(config.ToValue().release());
791 AsyncWorkCompleted();
794 UsbListInterfacesFunction::UsbListInterfacesFunction() {
797 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
800 bool UsbListInterfacesFunction::Prepare() {
801 parameters_ = ListInterfaces::Params::Create(*args_);
802 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
803 return true;
806 void UsbListInterfacesFunction::AsyncWorkStart() {
807 scoped_refptr<UsbDeviceHandle> device_handle =
808 GetDeviceHandleOrCompleteWithError(parameters_->handle);
809 if (!device_handle.get()) {
810 return;
813 ConfigDescriptor config;
814 ConvertConfigDescriptor(device_handle->GetDevice()->GetConfiguration(),
815 &config);
817 scoped_ptr<base::ListValue> result(new base::ListValue);
818 for (size_t i = 0; i < config.interfaces.size(); ++i) {
819 result->Append(config.interfaces[i]->ToValue().release());
822 SetResult(result.release());
823 AsyncWorkCompleted();
826 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
829 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
832 bool UsbCloseDeviceFunction::Prepare() {
833 parameters_ = CloseDevice::Params::Create(*args_);
834 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
835 return true;
838 void UsbCloseDeviceFunction::AsyncWorkStart() {
839 scoped_refptr<UsbDeviceHandle> device_handle =
840 GetDeviceHandleOrCompleteWithError(parameters_->handle);
841 if (!device_handle.get())
842 return;
844 device_handle->Close();
845 RemoveUsbDeviceResource(parameters_->handle.handle);
846 AsyncWorkCompleted();
849 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
852 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
855 bool UsbClaimInterfaceFunction::Prepare() {
856 parameters_ = ClaimInterface::Params::Create(*args_);
857 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
858 return true;
861 void UsbClaimInterfaceFunction::AsyncWorkStart() {
862 scoped_refptr<UsbDeviceHandle> device_handle =
863 GetDeviceHandleOrCompleteWithError(parameters_->handle);
864 if (!device_handle.get())
865 return;
867 bool success = device_handle->ClaimInterface(parameters_->interface_number);
869 if (!success)
870 SetError(kErrorCannotClaimInterface);
871 AsyncWorkCompleted();
874 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
877 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
880 bool UsbReleaseInterfaceFunction::Prepare() {
881 parameters_ = ReleaseInterface::Params::Create(*args_);
882 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
883 return true;
886 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
887 scoped_refptr<UsbDeviceHandle> device_handle =
888 GetDeviceHandleOrCompleteWithError(parameters_->handle);
889 if (!device_handle.get())
890 return;
892 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
893 if (!success)
894 SetError(kErrorCannotReleaseInterface);
895 AsyncWorkCompleted();
898 UsbSetInterfaceAlternateSettingFunction::
899 UsbSetInterfaceAlternateSettingFunction() {
902 UsbSetInterfaceAlternateSettingFunction::
903 ~UsbSetInterfaceAlternateSettingFunction() {
906 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
907 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
908 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
909 return true;
912 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
913 scoped_refptr<UsbDeviceHandle> device_handle =
914 GetDeviceHandleOrCompleteWithError(parameters_->handle);
915 if (!device_handle.get())
916 return;
918 bool success = device_handle->SetInterfaceAlternateSetting(
919 parameters_->interface_number, parameters_->alternate_setting);
920 if (!success)
921 SetError(kErrorCannotSetInterfaceAlternateSetting);
923 AsyncWorkCompleted();
926 UsbControlTransferFunction::UsbControlTransferFunction() {
929 UsbControlTransferFunction::~UsbControlTransferFunction() {
932 bool UsbControlTransferFunction::Prepare() {
933 parameters_ = ControlTransfer::Params::Create(*args_);
934 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
935 return true;
938 void UsbControlTransferFunction::AsyncWorkStart() {
939 scoped_refptr<UsbDeviceHandle> device_handle =
940 GetDeviceHandleOrCompleteWithError(parameters_->handle);
941 if (!device_handle.get())
942 return;
944 const ControlTransferInfo& transfer = parameters_->transfer_info;
946 UsbEndpointDirection direction;
947 UsbDeviceHandle::TransferRequestType request_type;
948 UsbDeviceHandle::TransferRecipient recipient;
949 size_t size = 0;
951 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
952 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
953 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
954 AsyncWorkCompleted();
955 return;
958 if (!GetTransferSize(transfer, &size)) {
959 CompleteWithError(kErrorInvalidTransferLength);
960 return;
963 scoped_refptr<net::IOBuffer> buffer =
964 CreateBufferForTransfer(transfer, direction, size);
965 if (!buffer.get()) {
966 CompleteWithError(kErrorMalformedParameters);
967 return;
970 device_handle->ControlTransfer(
971 direction,
972 request_type,
973 recipient,
974 transfer.request,
975 transfer.value,
976 transfer.index,
977 buffer.get(),
978 size,
980 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
983 UsbBulkTransferFunction::UsbBulkTransferFunction() {
986 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
989 bool UsbBulkTransferFunction::Prepare() {
990 parameters_ = BulkTransfer::Params::Create(*args_);
991 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
992 return true;
995 void UsbBulkTransferFunction::AsyncWorkStart() {
996 scoped_refptr<UsbDeviceHandle> device_handle =
997 GetDeviceHandleOrCompleteWithError(parameters_->handle);
998 if (!device_handle.get())
999 return;
1001 const GenericTransferInfo& transfer = parameters_->transfer_info;
1003 UsbEndpointDirection direction;
1004 size_t size = 0;
1006 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1007 AsyncWorkCompleted();
1008 return;
1011 if (!GetTransferSize(transfer, &size)) {
1012 CompleteWithError(kErrorInvalidTransferLength);
1013 return;
1016 scoped_refptr<net::IOBuffer> buffer =
1017 CreateBufferForTransfer(transfer, direction, size);
1018 if (!buffer.get()) {
1019 CompleteWithError(kErrorMalformedParameters);
1020 return;
1023 device_handle->BulkTransfer(
1024 direction,
1025 transfer.endpoint,
1026 buffer.get(),
1027 size,
1029 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1032 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1035 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1038 bool UsbInterruptTransferFunction::Prepare() {
1039 parameters_ = InterruptTransfer::Params::Create(*args_);
1040 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1041 return true;
1044 void UsbInterruptTransferFunction::AsyncWorkStart() {
1045 scoped_refptr<UsbDeviceHandle> device_handle =
1046 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1047 if (!device_handle.get())
1048 return;
1050 const GenericTransferInfo& transfer = parameters_->transfer_info;
1052 UsbEndpointDirection direction;
1053 size_t size = 0;
1055 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1056 AsyncWorkCompleted();
1057 return;
1060 if (!GetTransferSize(transfer, &size)) {
1061 CompleteWithError(kErrorInvalidTransferLength);
1062 return;
1065 scoped_refptr<net::IOBuffer> buffer =
1066 CreateBufferForTransfer(transfer, direction, size);
1067 if (!buffer.get()) {
1068 CompleteWithError(kErrorMalformedParameters);
1069 return;
1072 device_handle->InterruptTransfer(
1073 direction,
1074 transfer.endpoint,
1075 buffer.get(),
1076 size,
1078 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1081 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1084 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1087 bool UsbIsochronousTransferFunction::Prepare() {
1088 parameters_ = IsochronousTransfer::Params::Create(*args_);
1089 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1090 return true;
1093 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1094 scoped_refptr<UsbDeviceHandle> device_handle =
1095 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1096 if (!device_handle.get())
1097 return;
1099 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1100 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1102 size_t size = 0;
1103 UsbEndpointDirection direction;
1105 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1106 AsyncWorkCompleted();
1107 return;
1109 if (!GetTransferSize(generic_transfer, &size)) {
1110 CompleteWithError(kErrorInvalidTransferLength);
1111 return;
1113 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1114 CompleteWithError(kErrorInvalidNumberOfPackets);
1115 return;
1117 unsigned int packets = transfer.packets;
1118 if (transfer.packet_length < 0 ||
1119 transfer.packet_length >= kMaxPacketLength) {
1120 CompleteWithError(kErrorInvalidPacketLength);
1121 return;
1123 unsigned int packet_length = transfer.packet_length;
1124 const uint64 total_length = packets * packet_length;
1125 if (packets > size || total_length > size) {
1126 CompleteWithError(kErrorTransferLength);
1127 return;
1130 scoped_refptr<net::IOBuffer> buffer =
1131 CreateBufferForTransfer(generic_transfer, direction, size);
1132 if (!buffer.get()) {
1133 CompleteWithError(kErrorMalformedParameters);
1134 return;
1137 device_handle->IsochronousTransfer(
1138 direction,
1139 generic_transfer.endpoint,
1140 buffer.get(),
1141 size,
1142 packets,
1143 packet_length,
1145 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1148 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1151 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1154 bool UsbResetDeviceFunction::Prepare() {
1155 parameters_ = ResetDevice::Params::Create(*args_);
1156 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1157 return true;
1160 void UsbResetDeviceFunction::AsyncWorkStart() {
1161 scoped_refptr<UsbDeviceHandle> device_handle =
1162 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1163 if (!device_handle.get())
1164 return;
1166 bool success = device_handle->ResetDevice();
1167 if (!success) {
1168 device_handle->Close();
1169 RemoveUsbDeviceResource(parameters_->handle.handle);
1170 SetResult(new base::FundamentalValue(false));
1171 CompleteWithError(kErrorResetDevice);
1172 return;
1175 SetResult(new base::FundamentalValue(true));
1176 AsyncWorkCompleted();
1179 } // namespace extensions