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"
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/device_permissions_manager.h"
16 #include "extensions/browser/api/device_permissions_prompt.h"
17 #include "extensions/browser/api/extensions_api_client.h"
18 #include "extensions/browser/api/usb/usb_device_resource.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/common/api/usb.h"
21 #include "extensions/common/permissions/permissions_data.h"
22 #include "extensions/common/permissions/usb_device_permission.h"
24 namespace usb
= extensions::core_api::usb
;
25 namespace BulkTransfer
= usb::BulkTransfer
;
26 namespace ClaimInterface
= usb::ClaimInterface
;
27 namespace CloseDevice
= usb::CloseDevice
;
28 namespace ControlTransfer
= usb::ControlTransfer
;
29 namespace FindDevices
= usb::FindDevices
;
30 namespace GetDevices
= usb::GetDevices
;
31 namespace GetUserSelectedDevices
= usb::GetUserSelectedDevices
;
32 namespace InterruptTransfer
= usb::InterruptTransfer
;
33 namespace IsochronousTransfer
= usb::IsochronousTransfer
;
34 namespace SetConfiguration
= usb::SetConfiguration
;
35 namespace GetConfiguration
= usb::GetConfiguration
;
36 namespace ListInterfaces
= usb::ListInterfaces
;
37 namespace OpenDevice
= usb::OpenDevice
;
38 namespace ReleaseInterface
= usb::ReleaseInterface
;
39 namespace RequestAccess
= usb::RequestAccess
;
40 namespace ResetDevice
= usb::ResetDevice
;
41 namespace SetInterfaceAlternateSetting
= usb::SetInterfaceAlternateSetting
;
43 using content::BrowserThread
;
44 using device::UsbConfigDescriptor
;
45 using device::UsbDevice
;
46 using device::UsbDeviceFilter
;
47 using device::UsbDeviceHandle
;
48 using device::UsbEndpointDescriptor
;
49 using device::UsbEndpointDirection
;
50 using device::UsbInterfaceDescriptor
;
51 using device::UsbService
;
52 using device::UsbSynchronizationType
;
53 using device::UsbTransferStatus
;
54 using device::UsbTransferType
;
55 using device::UsbUsageType
;
58 using usb::ConfigDescriptor
;
59 using usb::ControlTransferInfo
;
60 using usb::ConnectionHandle
;
63 using usb::EndpointDescriptor
;
64 using usb::GenericTransferInfo
;
65 using usb::InterfaceDescriptor
;
66 using usb::IsochronousTransferInfo
;
68 using usb::RequestType
;
69 using usb::SynchronizationType
;
70 using usb::TransferType
;
73 typedef std::vector
<scoped_refptr
<UsbDevice
> > DeviceVector
;
74 typedef scoped_ptr
<DeviceVector
> ScopedDeviceVector
;
78 const char kDataKey
[] = "data";
79 const char kResultCodeKey
[] = "resultCode";
81 const char kErrorInitService
[] = "Failed to initialize USB service.";
83 const char kErrorOpen
[] = "Failed to open device.";
84 const char kErrorCancelled
[] = "Transfer was cancelled.";
85 const char kErrorDisconnect
[] = "Device disconnected.";
86 const char kErrorGeneric
[] = "Transfer failed.";
87 const char kErrorNotSupported
[] = "Not supported on this platform.";
88 const char kErrorNotConfigured
[] = "The device is not in a configured state.";
89 const char kErrorOverflow
[] = "Inbound transfer overflow.";
90 const char kErrorStalled
[] = "Transfer stalled.";
91 const char kErrorTimeout
[] = "Transfer timed out.";
92 const char kErrorTransferLength
[] = "Transfer length is insufficient.";
93 const char kErrorCannotSetConfiguration
[] =
94 "Error setting device configuration.";
95 const char kErrorCannotClaimInterface
[] = "Error claiming interface.";
96 const char kErrorCannotReleaseInterface
[] = "Error releasing interface.";
97 const char kErrorCannotSetInterfaceAlternateSetting
[] =
98 "Error setting alternate interface setting.";
99 const char kErrorConvertDirection
[] = "Invalid transfer direction.";
100 const char kErrorConvertRecipient
[] = "Invalid transfer recipient.";
101 const char kErrorConvertRequestType
[] = "Invalid request type.";
102 const char kErrorMalformedParameters
[] = "Error parsing parameters.";
103 const char kErrorNoDevice
[] = "No such device.";
104 const char kErrorPermissionDenied
[] = "Permission to access device was denied";
105 const char kErrorInvalidTransferLength
[] =
106 "Transfer length must be a positive number less than 104,857,600.";
107 const char kErrorInvalidNumberOfPackets
[] =
108 "Number of packets must be a positive number less than 4,194,304.";
109 const char kErrorInvalidPacketLength
[] =
110 "Packet length must be a positive number less than 65,536.";
111 const char kErrorInvalidTimeout
[] =
112 "Transfer timeout must be greater than or equal to 0.";
113 const char kErrorResetDevice
[] =
114 "Error resetting the device. The device has been closed.";
116 const size_t kMaxTransferLength
= 100 * 1024 * 1024;
117 const int kMaxPackets
= 4 * 1024 * 1024;
118 const int kMaxPacketLength
= 64 * 1024;
120 bool ConvertDirectionFromApi(const Direction
& input
,
121 UsbEndpointDirection
* output
) {
123 case usb::DIRECTION_IN
:
124 *output
= device::USB_DIRECTION_INBOUND
;
126 case usb::DIRECTION_OUT
:
127 *output
= device::USB_DIRECTION_OUTBOUND
;
135 bool ConvertRequestTypeFromApi(const RequestType
& input
,
136 UsbDeviceHandle::TransferRequestType
* output
) {
138 case usb::REQUEST_TYPE_STANDARD
:
139 *output
= UsbDeviceHandle::STANDARD
;
141 case usb::REQUEST_TYPE_CLASS
:
142 *output
= UsbDeviceHandle::CLASS
;
144 case usb::REQUEST_TYPE_VENDOR
:
145 *output
= UsbDeviceHandle::VENDOR
;
147 case usb::REQUEST_TYPE_RESERVED
:
148 *output
= UsbDeviceHandle::RESERVED
;
156 bool ConvertRecipientFromApi(const Recipient
& input
,
157 UsbDeviceHandle::TransferRecipient
* output
) {
159 case usb::RECIPIENT_DEVICE
:
160 *output
= UsbDeviceHandle::DEVICE
;
162 case usb::RECIPIENT_INTERFACE
:
163 *output
= UsbDeviceHandle::INTERFACE
;
165 case usb::RECIPIENT_ENDPOINT
:
166 *output
= UsbDeviceHandle::ENDPOINT
;
168 case usb::RECIPIENT_OTHER
:
169 *output
= UsbDeviceHandle::OTHER
;
178 bool GetTransferSize(const T
& input
, size_t* output
) {
179 if (input
.direction
== usb::DIRECTION_IN
) {
180 const int* length
= input
.length
.get();
181 if (length
&& *length
>= 0 &&
182 static_cast<size_t>(*length
) < kMaxTransferLength
) {
186 } else if (input
.direction
== usb::DIRECTION_OUT
) {
187 if (input
.data
.get()) {
188 *output
= input
.data
->size();
196 scoped_refptr
<net::IOBuffer
> CreateBufferForTransfer(
198 UsbEndpointDirection direction
,
200 if (size
>= kMaxTransferLength
)
203 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
204 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
205 // cannot represent a zero-length buffer, while an URB can.
206 scoped_refptr
<net::IOBuffer
> buffer
=
207 new net::IOBuffer(std::max(static_cast<size_t>(1), size
));
209 if (direction
== device::USB_DIRECTION_INBOUND
) {
211 } else if (direction
== device::USB_DIRECTION_OUTBOUND
) {
212 if (input
.data
.get() && size
<= input
.data
->size()) {
213 memcpy(buffer
->data(), input
.data
->data(), size
);
221 const char* ConvertTransferStatusToApi(const UsbTransferStatus status
) {
223 case device::USB_TRANSFER_COMPLETED
:
225 case device::USB_TRANSFER_ERROR
:
226 return kErrorGeneric
;
227 case device::USB_TRANSFER_TIMEOUT
:
228 return kErrorTimeout
;
229 case device::USB_TRANSFER_CANCELLED
:
230 return kErrorCancelled
;
231 case device::USB_TRANSFER_STALLED
:
232 return kErrorStalled
;
233 case device::USB_TRANSFER_DISCONNECT
:
234 return kErrorDisconnect
;
235 case device::USB_TRANSFER_OVERFLOW
:
236 return kErrorOverflow
;
237 case device::USB_TRANSFER_LENGTH_SHORT
:
238 return kErrorTransferLength
;
245 void RequestUsbDevicesAccessHelper(
246 ScopedDeviceVector devices
,
247 std::vector
<scoped_refptr
<UsbDevice
> >::iterator i
,
249 const base::Callback
<void(ScopedDeviceVector result
)>& callback
,
254 i
= devices
->erase(i
);
256 if (i
== devices
->end()) {
257 callback
.Run(devices
.Pass());
260 (*i
)->RequestUsbAccess(interface_id
,
261 base::Bind(RequestUsbDevicesAccessHelper
,
262 base::Passed(devices
.Pass()),
268 void RequestUsbDevicesAccess(
269 ScopedDeviceVector devices
,
271 const base::Callback
<void(ScopedDeviceVector result
)>& callback
) {
272 if (devices
->empty()) {
273 callback
.Run(devices
.Pass());
276 std::vector
<scoped_refptr
<UsbDevice
> >::iterator i
= devices
->begin();
277 (*i
)->RequestUsbAccess(interface_id
,
278 base::Bind(RequestUsbDevicesAccessHelper
,
279 base::Passed(devices
.Pass()),
285 base::DictionaryValue
* CreateTransferInfo(UsbTransferStatus status
,
286 scoped_refptr
<net::IOBuffer
> data
,
288 base::DictionaryValue
* result
= new base::DictionaryValue();
289 result
->SetInteger(kResultCodeKey
, status
);
290 result
->Set(kDataKey
,
291 base::BinaryValue::CreateWithCopiedBuffer(data
->data(), length
));
295 base::Value
* PopulateConnectionHandle(int handle
,
298 ConnectionHandle result
;
299 result
.handle
= handle
;
300 result
.vendor_id
= vendor_id
;
301 result
.product_id
= product_id
;
302 return result
.ToValue().release();
305 base::Value
* PopulateDevice(const UsbDevice
* device
) {
307 result
.device
= device
->unique_id();
308 result
.vendor_id
= device
->vendor_id();
309 result
.product_id
= device
->product_id();
310 return result
.ToValue().release();
313 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
315 case device::USB_TRANSFER_CONTROL
:
316 return usb::TRANSFER_TYPE_CONTROL
;
317 case device::USB_TRANSFER_INTERRUPT
:
318 return usb::TRANSFER_TYPE_INTERRUPT
;
319 case device::USB_TRANSFER_ISOCHRONOUS
:
320 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
321 case device::USB_TRANSFER_BULK
:
322 return usb::TRANSFER_TYPE_BULK
;
325 return usb::TRANSFER_TYPE_NONE
;
329 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
331 case device::USB_DIRECTION_INBOUND
:
332 return usb::DIRECTION_IN
;
333 case device::USB_DIRECTION_OUTBOUND
:
334 return usb::DIRECTION_OUT
;
337 return usb::DIRECTION_NONE
;
341 SynchronizationType
ConvertSynchronizationTypeToApi(
342 const UsbSynchronizationType
& input
) {
344 case device::USB_SYNCHRONIZATION_NONE
:
345 return usb::SYNCHRONIZATION_TYPE_NONE
;
346 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
347 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
348 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
349 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
350 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
351 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
354 return usb::SYNCHRONIZATION_TYPE_NONE
;
358 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
360 case device::USB_USAGE_DATA
:
361 return usb::USAGE_TYPE_DATA
;
362 case device::USB_USAGE_FEEDBACK
:
363 return usb::USAGE_TYPE_FEEDBACK
;
364 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
365 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
368 return usb::USAGE_TYPE_NONE
;
372 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
373 EndpointDescriptor
* output
) {
374 output
->address
= input
.address
;
375 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
376 output
->direction
= ConvertDirectionToApi(input
.direction
);
377 output
->maximum_packet_size
= input
.maximum_packet_size
;
378 output
->synchronization
=
379 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
380 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
381 output
->polling_interval
.reset(new int(input
.polling_interval
));
382 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
385 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
386 InterfaceDescriptor
* output
) {
387 output
->interface_number
= input
.interface_number
;
388 output
->alternate_setting
= input
.alternate_setting
;
389 output
->interface_class
= input
.interface_class
;
390 output
->interface_subclass
= input
.interface_subclass
;
391 output
->interface_protocol
= input
.interface_protocol
;
392 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
393 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
394 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
395 output
->endpoints
.push_back(endpoint
);
397 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
400 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
401 ConfigDescriptor
* output
) {
402 output
->configuration_value
= input
.configuration_value
;
403 output
->self_powered
= input
.self_powered
;
404 output
->remote_wakeup
= input
.remote_wakeup
;
405 output
->max_power
= input
.maximum_power
;
406 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
407 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
408 ConvertInterfaceDescriptor(input_interface
, interface
.get());
409 output
->interfaces
.push_back(interface
);
411 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
414 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
415 UsbDeviceFilter
* output
) {
416 if (input
.vendor_id
) {
417 output
->SetVendorId(*input
.vendor_id
);
419 if (input
.product_id
) {
420 output
->SetProductId(*input
.product_id
);
422 if (input
.interface_class
) {
423 output
->SetInterfaceClass(*input
.interface_class
);
425 if (input
.interface_subclass
) {
426 output
->SetInterfaceSubclass(*input
.interface_subclass
);
428 if (input
.interface_protocol
) {
429 output
->SetInterfaceProtocol(*input
.interface_protocol
);
435 namespace extensions
{
437 UsbAsyncApiFunction::UsbAsyncApiFunction() : manager_(NULL
) {
440 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
443 bool UsbAsyncApiFunction::PrePrepare() {
444 manager_
= ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
445 set_work_thread_id(BrowserThread::FILE);
446 return manager_
!= NULL
;
449 bool UsbAsyncApiFunction::Respond() {
450 return error_
.empty();
453 bool UsbAsyncApiFunction::HasDevicePermission(scoped_refptr
<UsbDevice
> device
) {
454 DCHECK(device_permissions_
);
456 // Check the DevicePermissionsManager first so that if an entry is found
457 // it can be stored for later. This requires the serial number.
458 base::string16 serial_number
;
459 device
->GetSerialNumber(&serial_number
);
461 permission_entry_
= device_permissions_
->FindEntry(device
, serial_number
);
462 if (permission_entry_
.get()) {
466 UsbDevicePermission::CheckParam
param(
468 device
->product_id(),
469 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
470 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
471 APIPermission::kUsbDevice
, ¶m
)) {
478 scoped_refptr
<UsbDeviceHandle
>
479 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
480 const ConnectionHandle
& input_device_handle
) {
481 UsbDeviceResource
* resource
=
482 manager_
->Get(extension_
->id(), input_device_handle
.handle
);
484 CompleteWithError(kErrorNoDevice
);
488 if (!resource
->device().get() || !resource
->device()->GetDevice().get()) {
489 CompleteWithError(kErrorDisconnect
);
490 manager_
->Remove(extension_
->id(), input_device_handle
.handle
);
494 if (resource
->device()->GetDevice()->vendor_id() !=
495 input_device_handle
.vendor_id
||
496 resource
->device()->GetDevice()->product_id() !=
497 input_device_handle
.product_id
) {
498 CompleteWithError(kErrorNoDevice
);
502 return resource
->device();
505 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id
) {
506 manager_
->Remove(extension_
->id(), api_resource_id
);
509 void UsbAsyncApiFunction::CompleteWithError(const std::string
& error
) {
511 AsyncWorkCompleted();
514 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {
517 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {
520 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status
,
521 scoped_refptr
<net::IOBuffer
> data
,
523 if (status
!= device::USB_TRANSFER_COMPLETED
)
524 SetError(ConvertTransferStatusToApi(status
));
526 SetResult(CreateTransferInfo(status
, data
, length
));
527 AsyncWorkCompleted();
530 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
531 const Direction
& input
,
532 UsbEndpointDirection
* output
) {
533 const bool converted
= ConvertDirectionFromApi(input
, output
);
535 SetError(kErrorConvertDirection
);
539 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
540 const RequestType
& input
,
541 UsbDeviceHandle::TransferRequestType
* output
) {
542 const bool converted
= ConvertRequestTypeFromApi(input
, output
);
544 SetError(kErrorConvertRequestType
);
548 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
549 const Recipient
& input
,
550 UsbDeviceHandle::TransferRecipient
* output
) {
551 const bool converted
= ConvertRecipientFromApi(input
, output
);
553 SetError(kErrorConvertRecipient
);
557 UsbFindDevicesFunction::UsbFindDevicesFunction() {
560 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
563 bool UsbFindDevicesFunction::Prepare() {
564 parameters_
= FindDevices::Params::Create(*args_
);
565 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
569 void UsbFindDevicesFunction::AsyncWorkStart() {
570 scoped_ptr
<base::ListValue
> result(new base::ListValue());
571 const uint16_t vendor_id
= parameters_
->options
.vendor_id
;
572 const uint16_t product_id
= parameters_
->options
.product_id
;
573 int interface_id
= parameters_
->options
.interface_id
.get()
574 ? *parameters_
->options
.interface_id
.get()
575 : UsbDevicePermissionData::ANY_INTERFACE
;
576 UsbDevicePermission::CheckParam
param(vendor_id
, product_id
, interface_id
);
577 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
578 APIPermission::kUsbDevice
, ¶m
)) {
579 LOG(WARNING
) << "Insufficient permissions to access device.";
580 CompleteWithError(kErrorPermissionDenied
);
584 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
586 CompleteWithError(kErrorInitService
);
590 ScopedDeviceVector
devices(new DeviceVector());
591 service
->GetDevices(devices
.get());
593 for (DeviceVector::iterator it
= devices
->begin(); it
!= devices
->end();) {
594 if ((*it
)->vendor_id() != vendor_id
|| (*it
)->product_id() != product_id
) {
595 it
= devices
->erase(it
);
601 RequestUsbDevicesAccess(
604 base::Bind(&UsbFindDevicesFunction::OpenDevices
, this));
607 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices
) {
608 base::ListValue
* result
= new base::ListValue();
610 for (size_t i
= 0; i
< devices
->size(); ++i
) {
611 scoped_refptr
<UsbDeviceHandle
> device_handle
= devices
->at(i
)->Open();
612 if (device_handle
.get())
613 device_handles_
.push_back(device_handle
);
616 for (size_t i
= 0; i
< device_handles_
.size(); ++i
) {
617 UsbDeviceHandle
* const device_handle
= device_handles_
[i
].get();
618 UsbDeviceResource
* const resource
=
619 new UsbDeviceResource(extension_
->id(), device_handle
);
621 result
->Append(PopulateConnectionHandle(manager_
->Add(resource
),
622 parameters_
->options
.vendor_id
,
623 parameters_
->options
.product_id
));
627 AsyncWorkCompleted();
630 UsbGetDevicesFunction::UsbGetDevicesFunction() {
633 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
636 bool UsbGetDevicesFunction::Prepare() {
637 parameters_
= GetDevices::Params::Create(*args_
);
638 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
639 device_permissions_
= DevicePermissionsManager::Get(browser_context())
640 ->GetForExtension(extension()->id());
644 void UsbGetDevicesFunction::AsyncWorkStart() {
645 std::vector
<UsbDeviceFilter
> filters
;
646 if (parameters_
->options
.filters
) {
647 filters
.resize(parameters_
->options
.filters
->size());
648 for (size_t i
= 0; i
< parameters_
->options
.filters
->size(); ++i
) {
649 ConvertDeviceFilter(*parameters_
->options
.filters
->at(i
).get(),
653 if (parameters_
->options
.vendor_id
) {
654 filters
.resize(filters
.size() + 1);
655 filters
.back().SetVendorId(*parameters_
->options
.vendor_id
);
656 if (parameters_
->options
.product_id
) {
657 filters
.back().SetProductId(*parameters_
->options
.product_id
);
661 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
663 CompleteWithError(kErrorInitService
);
667 DeviceVector devices
;
668 service
->GetDevices(&devices
);
670 scoped_ptr
<base::ListValue
> result(new base::ListValue());
671 for (DeviceVector::iterator it
= devices
.begin(); it
!= devices
.end(); ++it
) {
672 scoped_refptr
<UsbDevice
> device
= *it
;
673 if ((filters
.empty() || UsbDeviceFilter::MatchesAny(device
, filters
)) &&
674 HasDevicePermission(device
)) {
675 result
->Append(PopulateDevice(it
->get()));
679 SetResult(result
.release());
680 AsyncWorkCompleted();
683 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
686 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
689 AsyncApiFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
690 scoped_ptr
<extensions::core_api::usb::GetUserSelectedDevices::Params
>
691 parameters
= GetUserSelectedDevices::Params::Create(*args_
);
692 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
694 if (!user_gesture()) {
695 return RespondNow(OneArgument(new base::ListValue()));
698 bool multiple
= false;
699 if (parameters
->options
.multiple
) {
700 multiple
= *parameters
->options
.multiple
;
703 std::vector
<UsbDeviceFilter
> filters
;
704 if (parameters
->options
.filters
) {
705 filters
.resize(parameters
->options
.filters
->size());
706 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
707 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
712 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
713 GetAssociatedWebContents());
715 return RespondNow(Error(kErrorNotSupported
));
719 prompt_
->AskForUsbDevices(
720 this, extension(), browser_context(), multiple
, filters
);
721 return RespondLater();
724 void UsbGetUserSelectedDevicesFunction::OnUsbDevicesChosen(
725 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
726 scoped_ptr
<base::ListValue
> result(new base::ListValue());
727 for (const auto& device
: devices
) {
728 result
->Append(PopulateDevice(device
.get()));
731 SetResult(result
.release());
736 UsbRequestAccessFunction::UsbRequestAccessFunction() {
739 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
742 bool UsbRequestAccessFunction::Prepare() {
743 parameters_
= RequestAccess::Params::Create(*args_
);
744 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
748 void UsbRequestAccessFunction::AsyncWorkStart() {
749 SetResult(new base::FundamentalValue(true));
750 AsyncWorkCompleted();
753 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
756 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
759 bool UsbOpenDeviceFunction::Prepare() {
760 parameters_
= OpenDevice::Params::Create(*args_
);
761 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
762 device_permissions_manager_
=
763 DevicePermissionsManager::Get(browser_context());
764 device_permissions_
=
765 device_permissions_manager_
->GetForExtension(extension()->id());
769 void UsbOpenDeviceFunction::AsyncWorkStart() {
770 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
772 CompleteWithError(kErrorInitService
);
776 device_
= service
->GetDeviceById(parameters_
->device
.device
);
777 if (!device_
.get()) {
778 CompleteWithError(kErrorNoDevice
);
782 if (!HasDevicePermission(device_
)) {
783 // This function must act as if there is no such device. Otherwise it can be
784 // used to fingerprint unauthorized devices.
785 CompleteWithError(kErrorNoDevice
);
789 device_
->RequestUsbAccess(
790 -1, /* any interface, unused by the permission broker */
791 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete
, this));
794 void UsbOpenDeviceFunction::OnRequestAccessComplete(bool success
) {
796 SetError(kErrorPermissionDenied
);
797 AsyncWorkCompleted();
801 scoped_refptr
<UsbDeviceHandle
> handle
= device_
->Open();
803 SetError(kErrorOpen
);
804 AsyncWorkCompleted();
808 SetResult(PopulateConnectionHandle(
809 manager_
->Add(new UsbDeviceResource(extension_
->id(), handle
)),
810 device_
->vendor_id(), device_
->product_id()));
811 AsyncWorkCompleted();
814 bool UsbOpenDeviceFunction::Respond() {
815 if (permission_entry_
.get()) {
816 device_permissions_manager_
->UpdateLastUsed(extension_
->id(),
819 return UsbAsyncApiFunction::Respond();
822 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
825 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
828 bool UsbSetConfigurationFunction::Prepare() {
829 parameters_
= SetConfiguration::Params::Create(*args_
);
830 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
834 void UsbSetConfigurationFunction::AsyncWorkStart() {
835 scoped_refptr
<UsbDeviceHandle
> device_handle
=
836 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
837 if (!device_handle
.get()) {
841 if (!device_handle
->SetConfiguration(parameters_
->configuration_value
)) {
842 SetError(kErrorCannotSetConfiguration
);
844 AsyncWorkCompleted();
847 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
850 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
853 bool UsbGetConfigurationFunction::Prepare() {
854 parameters_
= GetConfiguration::Params::Create(*args_
);
855 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
859 void UsbGetConfigurationFunction::AsyncWorkStart() {
860 scoped_refptr
<UsbDeviceHandle
> device_handle
=
861 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
862 if (!device_handle
.get()) {
866 const UsbConfigDescriptor
* config_descriptor
=
867 device_handle
->GetDevice()->GetConfiguration();
868 if (config_descriptor
) {
869 ConfigDescriptor config
;
870 ConvertConfigDescriptor(*config_descriptor
, &config
);
871 SetResult(config
.ToValue().release());
873 SetError(kErrorNotConfigured
);
876 AsyncWorkCompleted();
879 UsbListInterfacesFunction::UsbListInterfacesFunction() {
882 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
885 bool UsbListInterfacesFunction::Prepare() {
886 parameters_
= ListInterfaces::Params::Create(*args_
);
887 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
891 void UsbListInterfacesFunction::AsyncWorkStart() {
892 scoped_refptr
<UsbDeviceHandle
> device_handle
=
893 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
894 if (!device_handle
.get()) {
898 const UsbConfigDescriptor
* config_descriptor
=
899 device_handle
->GetDevice()->GetConfiguration();
900 if (config_descriptor
) {
901 ConfigDescriptor config
;
902 ConvertConfigDescriptor(*config_descriptor
, &config
);
904 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
905 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
906 result
->Append(config
.interfaces
[i
]->ToValue().release());
909 SetResult(result
.release());
911 SetError(kErrorNotConfigured
);
914 AsyncWorkCompleted();
917 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
920 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
923 bool UsbCloseDeviceFunction::Prepare() {
924 parameters_
= CloseDevice::Params::Create(*args_
);
925 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
929 void UsbCloseDeviceFunction::AsyncWorkStart() {
930 scoped_refptr
<UsbDeviceHandle
> device_handle
=
931 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
932 if (!device_handle
.get())
935 // The device handle is closed when the resource is destroyed.
936 RemoveUsbDeviceResource(parameters_
->handle
.handle
);
937 AsyncWorkCompleted();
940 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
943 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
946 bool UsbClaimInterfaceFunction::Prepare() {
947 parameters_
= ClaimInterface::Params::Create(*args_
);
948 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
952 void UsbClaimInterfaceFunction::AsyncWorkStart() {
953 scoped_refptr
<UsbDeviceHandle
> device_handle
=
954 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
955 if (!device_handle
.get())
958 bool success
= device_handle
->ClaimInterface(parameters_
->interface_number
);
961 SetError(kErrorCannotClaimInterface
);
962 AsyncWorkCompleted();
965 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
968 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
971 bool UsbReleaseInterfaceFunction::Prepare() {
972 parameters_
= ReleaseInterface::Params::Create(*args_
);
973 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
977 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
978 scoped_refptr
<UsbDeviceHandle
> device_handle
=
979 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
980 if (!device_handle
.get())
983 bool success
= device_handle
->ReleaseInterface(parameters_
->interface_number
);
985 SetError(kErrorCannotReleaseInterface
);
986 AsyncWorkCompleted();
989 UsbSetInterfaceAlternateSettingFunction::
990 UsbSetInterfaceAlternateSettingFunction() {
993 UsbSetInterfaceAlternateSettingFunction::
994 ~UsbSetInterfaceAlternateSettingFunction() {
997 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
998 parameters_
= SetInterfaceAlternateSetting::Params::Create(*args_
);
999 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1003 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
1004 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1005 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1006 if (!device_handle
.get())
1009 bool success
= device_handle
->SetInterfaceAlternateSetting(
1010 parameters_
->interface_number
, parameters_
->alternate_setting
);
1012 SetError(kErrorCannotSetInterfaceAlternateSetting
);
1014 AsyncWorkCompleted();
1017 UsbControlTransferFunction::UsbControlTransferFunction() {
1020 UsbControlTransferFunction::~UsbControlTransferFunction() {
1023 bool UsbControlTransferFunction::Prepare() {
1024 parameters_
= ControlTransfer::Params::Create(*args_
);
1025 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1029 void UsbControlTransferFunction::AsyncWorkStart() {
1030 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1031 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1032 if (!device_handle
.get())
1035 const ControlTransferInfo
& transfer
= parameters_
->transfer_info
;
1037 UsbEndpointDirection direction
;
1038 UsbDeviceHandle::TransferRequestType request_type
;
1039 UsbDeviceHandle::TransferRecipient recipient
;
1042 if (!ConvertDirectionSafely(transfer
.direction
, &direction
) ||
1043 !ConvertRequestTypeSafely(transfer
.request_type
, &request_type
) ||
1044 !ConvertRecipientSafely(transfer
.recipient
, &recipient
)) {
1045 AsyncWorkCompleted();
1049 if (!GetTransferSize(transfer
, &size
)) {
1050 CompleteWithError(kErrorInvalidTransferLength
);
1054 scoped_refptr
<net::IOBuffer
> buffer
=
1055 CreateBufferForTransfer(transfer
, direction
, size
);
1056 if (!buffer
.get()) {
1057 CompleteWithError(kErrorMalformedParameters
);
1061 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1063 CompleteWithError(kErrorInvalidTimeout
);
1067 device_handle
->ControlTransfer(
1068 direction
, request_type
, recipient
, transfer
.request
, transfer
.value
,
1069 transfer
.index
, buffer
.get(), size
, timeout
,
1070 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
1073 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1076 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1079 bool UsbBulkTransferFunction::Prepare() {
1080 parameters_
= BulkTransfer::Params::Create(*args_
);
1081 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1085 void UsbBulkTransferFunction::AsyncWorkStart() {
1086 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1087 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1088 if (!device_handle
.get())
1091 const GenericTransferInfo
& transfer
= parameters_
->transfer_info
;
1093 UsbEndpointDirection direction
;
1096 if (!ConvertDirectionSafely(transfer
.direction
, &direction
)) {
1097 AsyncWorkCompleted();
1101 if (!GetTransferSize(transfer
, &size
)) {
1102 CompleteWithError(kErrorInvalidTransferLength
);
1106 scoped_refptr
<net::IOBuffer
> buffer
=
1107 CreateBufferForTransfer(transfer
, direction
, size
);
1108 if (!buffer
.get()) {
1109 CompleteWithError(kErrorMalformedParameters
);
1113 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1115 CompleteWithError(kErrorInvalidTimeout
);
1119 device_handle
->BulkTransfer(
1120 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1121 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1124 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1127 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1130 bool UsbInterruptTransferFunction::Prepare() {
1131 parameters_
= InterruptTransfer::Params::Create(*args_
);
1132 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1136 void UsbInterruptTransferFunction::AsyncWorkStart() {
1137 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1138 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1139 if (!device_handle
.get())
1142 const GenericTransferInfo
& transfer
= parameters_
->transfer_info
;
1144 UsbEndpointDirection direction
;
1147 if (!ConvertDirectionSafely(transfer
.direction
, &direction
)) {
1148 AsyncWorkCompleted();
1152 if (!GetTransferSize(transfer
, &size
)) {
1153 CompleteWithError(kErrorInvalidTransferLength
);
1157 scoped_refptr
<net::IOBuffer
> buffer
=
1158 CreateBufferForTransfer(transfer
, direction
, size
);
1159 if (!buffer
.get()) {
1160 CompleteWithError(kErrorMalformedParameters
);
1164 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1166 CompleteWithError(kErrorInvalidTimeout
);
1170 device_handle
->InterruptTransfer(
1171 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1172 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1175 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1178 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1181 bool UsbIsochronousTransferFunction::Prepare() {
1182 parameters_
= IsochronousTransfer::Params::Create(*args_
);
1183 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1187 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1188 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1189 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1190 if (!device_handle
.get())
1193 const IsochronousTransferInfo
& transfer
= parameters_
->transfer_info
;
1194 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1197 UsbEndpointDirection direction
;
1199 if (!ConvertDirectionSafely(generic_transfer
.direction
, &direction
)) {
1200 AsyncWorkCompleted();
1203 if (!GetTransferSize(generic_transfer
, &size
)) {
1204 CompleteWithError(kErrorInvalidTransferLength
);
1207 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1208 CompleteWithError(kErrorInvalidNumberOfPackets
);
1211 unsigned int packets
= transfer
.packets
;
1212 if (transfer
.packet_length
< 0 ||
1213 transfer
.packet_length
>= kMaxPacketLength
) {
1214 CompleteWithError(kErrorInvalidPacketLength
);
1217 unsigned int packet_length
= transfer
.packet_length
;
1218 const uint64 total_length
= packets
* packet_length
;
1219 if (packets
> size
|| total_length
> size
) {
1220 CompleteWithError(kErrorTransferLength
);
1224 scoped_refptr
<net::IOBuffer
> buffer
=
1225 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1226 if (!buffer
.get()) {
1227 CompleteWithError(kErrorMalformedParameters
);
1231 int timeout
= generic_transfer
.timeout
? *generic_transfer
.timeout
: 0;
1233 CompleteWithError(kErrorInvalidTimeout
);
1237 device_handle
->IsochronousTransfer(
1238 direction
, generic_transfer
.endpoint
, buffer
.get(), size
, packets
,
1239 packet_length
, timeout
,
1240 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1243 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1246 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1249 bool UsbResetDeviceFunction::Prepare() {
1250 parameters_
= ResetDevice::Params::Create(*args_
);
1251 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1255 void UsbResetDeviceFunction::AsyncWorkStart() {
1256 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1257 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1258 if (!device_handle
.get())
1261 bool success
= device_handle
->ResetDevice();
1263 device_handle
->Close();
1264 RemoveUsbDeviceResource(parameters_
->handle
.handle
);
1265 SetResult(new base::FundamentalValue(false));
1266 CompleteWithError(kErrorResetDevice
);
1270 SetResult(new base::FundamentalValue(true));
1271 AsyncWorkCompleted();
1274 } // namespace extensions