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/barrier_closure.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "device/core/device_client.h"
13 #include "device/usb/usb_descriptors.h"
14 #include "device/usb/usb_device_handle.h"
15 #include "device/usb/usb_service.h"
16 #include "extensions/browser/api/device_permissions_manager.h"
17 #include "extensions/browser/api/device_permissions_prompt.h"
18 #include "extensions/browser/api/extensions_api_client.h"
19 #include "extensions/browser/api/usb/usb_device_resource.h"
20 #include "extensions/browser/api/usb/usb_guid_map.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/common/api/usb.h"
23 #include "extensions/common/permissions/permissions_data.h"
24 #include "extensions/common/permissions/usb_device_permission.h"
26 namespace usb
= extensions::api::usb
;
27 namespace BulkTransfer
= usb::BulkTransfer
;
28 namespace ClaimInterface
= usb::ClaimInterface
;
29 namespace CloseDevice
= usb::CloseDevice
;
30 namespace ControlTransfer
= usb::ControlTransfer
;
31 namespace FindDevices
= usb::FindDevices
;
32 namespace GetConfigurations
= usb::GetConfigurations
;
33 namespace GetDevices
= usb::GetDevices
;
34 namespace GetUserSelectedDevices
= usb::GetUserSelectedDevices
;
35 namespace InterruptTransfer
= usb::InterruptTransfer
;
36 namespace IsochronousTransfer
= usb::IsochronousTransfer
;
37 namespace SetConfiguration
= usb::SetConfiguration
;
38 namespace GetConfiguration
= usb::GetConfiguration
;
39 namespace ListInterfaces
= usb::ListInterfaces
;
40 namespace OpenDevice
= usb::OpenDevice
;
41 namespace ReleaseInterface
= usb::ReleaseInterface
;
42 namespace RequestAccess
= usb::RequestAccess
;
43 namespace ResetDevice
= usb::ResetDevice
;
44 namespace SetInterfaceAlternateSetting
= usb::SetInterfaceAlternateSetting
;
46 using content::BrowserThread
;
47 using device::UsbConfigDescriptor
;
48 using device::UsbDevice
;
49 using device::UsbDeviceFilter
;
50 using device::UsbDeviceHandle
;
51 using device::UsbEndpointDescriptor
;
52 using device::UsbEndpointDirection
;
53 using device::UsbInterfaceDescriptor
;
54 using device::UsbService
;
55 using device::UsbSynchronizationType
;
56 using device::UsbTransferStatus
;
57 using device::UsbTransferType
;
58 using device::UsbUsageType
;
61 using usb::ConfigDescriptor
;
62 using usb::ControlTransferInfo
;
63 using usb::ConnectionHandle
;
66 using usb::EndpointDescriptor
;
67 using usb::GenericTransferInfo
;
68 using usb::InterfaceDescriptor
;
69 using usb::IsochronousTransferInfo
;
71 using usb::RequestType
;
72 using usb::SynchronizationType
;
73 using usb::TransferType
;
76 namespace extensions
{
80 const char kDataKey
[] = "data";
81 const char kResultCodeKey
[] = "resultCode";
83 const char kErrorInitService
[] = "Failed to initialize USB service.";
85 const char kErrorOpen
[] = "Failed to open device.";
86 const char kErrorCancelled
[] = "Transfer was cancelled.";
87 const char kErrorDisconnect
[] = "Device disconnected.";
88 const char kErrorGeneric
[] = "Transfer failed.";
89 const char kErrorNotSupported
[] = "Not supported on this platform.";
90 const char kErrorNotConfigured
[] = "The device is not in a configured state.";
91 const char kErrorOverflow
[] = "Inbound transfer overflow.";
92 const char kErrorStalled
[] = "Transfer stalled.";
93 const char kErrorTimeout
[] = "Transfer timed out.";
94 const char kErrorTransferLength
[] = "Transfer length is insufficient.";
95 const char kErrorCannotSetConfiguration
[] =
96 "Error setting device configuration.";
97 const char kErrorCannotClaimInterface
[] = "Error claiming interface.";
98 const char kErrorCannotReleaseInterface
[] = "Error releasing interface.";
99 const char kErrorCannotSetInterfaceAlternateSetting
[] =
100 "Error setting alternate interface setting.";
101 const char kErrorConvertDirection
[] = "Invalid transfer direction.";
102 const char kErrorConvertRecipient
[] = "Invalid transfer recipient.";
103 const char kErrorConvertRequestType
[] = "Invalid request type.";
104 const char kErrorMalformedParameters
[] = "Error parsing parameters.";
105 const char kErrorNoConnection
[] = "No such connection.";
106 const char kErrorNoDevice
[] = "No such device.";
107 const char kErrorPermissionDenied
[] = "Permission to access device was denied";
108 const char kErrorInvalidTransferLength
[] =
109 "Transfer length must be a positive number less than 104,857,600.";
110 const char kErrorInvalidNumberOfPackets
[] =
111 "Number of packets must be a positive number less than 4,194,304.";
112 const char kErrorInvalidPacketLength
[] =
113 "Packet length must be a positive number less than 65,536.";
114 const char kErrorInvalidTimeout
[] =
115 "Transfer timeout must be greater than or equal to 0.";
116 const char kErrorResetDevice
[] =
117 "Error resetting the device. The device has been closed.";
119 const size_t kMaxTransferLength
= 100 * 1024 * 1024;
120 const int kMaxPackets
= 4 * 1024 * 1024;
121 const int kMaxPacketLength
= 64 * 1024;
123 bool ConvertDirectionFromApi(const Direction
& input
,
124 UsbEndpointDirection
* output
) {
126 case usb::DIRECTION_IN
:
127 *output
= device::USB_DIRECTION_INBOUND
;
129 case usb::DIRECTION_OUT
:
130 *output
= device::USB_DIRECTION_OUTBOUND
;
138 bool ConvertRequestTypeFromApi(const RequestType
& input
,
139 UsbDeviceHandle::TransferRequestType
* output
) {
141 case usb::REQUEST_TYPE_STANDARD
:
142 *output
= UsbDeviceHandle::STANDARD
;
144 case usb::REQUEST_TYPE_CLASS
:
145 *output
= UsbDeviceHandle::CLASS
;
147 case usb::REQUEST_TYPE_VENDOR
:
148 *output
= UsbDeviceHandle::VENDOR
;
150 case usb::REQUEST_TYPE_RESERVED
:
151 *output
= UsbDeviceHandle::RESERVED
;
159 bool ConvertRecipientFromApi(const Recipient
& input
,
160 UsbDeviceHandle::TransferRecipient
* output
) {
162 case usb::RECIPIENT_DEVICE
:
163 *output
= UsbDeviceHandle::DEVICE
;
165 case usb::RECIPIENT_INTERFACE
:
166 *output
= UsbDeviceHandle::INTERFACE
;
168 case usb::RECIPIENT_ENDPOINT
:
169 *output
= UsbDeviceHandle::ENDPOINT
;
171 case usb::RECIPIENT_OTHER
:
172 *output
= UsbDeviceHandle::OTHER
;
181 bool GetTransferSize(const T
& input
, size_t* output
) {
182 if (input
.direction
== usb::DIRECTION_IN
) {
183 const int* length
= input
.length
.get();
184 if (length
&& *length
>= 0 &&
185 static_cast<size_t>(*length
) < kMaxTransferLength
) {
189 } else if (input
.direction
== usb::DIRECTION_OUT
) {
190 if (input
.data
.get()) {
191 *output
= input
.data
->size();
199 scoped_refptr
<net::IOBuffer
> CreateBufferForTransfer(
201 UsbEndpointDirection direction
,
203 if (size
>= kMaxTransferLength
)
206 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
207 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
208 // cannot represent a zero-length buffer, while an URB can.
209 scoped_refptr
<net::IOBuffer
> buffer
=
210 new net::IOBuffer(std::max(static_cast<size_t>(1), size
));
212 if (direction
== device::USB_DIRECTION_INBOUND
) {
214 } else if (direction
== device::USB_DIRECTION_OUTBOUND
) {
215 if (input
.data
.get() && size
<= input
.data
->size()) {
216 memcpy(buffer
->data(), input
.data
->data(), size
);
224 const char* ConvertTransferStatusToApi(const UsbTransferStatus status
) {
226 case device::USB_TRANSFER_COMPLETED
:
228 case device::USB_TRANSFER_ERROR
:
229 return kErrorGeneric
;
230 case device::USB_TRANSFER_TIMEOUT
:
231 return kErrorTimeout
;
232 case device::USB_TRANSFER_CANCELLED
:
233 return kErrorCancelled
;
234 case device::USB_TRANSFER_STALLED
:
235 return kErrorStalled
;
236 case device::USB_TRANSFER_DISCONNECT
:
237 return kErrorDisconnect
;
238 case device::USB_TRANSFER_OVERFLOW
:
239 return kErrorOverflow
;
240 case device::USB_TRANSFER_LENGTH_SHORT
:
241 return kErrorTransferLength
;
248 base::Value
* PopulateConnectionHandle(int handle
,
251 ConnectionHandle result
;
252 result
.handle
= handle
;
253 result
.vendor_id
= vendor_id
;
254 result
.product_id
= product_id
;
255 return result
.ToValue().release();
258 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
260 case device::USB_TRANSFER_CONTROL
:
261 return usb::TRANSFER_TYPE_CONTROL
;
262 case device::USB_TRANSFER_INTERRUPT
:
263 return usb::TRANSFER_TYPE_INTERRUPT
;
264 case device::USB_TRANSFER_ISOCHRONOUS
:
265 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
266 case device::USB_TRANSFER_BULK
:
267 return usb::TRANSFER_TYPE_BULK
;
270 return usb::TRANSFER_TYPE_NONE
;
274 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
276 case device::USB_DIRECTION_INBOUND
:
277 return usb::DIRECTION_IN
;
278 case device::USB_DIRECTION_OUTBOUND
:
279 return usb::DIRECTION_OUT
;
282 return usb::DIRECTION_NONE
;
286 SynchronizationType
ConvertSynchronizationTypeToApi(
287 const UsbSynchronizationType
& input
) {
289 case device::USB_SYNCHRONIZATION_NONE
:
290 return usb::SYNCHRONIZATION_TYPE_NONE
;
291 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
292 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
293 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
294 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
295 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
296 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
299 return usb::SYNCHRONIZATION_TYPE_NONE
;
303 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
305 case device::USB_USAGE_DATA
:
306 return usb::USAGE_TYPE_DATA
;
307 case device::USB_USAGE_FEEDBACK
:
308 return usb::USAGE_TYPE_FEEDBACK
;
309 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
310 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
313 return usb::USAGE_TYPE_NONE
;
317 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
318 EndpointDescriptor
* output
) {
319 output
->address
= input
.address
;
320 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
321 output
->direction
= ConvertDirectionToApi(input
.direction
);
322 output
->maximum_packet_size
= input
.maximum_packet_size
;
323 output
->synchronization
=
324 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
325 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
326 output
->polling_interval
.reset(new int(input
.polling_interval
));
327 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
330 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
331 InterfaceDescriptor
* output
) {
332 output
->interface_number
= input
.interface_number
;
333 output
->alternate_setting
= input
.alternate_setting
;
334 output
->interface_class
= input
.interface_class
;
335 output
->interface_subclass
= input
.interface_subclass
;
336 output
->interface_protocol
= input
.interface_protocol
;
337 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
338 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
339 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
340 output
->endpoints
.push_back(endpoint
);
342 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
345 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
346 ConfigDescriptor
* output
) {
347 output
->configuration_value
= input
.configuration_value
;
348 output
->self_powered
= input
.self_powered
;
349 output
->remote_wakeup
= input
.remote_wakeup
;
350 output
->max_power
= input
.maximum_power
;
351 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
352 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
353 ConvertInterfaceDescriptor(input_interface
, interface
.get());
354 output
->interfaces
.push_back(interface
);
356 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
359 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
360 UsbDeviceFilter
* output
) {
361 if (input
.vendor_id
) {
362 output
->SetVendorId(*input
.vendor_id
);
364 if (input
.product_id
) {
365 output
->SetProductId(*input
.product_id
);
367 if (input
.interface_class
) {
368 output
->SetInterfaceClass(*input
.interface_class
);
370 if (input
.interface_subclass
) {
371 output
->SetInterfaceSubclass(*input
.interface_subclass
);
373 if (input
.interface_protocol
) {
374 output
->SetInterfaceProtocol(*input
.interface_protocol
);
380 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
381 : device_permissions_manager_(nullptr) {
384 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
387 bool UsbPermissionCheckingFunction::HasDevicePermission(
388 scoped_refptr
<UsbDevice
> device
) {
389 if (!device_permissions_manager_
) {
390 device_permissions_manager_
=
391 DevicePermissionsManager::Get(browser_context());
394 DevicePermissions
* device_permissions
=
395 device_permissions_manager_
->GetForExtension(extension_id());
396 DCHECK(device_permissions
);
398 permission_entry_
= device_permissions
->FindUsbDeviceEntry(device
);
399 if (permission_entry_
.get()) {
403 UsbDevicePermission::CheckParam
param(
405 device
->product_id(),
406 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
407 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
408 APIPermission::kUsbDevice
, ¶m
)) {
415 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
416 if (permission_entry_
.get()) {
417 device_permissions_manager_
->UpdateLastUsed(extension_id(),
422 UsbConnectionFunction::UsbConnectionFunction() {
425 UsbConnectionFunction::~UsbConnectionFunction() {
428 scoped_refptr
<device::UsbDeviceHandle
> UsbConnectionFunction::GetDeviceHandle(
429 const extensions::api::usb::ConnectionHandle
& handle
) {
430 ApiResourceManager
<UsbDeviceResource
>* manager
=
431 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
436 UsbDeviceResource
* resource
= manager
->Get(extension_id(), handle
.handle
);
441 return resource
->device();
444 void UsbConnectionFunction::ReleaseDeviceHandle(
445 const extensions::api::usb::ConnectionHandle
& handle
) {
446 ApiResourceManager
<UsbDeviceResource
>* manager
=
447 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
448 manager
->Remove(extension_id(), handle
.handle
);
451 UsbTransferFunction::UsbTransferFunction() {
454 UsbTransferFunction::~UsbTransferFunction() {
457 void UsbTransferFunction::OnCompleted(UsbTransferStatus status
,
458 scoped_refptr
<net::IOBuffer
> data
,
460 scoped_ptr
<base::DictionaryValue
> transfer_info(new base::DictionaryValue());
461 transfer_info
->SetInteger(kResultCodeKey
, status
);
462 transfer_info
->Set(kDataKey
, base::BinaryValue::CreateWithCopiedBuffer(
463 data
->data(), length
));
465 if (status
== device::USB_TRANSFER_COMPLETED
) {
466 Respond(OneArgument(transfer_info
.Pass()));
468 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
469 error_args
->Append(transfer_info
.Pass());
470 // Returning arguments with an error is wrong but we're stuck with it.
471 Respond(ErrorWithArguments(error_args
.Pass(),
472 ConvertTransferStatusToApi(status
)));
476 UsbFindDevicesFunction::UsbFindDevicesFunction() {
479 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
482 ExtensionFunction::ResponseAction
UsbFindDevicesFunction::Run() {
483 scoped_ptr
<extensions::api::usb::FindDevices::Params
> parameters
=
484 FindDevices::Params::Create(*args_
);
485 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
487 vendor_id_
= parameters
->options
.vendor_id
;
488 product_id_
= parameters
->options
.product_id
;
489 int interface_id
= parameters
->options
.interface_id
.get()
490 ? *parameters
->options
.interface_id
.get()
491 : UsbDevicePermissionData::ANY_INTERFACE
;
492 UsbDevicePermission::CheckParam
param(vendor_id_
, product_id_
, interface_id
);
493 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
494 APIPermission::kUsbDevice
, ¶m
)) {
495 return RespondNow(Error(kErrorPermissionDenied
));
498 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
500 return RespondNow(Error(kErrorInitService
));
504 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete
, this));
505 return RespondLater();
508 void UsbFindDevicesFunction::OnGetDevicesComplete(
509 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
510 result_
.reset(new base::ListValue());
511 barrier_
= base::BarrierClosure(
512 devices
.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete
, this));
514 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
515 if (device
->vendor_id() != vendor_id_
||
516 device
->product_id() != product_id_
) {
519 device
->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened
, this));
524 void UsbFindDevicesFunction::OnDeviceOpened(
525 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
526 if (device_handle
.get()) {
527 ApiResourceManager
<UsbDeviceResource
>* manager
=
528 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
529 UsbDeviceResource
* resource
=
530 new UsbDeviceResource(extension_id(), device_handle
);
531 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
532 result_
->Append(PopulateConnectionHandle(
533 manager
->Add(resource
), device
->vendor_id(), device
->product_id()));
538 void UsbFindDevicesFunction::OpenComplete() {
539 Respond(OneArgument(result_
.Pass()));
542 UsbGetDevicesFunction::UsbGetDevicesFunction() {
545 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
548 ExtensionFunction::ResponseAction
UsbGetDevicesFunction::Run() {
549 scoped_ptr
<extensions::api::usb::GetDevices::Params
> parameters
=
550 GetDevices::Params::Create(*args_
);
551 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
553 if (parameters
->options
.filters
) {
554 filters_
.resize(parameters
->options
.filters
->size());
555 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
556 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
560 if (parameters
->options
.vendor_id
) {
561 filters_
.resize(filters_
.size() + 1);
562 filters_
.back().SetVendorId(*parameters
->options
.vendor_id
);
563 if (parameters
->options
.product_id
) {
564 filters_
.back().SetProductId(*parameters
->options
.product_id
);
568 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
570 return RespondNow(Error(kErrorInitService
));
574 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete
, this));
575 return RespondLater();
578 void UsbGetDevicesFunction::OnGetDevicesComplete(
579 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
580 scoped_ptr
<base::ListValue
> result(new base::ListValue());
581 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
582 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
583 if ((filters_
.empty() || UsbDeviceFilter::MatchesAny(device
, filters_
)) &&
584 HasDevicePermission(device
)) {
586 guid_map
->GetApiDevice(device
, &api_device
);
587 result
->Append(api_device
.ToValue());
591 Respond(OneArgument(result
.Pass()));
594 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
597 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
600 ExtensionFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
601 scoped_ptr
<extensions::api::usb::GetUserSelectedDevices::Params
> parameters
=
602 GetUserSelectedDevices::Params::Create(*args_
);
603 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
605 if (!user_gesture()) {
606 return RespondNow(OneArgument(new base::ListValue()));
609 bool multiple
= false;
610 if (parameters
->options
.multiple
) {
611 multiple
= *parameters
->options
.multiple
;
614 std::vector
<UsbDeviceFilter
> filters
;
615 if (parameters
->options
.filters
) {
616 filters
.resize(parameters
->options
.filters
->size());
617 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
618 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
623 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
624 GetAssociatedWebContents());
626 return RespondNow(Error(kErrorNotSupported
));
629 prompt_
->AskForUsbDevices(
630 extension(), browser_context(), multiple
, filters
,
631 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen
, this));
632 return RespondLater();
635 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
636 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
637 scoped_ptr
<base::ListValue
> result(new base::ListValue());
638 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
639 for (const auto& device
: devices
) {
641 guid_map
->GetApiDevice(device
, &api_device
);
642 result
->Append(api_device
.ToValue());
645 Respond(OneArgument(result
.Pass()));
648 UsbGetConfigurationsFunction::UsbGetConfigurationsFunction() {}
650 UsbGetConfigurationsFunction::~UsbGetConfigurationsFunction() {}
652 ExtensionFunction::ResponseAction
UsbGetConfigurationsFunction::Run() {
653 scoped_ptr
<extensions::api::usb::GetConfigurations::Params
> parameters
=
654 GetConfigurations::Params::Create(*args_
);
655 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
657 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
659 return RespondNow(Error(kErrorInitService
));
663 if (!UsbGuidMap::Get(browser_context())
664 ->GetGuidFromId(parameters
->device
.device
, &guid
)) {
665 return RespondNow(Error(kErrorNoDevice
));
668 scoped_refptr
<UsbDevice
> device
= service
->GetDevice(guid
);
670 return RespondNow(Error(kErrorNoDevice
));
673 if (!HasDevicePermission(device
)) {
674 // This function must act as if there is no such device. Otherwise it can be
675 // used to fingerprint unauthorized devices.
676 return RespondNow(Error(kErrorNoDevice
));
679 scoped_ptr
<base::ListValue
> configs(new base::ListValue());
680 const UsbConfigDescriptor
* active_config
= device
->GetActiveConfiguration();
681 for (const UsbConfigDescriptor
& config
: device
->configurations()) {
682 ConfigDescriptor api_config
;
683 ConvertConfigDescriptor(config
, &api_config
);
685 config
.configuration_value
== active_config
->configuration_value
) {
686 api_config
.active
= true;
688 configs
->Append(api_config
.ToValue());
690 return RespondNow(OneArgument(configs
.Pass()));
693 UsbRequestAccessFunction::UsbRequestAccessFunction() {
696 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
699 ExtensionFunction::ResponseAction
UsbRequestAccessFunction::Run() {
700 scoped_ptr
<extensions::api::usb::RequestAccess::Params
> parameters
=
701 RequestAccess::Params::Create(*args_
);
702 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
703 return RespondNow(OneArgument(new base::FundamentalValue(true)));
706 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
709 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
712 ExtensionFunction::ResponseAction
UsbOpenDeviceFunction::Run() {
713 scoped_ptr
<extensions::api::usb::OpenDevice::Params
> parameters
=
714 OpenDevice::Params::Create(*args_
);
715 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
717 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
719 return RespondNow(Error(kErrorInitService
));
723 if (!UsbGuidMap::Get(browser_context())
724 ->GetGuidFromId(parameters
->device
.device
, &guid
)) {
725 return RespondNow(Error(kErrorNoDevice
));
728 scoped_refptr
<UsbDevice
> device
= service
->GetDevice(guid
);
730 return RespondNow(Error(kErrorNoDevice
));
733 if (!HasDevicePermission(device
)) {
734 // This function must act as if there is no such device. Otherwise it can be
735 // used to fingerprint unauthorized devices.
736 return RespondNow(Error(kErrorNoDevice
));
739 device
->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened
, this));
740 return RespondLater();
743 void UsbOpenDeviceFunction::OnDeviceOpened(
744 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
745 if (!device_handle
.get()) {
746 Respond(Error(kErrorOpen
));
750 RecordDeviceLastUsed();
752 ApiResourceManager
<UsbDeviceResource
>* manager
=
753 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
754 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
755 Respond(OneArgument(PopulateConnectionHandle(
756 manager
->Add(new UsbDeviceResource(extension_id(), device_handle
)),
757 device
->vendor_id(), device
->product_id())));
760 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
763 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
766 ExtensionFunction::ResponseAction
UsbSetConfigurationFunction::Run() {
767 scoped_ptr
<extensions::api::usb::SetConfiguration::Params
> parameters
=
768 SetConfiguration::Params::Create(*args_
);
769 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
771 scoped_refptr
<UsbDeviceHandle
> device_handle
=
772 GetDeviceHandle(parameters
->handle
);
773 if (!device_handle
.get()) {
774 return RespondNow(Error(kErrorNoConnection
));
777 device_handle
->SetConfiguration(
778 parameters
->configuration_value
,
779 base::Bind(&UsbSetConfigurationFunction::OnComplete
, this));
780 return RespondLater();
783 void UsbSetConfigurationFunction::OnComplete(bool success
) {
785 Respond(NoArguments());
787 Respond(Error(kErrorCannotSetConfiguration
));
791 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
794 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
797 ExtensionFunction::ResponseAction
UsbGetConfigurationFunction::Run() {
798 scoped_ptr
<extensions::api::usb::GetConfiguration::Params
> parameters
=
799 GetConfiguration::Params::Create(*args_
);
800 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
802 scoped_refptr
<UsbDeviceHandle
> device_handle
=
803 GetDeviceHandle(parameters
->handle
);
804 if (!device_handle
.get()) {
805 return RespondNow(Error(kErrorNoConnection
));
808 const UsbConfigDescriptor
* config_descriptor
=
809 device_handle
->GetDevice()->GetActiveConfiguration();
810 if (config_descriptor
) {
811 ConfigDescriptor config
;
812 ConvertConfigDescriptor(*config_descriptor
, &config
);
813 config
.active
= true;
814 return RespondNow(OneArgument(config
.ToValue()));
816 return RespondNow(Error(kErrorNotConfigured
));
820 UsbListInterfacesFunction::UsbListInterfacesFunction() {
823 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
826 ExtensionFunction::ResponseAction
UsbListInterfacesFunction::Run() {
827 scoped_ptr
<extensions::api::usb::ListInterfaces::Params
> parameters
=
828 ListInterfaces::Params::Create(*args_
);
829 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
831 scoped_refptr
<UsbDeviceHandle
> device_handle
=
832 GetDeviceHandle(parameters
->handle
);
833 if (!device_handle
.get()) {
834 return RespondNow(Error(kErrorNoConnection
));
837 const UsbConfigDescriptor
* config_descriptor
=
838 device_handle
->GetDevice()->GetActiveConfiguration();
839 if (config_descriptor
) {
840 ConfigDescriptor config
;
841 ConvertConfigDescriptor(*config_descriptor
, &config
);
843 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
844 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
845 result
->Append(config
.interfaces
[i
]->ToValue());
848 return RespondNow(OneArgument(result
.Pass()));
850 return RespondNow(Error(kErrorNotConfigured
));
854 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
857 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
860 ExtensionFunction::ResponseAction
UsbCloseDeviceFunction::Run() {
861 scoped_ptr
<extensions::api::usb::CloseDevice::Params
> parameters
=
862 CloseDevice::Params::Create(*args_
);
863 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
865 scoped_refptr
<UsbDeviceHandle
> device_handle
=
866 GetDeviceHandle(parameters
->handle
);
867 if (!device_handle
.get()) {
868 return RespondNow(Error(kErrorNoConnection
));
871 // The device handle is closed when the resource is destroyed.
872 ReleaseDeviceHandle(parameters
->handle
);
873 return RespondNow(NoArguments());
876 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
879 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
882 ExtensionFunction::ResponseAction
UsbClaimInterfaceFunction::Run() {
883 scoped_ptr
<extensions::api::usb::ClaimInterface::Params
> parameters
=
884 ClaimInterface::Params::Create(*args_
);
885 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
887 scoped_refptr
<UsbDeviceHandle
> device_handle
=
888 GetDeviceHandle(parameters
->handle
);
889 if (!device_handle
.get()) {
890 return RespondNow(Error(kErrorNoConnection
));
893 device_handle
->ClaimInterface(
894 parameters
->interface_number
,
895 base::Bind(&UsbClaimInterfaceFunction::OnComplete
, this));
896 return RespondLater();
899 void UsbClaimInterfaceFunction::OnComplete(bool success
) {
901 Respond(NoArguments());
903 Respond(Error(kErrorCannotClaimInterface
));
907 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
910 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
913 ExtensionFunction::ResponseAction
UsbReleaseInterfaceFunction::Run() {
914 scoped_ptr
<extensions::api::usb::ReleaseInterface::Params
> parameters
=
915 ReleaseInterface::Params::Create(*args_
);
916 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
918 scoped_refptr
<UsbDeviceHandle
> device_handle
=
919 GetDeviceHandle(parameters
->handle
);
920 if (!device_handle
.get()) {
921 return RespondNow(Error(kErrorNoConnection
));
924 if (device_handle
->ReleaseInterface(parameters
->interface_number
)) {
925 return RespondNow(NoArguments());
927 return RespondNow(Error(kErrorCannotReleaseInterface
));
931 UsbSetInterfaceAlternateSettingFunction::
932 UsbSetInterfaceAlternateSettingFunction() {
935 UsbSetInterfaceAlternateSettingFunction::
936 ~UsbSetInterfaceAlternateSettingFunction() {
939 ExtensionFunction::ResponseAction
940 UsbSetInterfaceAlternateSettingFunction::Run() {
941 scoped_ptr
<extensions::api::usb::SetInterfaceAlternateSetting::Params
>
942 parameters
= SetInterfaceAlternateSetting::Params::Create(*args_
);
943 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
945 scoped_refptr
<UsbDeviceHandle
> device_handle
=
946 GetDeviceHandle(parameters
->handle
);
947 if (!device_handle
.get()) {
948 return RespondNow(Error(kErrorNoConnection
));
951 device_handle
->SetInterfaceAlternateSetting(
952 parameters
->interface_number
, parameters
->alternate_setting
,
953 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete
, this));
954 return RespondLater();
957 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success
) {
959 Respond(NoArguments());
961 Respond(Error(kErrorCannotSetInterfaceAlternateSetting
));
965 UsbControlTransferFunction::UsbControlTransferFunction() {
968 UsbControlTransferFunction::~UsbControlTransferFunction() {
971 ExtensionFunction::ResponseAction
UsbControlTransferFunction::Run() {
972 scoped_ptr
<extensions::api::usb::ControlTransfer::Params
> parameters
=
973 ControlTransfer::Params::Create(*args_
);
974 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
976 scoped_refptr
<UsbDeviceHandle
> device_handle
=
977 GetDeviceHandle(parameters
->handle
);
978 if (!device_handle
.get()) {
979 return RespondNow(Error(kErrorNoConnection
));
982 const ControlTransferInfo
& transfer
= parameters
->transfer_info
;
983 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
984 UsbDeviceHandle::TransferRequestType request_type
;
985 UsbDeviceHandle::TransferRecipient recipient
;
988 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
989 return RespondNow(Error(kErrorConvertDirection
));
992 if (!ConvertRequestTypeFromApi(transfer
.request_type
, &request_type
)) {
993 return RespondNow(Error(kErrorConvertRequestType
));
996 if (!ConvertRecipientFromApi(transfer
.recipient
, &recipient
)) {
997 return RespondNow(Error(kErrorConvertRecipient
));
1000 if (!GetTransferSize(transfer
, &size
)) {
1001 return RespondNow(Error(kErrorInvalidTransferLength
));
1004 scoped_refptr
<net::IOBuffer
> buffer
=
1005 CreateBufferForTransfer(transfer
, direction
, size
);
1006 if (!buffer
.get()) {
1007 return RespondNow(Error(kErrorMalformedParameters
));
1010 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1012 return RespondNow(Error(kErrorInvalidTimeout
));
1015 device_handle
->ControlTransfer(
1016 direction
, request_type
, recipient
, transfer
.request
, transfer
.value
,
1017 transfer
.index
, buffer
.get(), size
, timeout
,
1018 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
1019 return RespondLater();
1022 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1025 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1028 ExtensionFunction::ResponseAction
UsbBulkTransferFunction::Run() {
1029 scoped_ptr
<extensions::api::usb::BulkTransfer::Params
> parameters
=
1030 BulkTransfer::Params::Create(*args_
);
1031 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1033 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1034 GetDeviceHandle(parameters
->handle
);
1035 if (!device_handle
.get()) {
1036 return RespondNow(Error(kErrorNoConnection
));
1039 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1040 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1043 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1044 return RespondNow(Error(kErrorConvertDirection
));
1047 if (!GetTransferSize(transfer
, &size
)) {
1048 return RespondNow(Error(kErrorInvalidTransferLength
));
1051 scoped_refptr
<net::IOBuffer
> buffer
=
1052 CreateBufferForTransfer(transfer
, direction
, size
);
1053 if (!buffer
.get()) {
1054 return RespondNow(Error(kErrorMalformedParameters
));
1057 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1059 return RespondNow(Error(kErrorInvalidTimeout
));
1062 device_handle
->GenericTransfer(
1063 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1064 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1065 return RespondLater();
1068 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1071 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1074 ExtensionFunction::ResponseAction
UsbInterruptTransferFunction::Run() {
1075 scoped_ptr
<extensions::api::usb::InterruptTransfer::Params
> parameters
=
1076 InterruptTransfer::Params::Create(*args_
);
1077 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1079 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1080 GetDeviceHandle(parameters
->handle
);
1081 if (!device_handle
.get()) {
1082 return RespondNow(Error(kErrorNoConnection
));
1085 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1086 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1089 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1090 return RespondNow(Error(kErrorConvertDirection
));
1093 if (!GetTransferSize(transfer
, &size
)) {
1094 return RespondNow(Error(kErrorInvalidTransferLength
));
1097 scoped_refptr
<net::IOBuffer
> buffer
=
1098 CreateBufferForTransfer(transfer
, direction
, size
);
1099 if (!buffer
.get()) {
1100 return RespondNow(Error(kErrorMalformedParameters
));
1103 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1105 return RespondNow(Error(kErrorInvalidTimeout
));
1108 device_handle
->GenericTransfer(
1109 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1110 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1111 return RespondLater();
1114 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1117 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1120 ExtensionFunction::ResponseAction
UsbIsochronousTransferFunction::Run() {
1121 scoped_ptr
<extensions::api::usb::IsochronousTransfer::Params
> parameters
=
1122 IsochronousTransfer::Params::Create(*args_
);
1123 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1125 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1126 GetDeviceHandle(parameters
->handle
);
1127 if (!device_handle
.get()) {
1128 return RespondNow(Error(kErrorNoConnection
));
1131 const IsochronousTransferInfo
& transfer
= parameters
->transfer_info
;
1132 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1134 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1136 if (!ConvertDirectionFromApi(generic_transfer
.direction
, &direction
)) {
1137 return RespondNow(Error(kErrorConvertDirection
));
1140 if (!GetTransferSize(generic_transfer
, &size
)) {
1141 return RespondNow(Error(kErrorInvalidTransferLength
));
1144 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1145 return RespondNow(Error(kErrorInvalidNumberOfPackets
));
1148 unsigned int packets
= transfer
.packets
;
1149 if (transfer
.packet_length
< 0 ||
1150 transfer
.packet_length
>= kMaxPacketLength
) {
1151 return RespondNow(Error(kErrorInvalidPacketLength
));
1154 unsigned int packet_length
= transfer
.packet_length
;
1155 const uint64 total_length
= packets
* packet_length
;
1156 if (packets
> size
|| total_length
> size
) {
1157 return RespondNow(Error(kErrorTransferLength
));
1160 scoped_refptr
<net::IOBuffer
> buffer
=
1161 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1162 if (!buffer
.get()) {
1163 return RespondNow(Error(kErrorMalformedParameters
));
1166 int timeout
= generic_transfer
.timeout
? *generic_transfer
.timeout
: 0;
1168 return RespondNow(Error(kErrorInvalidTimeout
));
1171 device_handle
->IsochronousTransfer(
1172 direction
, generic_transfer
.endpoint
, buffer
.get(), size
, packets
,
1173 packet_length
, timeout
,
1174 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1175 return RespondLater();
1178 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1181 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1184 ExtensionFunction::ResponseAction
UsbResetDeviceFunction::Run() {
1185 parameters_
= ResetDevice::Params::Create(*args_
);
1186 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1188 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1189 GetDeviceHandle(parameters_
->handle
);
1190 if (!device_handle
.get()) {
1191 return RespondNow(Error(kErrorNoConnection
));
1194 device_handle
->ResetDevice(
1195 base::Bind(&UsbResetDeviceFunction::OnComplete
, this));
1196 return RespondLater();
1199 void UsbResetDeviceFunction::OnComplete(bool success
) {
1201 Respond(OneArgument(new base::FundamentalValue(true)));
1203 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1204 GetDeviceHandle(parameters_
->handle
);
1205 if (device_handle
.get()) {
1206 device_handle
->Close();
1208 ReleaseDeviceHandle(parameters_
->handle
);
1210 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
1211 error_args
->AppendBoolean(false);
1212 // Returning arguments with an error is wrong but we're stuck with it.
1213 Respond(ErrorWithArguments(error_args
.Pass(), kErrorResetDevice
));
1217 } // namespace extensions