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 GetDevices
= usb::GetDevices
;
33 namespace GetUserSelectedDevices
= usb::GetUserSelectedDevices
;
34 namespace InterruptTransfer
= usb::InterruptTransfer
;
35 namespace IsochronousTransfer
= usb::IsochronousTransfer
;
36 namespace SetConfiguration
= usb::SetConfiguration
;
37 namespace GetConfiguration
= usb::GetConfiguration
;
38 namespace ListInterfaces
= usb::ListInterfaces
;
39 namespace OpenDevice
= usb::OpenDevice
;
40 namespace ReleaseInterface
= usb::ReleaseInterface
;
41 namespace RequestAccess
= usb::RequestAccess
;
42 namespace ResetDevice
= usb::ResetDevice
;
43 namespace SetInterfaceAlternateSetting
= usb::SetInterfaceAlternateSetting
;
45 using content::BrowserThread
;
46 using device::UsbConfigDescriptor
;
47 using device::UsbDevice
;
48 using device::UsbDeviceFilter
;
49 using device::UsbDeviceHandle
;
50 using device::UsbEndpointDescriptor
;
51 using device::UsbEndpointDirection
;
52 using device::UsbInterfaceDescriptor
;
53 using device::UsbService
;
54 using device::UsbSynchronizationType
;
55 using device::UsbTransferStatus
;
56 using device::UsbTransferType
;
57 using device::UsbUsageType
;
60 using usb::ConfigDescriptor
;
61 using usb::ControlTransferInfo
;
62 using usb::ConnectionHandle
;
65 using usb::EndpointDescriptor
;
66 using usb::GenericTransferInfo
;
67 using usb::InterfaceDescriptor
;
68 using usb::IsochronousTransferInfo
;
70 using usb::RequestType
;
71 using usb::SynchronizationType
;
72 using usb::TransferType
;
75 namespace extensions
{
79 const char kDataKey
[] = "data";
80 const char kResultCodeKey
[] = "resultCode";
82 const char kErrorInitService
[] = "Failed to initialize USB service.";
84 const char kErrorOpen
[] = "Failed to open device.";
85 const char kErrorCancelled
[] = "Transfer was cancelled.";
86 const char kErrorDisconnect
[] = "Device disconnected.";
87 const char kErrorGeneric
[] = "Transfer failed.";
88 const char kErrorNotSupported
[] = "Not supported on this platform.";
89 const char kErrorNotConfigured
[] = "The device is not in a configured state.";
90 const char kErrorOverflow
[] = "Inbound transfer overflow.";
91 const char kErrorStalled
[] = "Transfer stalled.";
92 const char kErrorTimeout
[] = "Transfer timed out.";
93 const char kErrorTransferLength
[] = "Transfer length is insufficient.";
94 const char kErrorCannotSetConfiguration
[] =
95 "Error setting device configuration.";
96 const char kErrorCannotClaimInterface
[] = "Error claiming interface.";
97 const char kErrorCannotReleaseInterface
[] = "Error releasing interface.";
98 const char kErrorCannotSetInterfaceAlternateSetting
[] =
99 "Error setting alternate interface setting.";
100 const char kErrorConvertDirection
[] = "Invalid transfer direction.";
101 const char kErrorConvertRecipient
[] = "Invalid transfer recipient.";
102 const char kErrorConvertRequestType
[] = "Invalid request type.";
103 const char kErrorMalformedParameters
[] = "Error parsing parameters.";
104 const char kErrorNoConnection
[] = "No such connection.";
105 const char kErrorNoDevice
[] = "No such device.";
106 const char kErrorPermissionDenied
[] = "Permission to access device was denied";
107 const char kErrorInvalidTransferLength
[] =
108 "Transfer length must be a positive number less than 104,857,600.";
109 const char kErrorInvalidNumberOfPackets
[] =
110 "Number of packets must be a positive number less than 4,194,304.";
111 const char kErrorInvalidPacketLength
[] =
112 "Packet length must be a positive number less than 65,536.";
113 const char kErrorInvalidTimeout
[] =
114 "Transfer timeout must be greater than or equal to 0.";
115 const char kErrorResetDevice
[] =
116 "Error resetting the device. The device has been closed.";
118 const size_t kMaxTransferLength
= 100 * 1024 * 1024;
119 const int kMaxPackets
= 4 * 1024 * 1024;
120 const int kMaxPacketLength
= 64 * 1024;
122 bool ConvertDirectionFromApi(const Direction
& input
,
123 UsbEndpointDirection
* output
) {
125 case usb::DIRECTION_IN
:
126 *output
= device::USB_DIRECTION_INBOUND
;
128 case usb::DIRECTION_OUT
:
129 *output
= device::USB_DIRECTION_OUTBOUND
;
137 bool ConvertRequestTypeFromApi(const RequestType
& input
,
138 UsbDeviceHandle::TransferRequestType
* output
) {
140 case usb::REQUEST_TYPE_STANDARD
:
141 *output
= UsbDeviceHandle::STANDARD
;
143 case usb::REQUEST_TYPE_CLASS
:
144 *output
= UsbDeviceHandle::CLASS
;
146 case usb::REQUEST_TYPE_VENDOR
:
147 *output
= UsbDeviceHandle::VENDOR
;
149 case usb::REQUEST_TYPE_RESERVED
:
150 *output
= UsbDeviceHandle::RESERVED
;
158 bool ConvertRecipientFromApi(const Recipient
& input
,
159 UsbDeviceHandle::TransferRecipient
* output
) {
161 case usb::RECIPIENT_DEVICE
:
162 *output
= UsbDeviceHandle::DEVICE
;
164 case usb::RECIPIENT_INTERFACE
:
165 *output
= UsbDeviceHandle::INTERFACE
;
167 case usb::RECIPIENT_ENDPOINT
:
168 *output
= UsbDeviceHandle::ENDPOINT
;
170 case usb::RECIPIENT_OTHER
:
171 *output
= UsbDeviceHandle::OTHER
;
180 bool GetTransferSize(const T
& input
, size_t* output
) {
181 if (input
.direction
== usb::DIRECTION_IN
) {
182 const int* length
= input
.length
.get();
183 if (length
&& *length
>= 0 &&
184 static_cast<size_t>(*length
) < kMaxTransferLength
) {
188 } else if (input
.direction
== usb::DIRECTION_OUT
) {
189 if (input
.data
.get()) {
190 *output
= input
.data
->size();
198 scoped_refptr
<net::IOBuffer
> CreateBufferForTransfer(
200 UsbEndpointDirection direction
,
202 if (size
>= kMaxTransferLength
)
205 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
206 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
207 // cannot represent a zero-length buffer, while an URB can.
208 scoped_refptr
<net::IOBuffer
> buffer
=
209 new net::IOBuffer(std::max(static_cast<size_t>(1), size
));
211 if (direction
== device::USB_DIRECTION_INBOUND
) {
213 } else if (direction
== device::USB_DIRECTION_OUTBOUND
) {
214 if (input
.data
.get() && size
<= input
.data
->size()) {
215 memcpy(buffer
->data(), input
.data
->data(), size
);
223 const char* ConvertTransferStatusToApi(const UsbTransferStatus status
) {
225 case device::USB_TRANSFER_COMPLETED
:
227 case device::USB_TRANSFER_ERROR
:
228 return kErrorGeneric
;
229 case device::USB_TRANSFER_TIMEOUT
:
230 return kErrorTimeout
;
231 case device::USB_TRANSFER_CANCELLED
:
232 return kErrorCancelled
;
233 case device::USB_TRANSFER_STALLED
:
234 return kErrorStalled
;
235 case device::USB_TRANSFER_DISCONNECT
:
236 return kErrorDisconnect
;
237 case device::USB_TRANSFER_OVERFLOW
:
238 return kErrorOverflow
;
239 case device::USB_TRANSFER_LENGTH_SHORT
:
240 return kErrorTransferLength
;
247 base::Value
* PopulateConnectionHandle(int handle
,
250 ConnectionHandle result
;
251 result
.handle
= handle
;
252 result
.vendor_id
= vendor_id
;
253 result
.product_id
= product_id
;
254 return result
.ToValue().release();
257 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
259 case device::USB_TRANSFER_CONTROL
:
260 return usb::TRANSFER_TYPE_CONTROL
;
261 case device::USB_TRANSFER_INTERRUPT
:
262 return usb::TRANSFER_TYPE_INTERRUPT
;
263 case device::USB_TRANSFER_ISOCHRONOUS
:
264 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
265 case device::USB_TRANSFER_BULK
:
266 return usb::TRANSFER_TYPE_BULK
;
269 return usb::TRANSFER_TYPE_NONE
;
273 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
275 case device::USB_DIRECTION_INBOUND
:
276 return usb::DIRECTION_IN
;
277 case device::USB_DIRECTION_OUTBOUND
:
278 return usb::DIRECTION_OUT
;
281 return usb::DIRECTION_NONE
;
285 SynchronizationType
ConvertSynchronizationTypeToApi(
286 const UsbSynchronizationType
& input
) {
288 case device::USB_SYNCHRONIZATION_NONE
:
289 return usb::SYNCHRONIZATION_TYPE_NONE
;
290 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
291 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
292 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
293 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
294 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
295 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
298 return usb::SYNCHRONIZATION_TYPE_NONE
;
302 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
304 case device::USB_USAGE_DATA
:
305 return usb::USAGE_TYPE_DATA
;
306 case device::USB_USAGE_FEEDBACK
:
307 return usb::USAGE_TYPE_FEEDBACK
;
308 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
309 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
312 return usb::USAGE_TYPE_NONE
;
316 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
317 EndpointDescriptor
* output
) {
318 output
->address
= input
.address
;
319 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
320 output
->direction
= ConvertDirectionToApi(input
.direction
);
321 output
->maximum_packet_size
= input
.maximum_packet_size
;
322 output
->synchronization
=
323 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
324 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
325 output
->polling_interval
.reset(new int(input
.polling_interval
));
326 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
329 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
330 InterfaceDescriptor
* output
) {
331 output
->interface_number
= input
.interface_number
;
332 output
->alternate_setting
= input
.alternate_setting
;
333 output
->interface_class
= input
.interface_class
;
334 output
->interface_subclass
= input
.interface_subclass
;
335 output
->interface_protocol
= input
.interface_protocol
;
336 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
337 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
338 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
339 output
->endpoints
.push_back(endpoint
);
341 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
344 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
345 ConfigDescriptor
* output
) {
346 output
->configuration_value
= input
.configuration_value
;
347 output
->self_powered
= input
.self_powered
;
348 output
->remote_wakeup
= input
.remote_wakeup
;
349 output
->max_power
= input
.maximum_power
;
350 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
351 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
352 ConvertInterfaceDescriptor(input_interface
, interface
.get());
353 output
->interfaces
.push_back(interface
);
355 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
358 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
359 UsbDeviceFilter
* output
) {
360 if (input
.vendor_id
) {
361 output
->SetVendorId(*input
.vendor_id
);
363 if (input
.product_id
) {
364 output
->SetProductId(*input
.product_id
);
366 if (input
.interface_class
) {
367 output
->SetInterfaceClass(*input
.interface_class
);
369 if (input
.interface_subclass
) {
370 output
->SetInterfaceSubclass(*input
.interface_subclass
);
372 if (input
.interface_protocol
) {
373 output
->SetInterfaceProtocol(*input
.interface_protocol
);
379 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
380 : device_permissions_manager_(nullptr) {
383 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
386 bool UsbPermissionCheckingFunction::HasDevicePermission(
387 scoped_refptr
<UsbDevice
> device
) {
388 if (!device_permissions_manager_
) {
389 device_permissions_manager_
=
390 DevicePermissionsManager::Get(browser_context());
393 DevicePermissions
* device_permissions
=
394 device_permissions_manager_
->GetForExtension(extension_id());
395 DCHECK(device_permissions
);
397 permission_entry_
= device_permissions
->FindUsbDeviceEntry(device
);
398 if (permission_entry_
.get()) {
402 UsbDevicePermission::CheckParam
param(
404 device
->product_id(),
405 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
406 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
407 APIPermission::kUsbDevice
, ¶m
)) {
414 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
415 if (permission_entry_
.get()) {
416 device_permissions_manager_
->UpdateLastUsed(extension_id(),
421 UsbConnectionFunction::UsbConnectionFunction() {
424 UsbConnectionFunction::~UsbConnectionFunction() {
427 scoped_refptr
<device::UsbDeviceHandle
> UsbConnectionFunction::GetDeviceHandle(
428 const extensions::api::usb::ConnectionHandle
& handle
) {
429 ApiResourceManager
<UsbDeviceResource
>* manager
=
430 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
435 UsbDeviceResource
* resource
= manager
->Get(extension_id(), handle
.handle
);
440 return resource
->device();
443 void UsbConnectionFunction::ReleaseDeviceHandle(
444 const extensions::api::usb::ConnectionHandle
& handle
) {
445 ApiResourceManager
<UsbDeviceResource
>* manager
=
446 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
447 manager
->Remove(extension_id(), handle
.handle
);
450 UsbTransferFunction::UsbTransferFunction() {
453 UsbTransferFunction::~UsbTransferFunction() {
456 void UsbTransferFunction::OnCompleted(UsbTransferStatus status
,
457 scoped_refptr
<net::IOBuffer
> data
,
459 scoped_ptr
<base::DictionaryValue
> transfer_info(new base::DictionaryValue());
460 transfer_info
->SetInteger(kResultCodeKey
, status
);
461 transfer_info
->Set(kDataKey
, base::BinaryValue::CreateWithCopiedBuffer(
462 data
->data(), length
));
464 if (status
== device::USB_TRANSFER_COMPLETED
) {
465 Respond(OneArgument(transfer_info
.Pass()));
467 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
468 error_args
->Append(transfer_info
.Pass());
469 // Returning arguments with an error is wrong but we're stuck with it.
470 Respond(ErrorWithArguments(error_args
.Pass(),
471 ConvertTransferStatusToApi(status
)));
475 UsbFindDevicesFunction::UsbFindDevicesFunction() {
478 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
481 ExtensionFunction::ResponseAction
UsbFindDevicesFunction::Run() {
482 scoped_ptr
<extensions::api::usb::FindDevices::Params
> parameters
=
483 FindDevices::Params::Create(*args_
);
484 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
486 vendor_id_
= parameters
->options
.vendor_id
;
487 product_id_
= parameters
->options
.product_id
;
488 int interface_id
= parameters
->options
.interface_id
.get()
489 ? *parameters
->options
.interface_id
.get()
490 : UsbDevicePermissionData::ANY_INTERFACE
;
491 UsbDevicePermission::CheckParam
param(vendor_id_
, product_id_
, interface_id
);
492 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
493 APIPermission::kUsbDevice
, ¶m
)) {
494 return RespondNow(Error(kErrorPermissionDenied
));
497 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
499 return RespondNow(Error(kErrorInitService
));
503 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete
, this));
504 return RespondLater();
507 void UsbFindDevicesFunction::OnGetDevicesComplete(
508 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
509 result_
.reset(new base::ListValue());
510 barrier_
= base::BarrierClosure(
511 devices
.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete
, this));
513 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
514 if (device
->vendor_id() != vendor_id_
||
515 device
->product_id() != product_id_
) {
518 device
->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened
, this));
523 void UsbFindDevicesFunction::OnDeviceOpened(
524 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
525 if (device_handle
.get()) {
526 ApiResourceManager
<UsbDeviceResource
>* manager
=
527 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
528 UsbDeviceResource
* resource
=
529 new UsbDeviceResource(extension_id(), device_handle
);
530 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
531 result_
->Append(PopulateConnectionHandle(
532 manager
->Add(resource
), device
->vendor_id(), device
->product_id()));
537 void UsbFindDevicesFunction::OpenComplete() {
538 Respond(OneArgument(result_
.Pass()));
541 UsbGetDevicesFunction::UsbGetDevicesFunction() {
544 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
547 ExtensionFunction::ResponseAction
UsbGetDevicesFunction::Run() {
548 scoped_ptr
<extensions::api::usb::GetDevices::Params
> parameters
=
549 GetDevices::Params::Create(*args_
);
550 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
552 if (parameters
->options
.filters
) {
553 filters_
.resize(parameters
->options
.filters
->size());
554 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
555 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
559 if (parameters
->options
.vendor_id
) {
560 filters_
.resize(filters_
.size() + 1);
561 filters_
.back().SetVendorId(*parameters
->options
.vendor_id
);
562 if (parameters
->options
.product_id
) {
563 filters_
.back().SetProductId(*parameters
->options
.product_id
);
567 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
569 return RespondNow(Error(kErrorInitService
));
573 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete
, this));
574 return RespondLater();
577 void UsbGetDevicesFunction::OnGetDevicesComplete(
578 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
579 scoped_ptr
<base::ListValue
> result(new base::ListValue());
580 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
581 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
582 if ((filters_
.empty() || UsbDeviceFilter::MatchesAny(device
, filters_
)) &&
583 HasDevicePermission(device
)) {
585 guid_map
->GetApiDevice(device
, &api_device
);
586 result
->Append(api_device
.ToValue());
590 Respond(OneArgument(result
.Pass()));
593 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
596 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
599 ExtensionFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
600 scoped_ptr
<extensions::api::usb::GetUserSelectedDevices::Params
> parameters
=
601 GetUserSelectedDevices::Params::Create(*args_
);
602 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
604 if (!user_gesture()) {
605 return RespondNow(OneArgument(new base::ListValue()));
608 bool multiple
= false;
609 if (parameters
->options
.multiple
) {
610 multiple
= *parameters
->options
.multiple
;
613 std::vector
<UsbDeviceFilter
> filters
;
614 if (parameters
->options
.filters
) {
615 filters
.resize(parameters
->options
.filters
->size());
616 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
617 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
622 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
623 GetAssociatedWebContents());
625 return RespondNow(Error(kErrorNotSupported
));
628 prompt_
->AskForUsbDevices(
629 extension(), browser_context(), multiple
, filters
,
630 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen
, this));
631 return RespondLater();
634 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
635 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
636 scoped_ptr
<base::ListValue
> result(new base::ListValue());
637 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
638 for (const auto& device
: devices
) {
640 guid_map
->GetApiDevice(device
, &api_device
);
641 result
->Append(api_device
.ToValue());
644 Respond(OneArgument(result
.Pass()));
647 UsbRequestAccessFunction::UsbRequestAccessFunction() {
650 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
653 ExtensionFunction::ResponseAction
UsbRequestAccessFunction::Run() {
654 scoped_ptr
<extensions::api::usb::RequestAccess::Params
> parameters
=
655 RequestAccess::Params::Create(*args_
);
656 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
657 return RespondNow(OneArgument(new base::FundamentalValue(true)));
660 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
663 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
666 ExtensionFunction::ResponseAction
UsbOpenDeviceFunction::Run() {
667 scoped_ptr
<extensions::api::usb::OpenDevice::Params
> parameters
=
668 OpenDevice::Params::Create(*args_
);
669 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
671 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
673 return RespondNow(Error(kErrorInitService
));
677 if (!UsbGuidMap::Get(browser_context())
678 ->GetGuidFromId(parameters
->device
.device
, &guid
)) {
679 return RespondNow(Error(kErrorNoDevice
));
682 scoped_refptr
<UsbDevice
> device
= service
->GetDevice(guid
);
684 return RespondNow(Error(kErrorNoDevice
));
687 if (!HasDevicePermission(device
)) {
688 // This function must act as if there is no such device. Otherwise it can be
689 // used to fingerprint unauthorized devices.
690 return RespondNow(Error(kErrorNoDevice
));
693 device
->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened
, this));
694 return RespondLater();
697 void UsbOpenDeviceFunction::OnDeviceOpened(
698 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
699 if (!device_handle
.get()) {
700 Respond(Error(kErrorOpen
));
704 RecordDeviceLastUsed();
706 ApiResourceManager
<UsbDeviceResource
>* manager
=
707 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
708 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
709 Respond(OneArgument(PopulateConnectionHandle(
710 manager
->Add(new UsbDeviceResource(extension_id(), device_handle
)),
711 device
->vendor_id(), device
->product_id())));
714 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
717 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
720 ExtensionFunction::ResponseAction
UsbSetConfigurationFunction::Run() {
721 scoped_ptr
<extensions::api::usb::SetConfiguration::Params
> parameters
=
722 SetConfiguration::Params::Create(*args_
);
723 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
725 scoped_refptr
<UsbDeviceHandle
> device_handle
=
726 GetDeviceHandle(parameters
->handle
);
727 if (!device_handle
.get()) {
728 return RespondNow(Error(kErrorNoConnection
));
731 device_handle
->SetConfiguration(
732 parameters
->configuration_value
,
733 base::Bind(&UsbSetConfigurationFunction::OnComplete
, this));
734 return RespondLater();
737 void UsbSetConfigurationFunction::OnComplete(bool success
) {
739 Respond(NoArguments());
741 Respond(Error(kErrorCannotSetConfiguration
));
745 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
748 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
751 ExtensionFunction::ResponseAction
UsbGetConfigurationFunction::Run() {
752 scoped_ptr
<extensions::api::usb::GetConfiguration::Params
> parameters
=
753 GetConfiguration::Params::Create(*args_
);
754 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
756 scoped_refptr
<UsbDeviceHandle
> device_handle
=
757 GetDeviceHandle(parameters
->handle
);
758 if (!device_handle
.get()) {
759 return RespondNow(Error(kErrorNoConnection
));
762 const UsbConfigDescriptor
* config_descriptor
=
763 device_handle
->GetDevice()->GetActiveConfiguration();
764 if (config_descriptor
) {
765 ConfigDescriptor config
;
766 ConvertConfigDescriptor(*config_descriptor
, &config
);
767 return RespondNow(OneArgument(config
.ToValue()));
769 return RespondNow(Error(kErrorNotConfigured
));
773 UsbListInterfacesFunction::UsbListInterfacesFunction() {
776 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
779 ExtensionFunction::ResponseAction
UsbListInterfacesFunction::Run() {
780 scoped_ptr
<extensions::api::usb::ListInterfaces::Params
> parameters
=
781 ListInterfaces::Params::Create(*args_
);
782 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
784 scoped_refptr
<UsbDeviceHandle
> device_handle
=
785 GetDeviceHandle(parameters
->handle
);
786 if (!device_handle
.get()) {
787 return RespondNow(Error(kErrorNoConnection
));
790 const UsbConfigDescriptor
* config_descriptor
=
791 device_handle
->GetDevice()->GetActiveConfiguration();
792 if (config_descriptor
) {
793 ConfigDescriptor config
;
794 ConvertConfigDescriptor(*config_descriptor
, &config
);
796 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
797 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
798 result
->Append(config
.interfaces
[i
]->ToValue());
801 return RespondNow(OneArgument(result
.Pass()));
803 return RespondNow(Error(kErrorNotConfigured
));
807 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
810 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
813 ExtensionFunction::ResponseAction
UsbCloseDeviceFunction::Run() {
814 scoped_ptr
<extensions::api::usb::CloseDevice::Params
> parameters
=
815 CloseDevice::Params::Create(*args_
);
816 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
818 scoped_refptr
<UsbDeviceHandle
> device_handle
=
819 GetDeviceHandle(parameters
->handle
);
820 if (!device_handle
.get()) {
821 return RespondNow(Error(kErrorNoConnection
));
824 // The device handle is closed when the resource is destroyed.
825 ReleaseDeviceHandle(parameters
->handle
);
826 return RespondNow(NoArguments());
829 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
832 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
835 ExtensionFunction::ResponseAction
UsbClaimInterfaceFunction::Run() {
836 scoped_ptr
<extensions::api::usb::ClaimInterface::Params
> parameters
=
837 ClaimInterface::Params::Create(*args_
);
838 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
840 scoped_refptr
<UsbDeviceHandle
> device_handle
=
841 GetDeviceHandle(parameters
->handle
);
842 if (!device_handle
.get()) {
843 return RespondNow(Error(kErrorNoConnection
));
846 device_handle
->ClaimInterface(
847 parameters
->interface_number
,
848 base::Bind(&UsbClaimInterfaceFunction::OnComplete
, this));
849 return RespondLater();
852 void UsbClaimInterfaceFunction::OnComplete(bool success
) {
854 Respond(NoArguments());
856 Respond(Error(kErrorCannotClaimInterface
));
860 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
863 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
866 ExtensionFunction::ResponseAction
UsbReleaseInterfaceFunction::Run() {
867 scoped_ptr
<extensions::api::usb::ReleaseInterface::Params
> parameters
=
868 ReleaseInterface::Params::Create(*args_
);
869 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
871 scoped_refptr
<UsbDeviceHandle
> device_handle
=
872 GetDeviceHandle(parameters
->handle
);
873 if (!device_handle
.get()) {
874 return RespondNow(Error(kErrorNoConnection
));
877 if (device_handle
->ReleaseInterface(parameters
->interface_number
)) {
878 return RespondNow(NoArguments());
880 return RespondNow(Error(kErrorCannotReleaseInterface
));
884 UsbSetInterfaceAlternateSettingFunction::
885 UsbSetInterfaceAlternateSettingFunction() {
888 UsbSetInterfaceAlternateSettingFunction::
889 ~UsbSetInterfaceAlternateSettingFunction() {
892 ExtensionFunction::ResponseAction
893 UsbSetInterfaceAlternateSettingFunction::Run() {
894 scoped_ptr
<extensions::api::usb::SetInterfaceAlternateSetting::Params
>
895 parameters
= SetInterfaceAlternateSetting::Params::Create(*args_
);
896 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
898 scoped_refptr
<UsbDeviceHandle
> device_handle
=
899 GetDeviceHandle(parameters
->handle
);
900 if (!device_handle
.get()) {
901 return RespondNow(Error(kErrorNoConnection
));
904 device_handle
->SetInterfaceAlternateSetting(
905 parameters
->interface_number
, parameters
->alternate_setting
,
906 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete
, this));
907 return RespondLater();
910 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success
) {
912 Respond(NoArguments());
914 Respond(Error(kErrorCannotSetInterfaceAlternateSetting
));
918 UsbControlTransferFunction::UsbControlTransferFunction() {
921 UsbControlTransferFunction::~UsbControlTransferFunction() {
924 ExtensionFunction::ResponseAction
UsbControlTransferFunction::Run() {
925 scoped_ptr
<extensions::api::usb::ControlTransfer::Params
> parameters
=
926 ControlTransfer::Params::Create(*args_
);
927 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
929 scoped_refptr
<UsbDeviceHandle
> device_handle
=
930 GetDeviceHandle(parameters
->handle
);
931 if (!device_handle
.get()) {
932 return RespondNow(Error(kErrorNoConnection
));
935 const ControlTransferInfo
& transfer
= parameters
->transfer_info
;
936 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
937 UsbDeviceHandle::TransferRequestType request_type
;
938 UsbDeviceHandle::TransferRecipient recipient
;
941 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
942 return RespondNow(Error(kErrorConvertDirection
));
945 if (!ConvertRequestTypeFromApi(transfer
.request_type
, &request_type
)) {
946 return RespondNow(Error(kErrorConvertRequestType
));
949 if (!ConvertRecipientFromApi(transfer
.recipient
, &recipient
)) {
950 return RespondNow(Error(kErrorConvertRecipient
));
953 if (!GetTransferSize(transfer
, &size
)) {
954 return RespondNow(Error(kErrorInvalidTransferLength
));
957 scoped_refptr
<net::IOBuffer
> buffer
=
958 CreateBufferForTransfer(transfer
, direction
, size
);
960 return RespondNow(Error(kErrorMalformedParameters
));
963 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
965 return RespondNow(Error(kErrorInvalidTimeout
));
968 device_handle
->ControlTransfer(
969 direction
, request_type
, recipient
, transfer
.request
, transfer
.value
,
970 transfer
.index
, buffer
.get(), size
, timeout
,
971 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
972 return RespondLater();
975 UsbBulkTransferFunction::UsbBulkTransferFunction() {
978 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
981 ExtensionFunction::ResponseAction
UsbBulkTransferFunction::Run() {
982 scoped_ptr
<extensions::api::usb::BulkTransfer::Params
> parameters
=
983 BulkTransfer::Params::Create(*args_
);
984 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
986 scoped_refptr
<UsbDeviceHandle
> device_handle
=
987 GetDeviceHandle(parameters
->handle
);
988 if (!device_handle
.get()) {
989 return RespondNow(Error(kErrorNoConnection
));
992 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
993 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
996 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
997 return RespondNow(Error(kErrorConvertDirection
));
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
->GenericTransfer(
1016 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1017 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1018 return RespondLater();
1021 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1024 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1027 ExtensionFunction::ResponseAction
UsbInterruptTransferFunction::Run() {
1028 scoped_ptr
<extensions::api::usb::InterruptTransfer::Params
> parameters
=
1029 InterruptTransfer::Params::Create(*args_
);
1030 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1032 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1033 GetDeviceHandle(parameters
->handle
);
1034 if (!device_handle
.get()) {
1035 return RespondNow(Error(kErrorNoConnection
));
1038 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1039 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1042 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1043 return RespondNow(Error(kErrorConvertDirection
));
1046 if (!GetTransferSize(transfer
, &size
)) {
1047 return RespondNow(Error(kErrorInvalidTransferLength
));
1050 scoped_refptr
<net::IOBuffer
> buffer
=
1051 CreateBufferForTransfer(transfer
, direction
, size
);
1052 if (!buffer
.get()) {
1053 return RespondNow(Error(kErrorMalformedParameters
));
1056 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1058 return RespondNow(Error(kErrorInvalidTimeout
));
1061 device_handle
->GenericTransfer(
1062 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1063 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1064 return RespondLater();
1067 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1070 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1073 ExtensionFunction::ResponseAction
UsbIsochronousTransferFunction::Run() {
1074 scoped_ptr
<extensions::api::usb::IsochronousTransfer::Params
> parameters
=
1075 IsochronousTransfer::Params::Create(*args_
);
1076 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1078 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1079 GetDeviceHandle(parameters
->handle
);
1080 if (!device_handle
.get()) {
1081 return RespondNow(Error(kErrorNoConnection
));
1084 const IsochronousTransferInfo
& transfer
= parameters
->transfer_info
;
1085 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1087 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1089 if (!ConvertDirectionFromApi(generic_transfer
.direction
, &direction
)) {
1090 return RespondNow(Error(kErrorConvertDirection
));
1093 if (!GetTransferSize(generic_transfer
, &size
)) {
1094 return RespondNow(Error(kErrorInvalidTransferLength
));
1097 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1098 return RespondNow(Error(kErrorInvalidNumberOfPackets
));
1101 unsigned int packets
= transfer
.packets
;
1102 if (transfer
.packet_length
< 0 ||
1103 transfer
.packet_length
>= kMaxPacketLength
) {
1104 return RespondNow(Error(kErrorInvalidPacketLength
));
1107 unsigned int packet_length
= transfer
.packet_length
;
1108 const uint64 total_length
= packets
* packet_length
;
1109 if (packets
> size
|| total_length
> size
) {
1110 return RespondNow(Error(kErrorTransferLength
));
1113 scoped_refptr
<net::IOBuffer
> buffer
=
1114 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1115 if (!buffer
.get()) {
1116 return RespondNow(Error(kErrorMalformedParameters
));
1119 int timeout
= generic_transfer
.timeout
? *generic_transfer
.timeout
: 0;
1121 return RespondNow(Error(kErrorInvalidTimeout
));
1124 device_handle
->IsochronousTransfer(
1125 direction
, generic_transfer
.endpoint
, buffer
.get(), size
, packets
,
1126 packet_length
, timeout
,
1127 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1128 return RespondLater();
1131 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1134 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1137 ExtensionFunction::ResponseAction
UsbResetDeviceFunction::Run() {
1138 parameters_
= ResetDevice::Params::Create(*args_
);
1139 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1141 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1142 GetDeviceHandle(parameters_
->handle
);
1143 if (!device_handle
.get()) {
1144 return RespondNow(Error(kErrorNoConnection
));
1147 device_handle
->ResetDevice(
1148 base::Bind(&UsbResetDeviceFunction::OnComplete
, this));
1149 return RespondLater();
1152 void UsbResetDeviceFunction::OnComplete(bool success
) {
1154 Respond(OneArgument(new base::FundamentalValue(true)));
1156 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1157 GetDeviceHandle(parameters_
->handle
);
1158 if (device_handle
.get()) {
1159 device_handle
->Close();
1161 ReleaseDeviceHandle(parameters_
->handle
);
1163 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
1164 error_args
->AppendBoolean(false);
1165 // Returning arguments with an error is wrong but we're stuck with it.
1166 Respond(ErrorWithArguments(error_args
.Pass(), kErrorResetDevice
));
1170 } // namespace extensions