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_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
;
75 const char kDataKey
[] = "data";
76 const char kResultCodeKey
[] = "resultCode";
78 const char kErrorInitService
[] = "Failed to initialize USB service.";
80 const char kErrorOpen
[] = "Failed to open device.";
81 const char kErrorCancelled
[] = "Transfer was cancelled.";
82 const char kErrorDisconnect
[] = "Device disconnected.";
83 const char kErrorGeneric
[] = "Transfer failed.";
84 const char kErrorNotSupported
[] = "Not supported on this platform.";
85 const char kErrorNotConfigured
[] = "The device is not in a configured state.";
86 const char kErrorOverflow
[] = "Inbound transfer overflow.";
87 const char kErrorStalled
[] = "Transfer stalled.";
88 const char kErrorTimeout
[] = "Transfer timed out.";
89 const char kErrorTransferLength
[] = "Transfer length is insufficient.";
90 const char kErrorCannotSetConfiguration
[] =
91 "Error setting device configuration.";
92 const char kErrorCannotClaimInterface
[] = "Error claiming interface.";
93 const char kErrorCannotReleaseInterface
[] = "Error releasing interface.";
94 const char kErrorCannotSetInterfaceAlternateSetting
[] =
95 "Error setting alternate interface setting.";
96 const char kErrorConvertDirection
[] = "Invalid transfer direction.";
97 const char kErrorConvertRecipient
[] = "Invalid transfer recipient.";
98 const char kErrorConvertRequestType
[] = "Invalid request type.";
99 const char kErrorMalformedParameters
[] = "Error parsing parameters.";
100 const char kErrorNoConnection
[] = "No such connection.";
101 const char kErrorNoDevice
[] = "No such device.";
102 const char kErrorPermissionDenied
[] = "Permission to access device was denied";
103 const char kErrorInvalidTransferLength
[] =
104 "Transfer length must be a positive number less than 104,857,600.";
105 const char kErrorInvalidNumberOfPackets
[] =
106 "Number of packets must be a positive number less than 4,194,304.";
107 const char kErrorInvalidPacketLength
[] =
108 "Packet length must be a positive number less than 65,536.";
109 const char kErrorInvalidTimeout
[] =
110 "Transfer timeout must be greater than or equal to 0.";
111 const char kErrorResetDevice
[] =
112 "Error resetting the device. The device has been closed.";
114 const size_t kMaxTransferLength
= 100 * 1024 * 1024;
115 const int kMaxPackets
= 4 * 1024 * 1024;
116 const int kMaxPacketLength
= 64 * 1024;
118 bool ConvertDirectionFromApi(const Direction
& input
,
119 UsbEndpointDirection
* output
) {
121 case usb::DIRECTION_IN
:
122 *output
= device::USB_DIRECTION_INBOUND
;
124 case usb::DIRECTION_OUT
:
125 *output
= device::USB_DIRECTION_OUTBOUND
;
133 bool ConvertRequestTypeFromApi(const RequestType
& input
,
134 UsbDeviceHandle::TransferRequestType
* output
) {
136 case usb::REQUEST_TYPE_STANDARD
:
137 *output
= UsbDeviceHandle::STANDARD
;
139 case usb::REQUEST_TYPE_CLASS
:
140 *output
= UsbDeviceHandle::CLASS
;
142 case usb::REQUEST_TYPE_VENDOR
:
143 *output
= UsbDeviceHandle::VENDOR
;
145 case usb::REQUEST_TYPE_RESERVED
:
146 *output
= UsbDeviceHandle::RESERVED
;
154 bool ConvertRecipientFromApi(const Recipient
& input
,
155 UsbDeviceHandle::TransferRecipient
* output
) {
157 case usb::RECIPIENT_DEVICE
:
158 *output
= UsbDeviceHandle::DEVICE
;
160 case usb::RECIPIENT_INTERFACE
:
161 *output
= UsbDeviceHandle::INTERFACE
;
163 case usb::RECIPIENT_ENDPOINT
:
164 *output
= UsbDeviceHandle::ENDPOINT
;
166 case usb::RECIPIENT_OTHER
:
167 *output
= UsbDeviceHandle::OTHER
;
176 bool GetTransferSize(const T
& input
, size_t* output
) {
177 if (input
.direction
== usb::DIRECTION_IN
) {
178 const int* length
= input
.length
.get();
179 if (length
&& *length
>= 0 &&
180 static_cast<size_t>(*length
) < kMaxTransferLength
) {
184 } else if (input
.direction
== usb::DIRECTION_OUT
) {
185 if (input
.data
.get()) {
186 *output
= input
.data
->size();
194 scoped_refptr
<net::IOBuffer
> CreateBufferForTransfer(
196 UsbEndpointDirection direction
,
198 if (size
>= kMaxTransferLength
)
201 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
202 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
203 // cannot represent a zero-length buffer, while an URB can.
204 scoped_refptr
<net::IOBuffer
> buffer
=
205 new net::IOBuffer(std::max(static_cast<size_t>(1), size
));
207 if (direction
== device::USB_DIRECTION_INBOUND
) {
209 } else if (direction
== device::USB_DIRECTION_OUTBOUND
) {
210 if (input
.data
.get() && size
<= input
.data
->size()) {
211 memcpy(buffer
->data(), input
.data
->data(), size
);
219 const char* ConvertTransferStatusToApi(const UsbTransferStatus status
) {
221 case device::USB_TRANSFER_COMPLETED
:
223 case device::USB_TRANSFER_ERROR
:
224 return kErrorGeneric
;
225 case device::USB_TRANSFER_TIMEOUT
:
226 return kErrorTimeout
;
227 case device::USB_TRANSFER_CANCELLED
:
228 return kErrorCancelled
;
229 case device::USB_TRANSFER_STALLED
:
230 return kErrorStalled
;
231 case device::USB_TRANSFER_DISCONNECT
:
232 return kErrorDisconnect
;
233 case device::USB_TRANSFER_OVERFLOW
:
234 return kErrorOverflow
;
235 case device::USB_TRANSFER_LENGTH_SHORT
:
236 return kErrorTransferLength
;
243 base::Value
* PopulateConnectionHandle(int handle
,
246 ConnectionHandle result
;
247 result
.handle
= handle
;
248 result
.vendor_id
= vendor_id
;
249 result
.product_id
= product_id
;
250 return result
.ToValue().release();
253 base::Value
* PopulateDevice(const UsbDevice
* device
) {
255 result
.device
= device
->unique_id();
256 result
.vendor_id
= device
->vendor_id();
257 result
.product_id
= device
->product_id();
258 return result
.ToValue().release();
261 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
263 case device::USB_TRANSFER_CONTROL
:
264 return usb::TRANSFER_TYPE_CONTROL
;
265 case device::USB_TRANSFER_INTERRUPT
:
266 return usb::TRANSFER_TYPE_INTERRUPT
;
267 case device::USB_TRANSFER_ISOCHRONOUS
:
268 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
269 case device::USB_TRANSFER_BULK
:
270 return usb::TRANSFER_TYPE_BULK
;
273 return usb::TRANSFER_TYPE_NONE
;
277 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
279 case device::USB_DIRECTION_INBOUND
:
280 return usb::DIRECTION_IN
;
281 case device::USB_DIRECTION_OUTBOUND
:
282 return usb::DIRECTION_OUT
;
285 return usb::DIRECTION_NONE
;
289 SynchronizationType
ConvertSynchronizationTypeToApi(
290 const UsbSynchronizationType
& input
) {
292 case device::USB_SYNCHRONIZATION_NONE
:
293 return usb::SYNCHRONIZATION_TYPE_NONE
;
294 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
295 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
296 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
297 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
298 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
299 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
302 return usb::SYNCHRONIZATION_TYPE_NONE
;
306 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
308 case device::USB_USAGE_DATA
:
309 return usb::USAGE_TYPE_DATA
;
310 case device::USB_USAGE_FEEDBACK
:
311 return usb::USAGE_TYPE_FEEDBACK
;
312 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
313 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
316 return usb::USAGE_TYPE_NONE
;
320 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
321 EndpointDescriptor
* output
) {
322 output
->address
= input
.address
;
323 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
324 output
->direction
= ConvertDirectionToApi(input
.direction
);
325 output
->maximum_packet_size
= input
.maximum_packet_size
;
326 output
->synchronization
=
327 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
328 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
329 output
->polling_interval
.reset(new int(input
.polling_interval
));
330 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
333 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
334 InterfaceDescriptor
* output
) {
335 output
->interface_number
= input
.interface_number
;
336 output
->alternate_setting
= input
.alternate_setting
;
337 output
->interface_class
= input
.interface_class
;
338 output
->interface_subclass
= input
.interface_subclass
;
339 output
->interface_protocol
= input
.interface_protocol
;
340 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
341 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
342 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
343 output
->endpoints
.push_back(endpoint
);
345 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
348 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
349 ConfigDescriptor
* output
) {
350 output
->configuration_value
= input
.configuration_value
;
351 output
->self_powered
= input
.self_powered
;
352 output
->remote_wakeup
= input
.remote_wakeup
;
353 output
->max_power
= input
.maximum_power
;
354 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
355 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
356 ConvertInterfaceDescriptor(input_interface
, interface
.get());
357 output
->interfaces
.push_back(interface
);
359 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
362 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
363 UsbDeviceFilter
* output
) {
364 if (input
.vendor_id
) {
365 output
->SetVendorId(*input
.vendor_id
);
367 if (input
.product_id
) {
368 output
->SetProductId(*input
.product_id
);
370 if (input
.interface_class
) {
371 output
->SetInterfaceClass(*input
.interface_class
);
373 if (input
.interface_subclass
) {
374 output
->SetInterfaceSubclass(*input
.interface_subclass
);
376 if (input
.interface_protocol
) {
377 output
->SetInterfaceProtocol(*input
.interface_protocol
);
383 namespace extensions
{
385 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
386 : device_permissions_manager_(nullptr) {
389 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
392 bool UsbPermissionCheckingFunction::HasDevicePermission(
393 scoped_refptr
<UsbDevice
> device
) {
394 if (!device_permissions_manager_
) {
395 device_permissions_manager_
=
396 DevicePermissionsManager::Get(browser_context());
399 DevicePermissions
* device_permissions
=
400 device_permissions_manager_
->GetForExtension(extension_id());
401 DCHECK(device_permissions
);
403 permission_entry_
= device_permissions
->FindUsbDeviceEntry(device
);
404 if (permission_entry_
.get()) {
408 UsbDevicePermission::CheckParam
param(
410 device
->product_id(),
411 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
412 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
413 APIPermission::kUsbDevice
, ¶m
)) {
420 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
421 if (permission_entry_
.get()) {
422 device_permissions_manager_
->UpdateLastUsed(extension_id(),
427 UsbConnectionFunction::UsbConnectionFunction() {
430 UsbConnectionFunction::~UsbConnectionFunction() {
433 scoped_refptr
<device::UsbDeviceHandle
> UsbConnectionFunction::GetDeviceHandle(
434 const extensions::core_api::usb::ConnectionHandle
& handle
) {
435 ApiResourceManager
<UsbDeviceResource
>* manager
=
436 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
441 UsbDeviceResource
* resource
= manager
->Get(extension_id(), handle
.handle
);
446 return resource
->device();
449 void UsbConnectionFunction::ReleaseDeviceHandle(
450 const extensions::core_api::usb::ConnectionHandle
& handle
) {
451 ApiResourceManager
<UsbDeviceResource
>* manager
=
452 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
453 manager
->Remove(extension_id(), handle
.handle
);
456 UsbTransferFunction::UsbTransferFunction() {
459 UsbTransferFunction::~UsbTransferFunction() {
462 void UsbTransferFunction::OnCompleted(UsbTransferStatus status
,
463 scoped_refptr
<net::IOBuffer
> data
,
465 scoped_ptr
<base::DictionaryValue
> transfer_info(new base::DictionaryValue());
466 transfer_info
->SetInteger(kResultCodeKey
, status
);
467 transfer_info
->Set(kDataKey
, base::BinaryValue::CreateWithCopiedBuffer(
468 data
->data(), length
));
470 if (status
== device::USB_TRANSFER_COMPLETED
) {
471 Respond(OneArgument(transfer_info
.release()));
473 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
474 error_args
->Append(transfer_info
.release());
475 // Returning arguments with an error is wrong but we're stuck with it.
476 Respond(ErrorWithArguments(error_args
.Pass(),
477 ConvertTransferStatusToApi(status
)));
481 UsbFindDevicesFunction::UsbFindDevicesFunction() {
484 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
487 ExtensionFunction::ResponseAction
UsbFindDevicesFunction::Run() {
488 scoped_ptr
<extensions::core_api::usb::FindDevices::Params
> parameters
=
489 FindDevices::Params::Create(*args_
);
490 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
492 vendor_id_
= parameters
->options
.vendor_id
;
493 product_id_
= parameters
->options
.product_id
;
494 interface_id_
= parameters
->options
.interface_id
.get()
495 ? *parameters
->options
.interface_id
.get()
496 : UsbDevicePermissionData::ANY_INTERFACE
;
497 UsbDevicePermission::CheckParam
param(vendor_id_
, product_id_
, interface_id_
);
498 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
499 APIPermission::kUsbDevice
, ¶m
)) {
500 return RespondNow(Error(kErrorPermissionDenied
));
503 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
505 return RespondNow(Error(kErrorInitService
));
509 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete
, this));
510 return RespondLater();
513 void UsbFindDevicesFunction::OnGetDevicesComplete(
514 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
515 result_
.reset(new base::ListValue());
516 barrier_
= base::BarrierClosure(
517 devices
.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete
, this));
519 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
520 if (device
->vendor_id() != vendor_id_
||
521 device
->product_id() != product_id_
) {
524 device
->RequestUsbAccess(
526 base::Bind(&UsbFindDevicesFunction::OnRequestAccessComplete
, this,
532 void UsbFindDevicesFunction::OnRequestAccessComplete(
533 scoped_refptr
<UsbDevice
> device
,
536 device
->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened
, this));
542 void UsbFindDevicesFunction::OnDeviceOpened(
543 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
544 if (device_handle
.get()) {
545 ApiResourceManager
<UsbDeviceResource
>* manager
=
546 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
547 UsbDeviceResource
* resource
=
548 new UsbDeviceResource(extension_id(), device_handle
);
549 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
550 result_
->Append(PopulateConnectionHandle(
551 manager
->Add(resource
), device
->vendor_id(), device
->product_id()));
556 void UsbFindDevicesFunction::OpenComplete() {
557 Respond(OneArgument(result_
.release()));
560 UsbGetDevicesFunction::UsbGetDevicesFunction() {
563 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
566 ExtensionFunction::ResponseAction
UsbGetDevicesFunction::Run() {
567 scoped_ptr
<extensions::core_api::usb::GetDevices::Params
> parameters
=
568 GetDevices::Params::Create(*args_
);
569 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
571 if (parameters
->options
.filters
) {
572 filters_
.resize(parameters
->options
.filters
->size());
573 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
574 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
578 if (parameters
->options
.vendor_id
) {
579 filters_
.resize(filters_
.size() + 1);
580 filters_
.back().SetVendorId(*parameters
->options
.vendor_id
);
581 if (parameters
->options
.product_id
) {
582 filters_
.back().SetProductId(*parameters
->options
.product_id
);
586 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
588 return RespondNow(Error(kErrorInitService
));
592 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete
, this));
593 return RespondLater();
596 void UsbGetDevicesFunction::OnGetDevicesComplete(
597 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
598 scoped_ptr
<base::ListValue
> result(new base::ListValue());
599 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
600 if ((filters_
.empty() || UsbDeviceFilter::MatchesAny(device
, filters_
)) &&
601 HasDevicePermission(device
)) {
602 result
->Append(PopulateDevice(device
.get()));
606 Respond(OneArgument(result
.release()));
609 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
612 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
615 ExtensionFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
616 scoped_ptr
<extensions::core_api::usb::GetUserSelectedDevices::Params
>
617 parameters
= GetUserSelectedDevices::Params::Create(*args_
);
618 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
620 if (!user_gesture()) {
621 return RespondNow(OneArgument(new base::ListValue()));
624 bool multiple
= false;
625 if (parameters
->options
.multiple
) {
626 multiple
= *parameters
->options
.multiple
;
629 std::vector
<UsbDeviceFilter
> filters
;
630 if (parameters
->options
.filters
) {
631 filters
.resize(parameters
->options
.filters
->size());
632 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
633 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
638 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
639 GetAssociatedWebContents());
641 return RespondNow(Error(kErrorNotSupported
));
644 prompt_
->AskForUsbDevices(
645 extension(), browser_context(), multiple
, filters
,
646 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen
, this));
647 return RespondLater();
650 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
651 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
652 scoped_ptr
<base::ListValue
> result(new base::ListValue());
653 for (const auto& device
: devices
) {
654 result
->Append(PopulateDevice(device
.get()));
657 Respond(OneArgument(result
.release()));
660 UsbRequestAccessFunction::UsbRequestAccessFunction() {
663 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
666 ExtensionFunction::ResponseAction
UsbRequestAccessFunction::Run() {
667 scoped_ptr
<extensions::core_api::usb::RequestAccess::Params
> parameters
=
668 RequestAccess::Params::Create(*args_
);
669 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
670 return RespondNow(OneArgument(new base::FundamentalValue(true)));
673 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
676 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
679 ExtensionFunction::ResponseAction
UsbOpenDeviceFunction::Run() {
680 scoped_ptr
<extensions::core_api::usb::OpenDevice::Params
> parameters
=
681 OpenDevice::Params::Create(*args_
);
682 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
684 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
686 return RespondNow(Error(kErrorInitService
));
689 scoped_refptr
<UsbDevice
> device
=
690 service
->GetDeviceById(parameters
->device
.device
);
692 return RespondNow(Error(kErrorNoDevice
));
695 if (!HasDevicePermission(device
)) {
696 // This function must act as if there is no such device. Otherwise it can be
697 // used to fingerprint unauthorized devices.
698 return RespondNow(Error(kErrorNoDevice
));
701 device
->RequestUsbAccess(
702 -1, /* any interface, unused by the permission broker */
703 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete
, this,
705 return RespondLater();
708 void UsbOpenDeviceFunction::OnRequestAccessComplete(
709 scoped_refptr
<UsbDevice
> device
,
712 device
->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened
, this));
714 Respond(Error(kErrorPermissionDenied
));
718 void UsbOpenDeviceFunction::OnDeviceOpened(
719 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
720 if (!device_handle
.get()) {
721 Respond(Error(kErrorOpen
));
725 RecordDeviceLastUsed();
727 ApiResourceManager
<UsbDeviceResource
>* manager
=
728 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
729 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
730 Respond(OneArgument(PopulateConnectionHandle(
731 manager
->Add(new UsbDeviceResource(extension_id(), device_handle
)),
732 device
->vendor_id(), device
->product_id())));
735 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
738 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
741 ExtensionFunction::ResponseAction
UsbSetConfigurationFunction::Run() {
742 scoped_ptr
<extensions::core_api::usb::SetConfiguration::Params
> parameters
=
743 SetConfiguration::Params::Create(*args_
);
744 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
746 scoped_refptr
<UsbDeviceHandle
> device_handle
=
747 GetDeviceHandle(parameters
->handle
);
748 if (!device_handle
.get()) {
749 return RespondNow(Error(kErrorNoConnection
));
752 device_handle
->SetConfiguration(
753 parameters
->configuration_value
,
754 base::Bind(&UsbSetConfigurationFunction::OnComplete
, this));
755 return RespondLater();
758 void UsbSetConfigurationFunction::OnComplete(bool success
) {
760 Respond(NoArguments());
762 Respond(Error(kErrorCannotSetConfiguration
));
766 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
769 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
772 ExtensionFunction::ResponseAction
UsbGetConfigurationFunction::Run() {
773 scoped_ptr
<extensions::core_api::usb::GetConfiguration::Params
> parameters
=
774 GetConfiguration::Params::Create(*args_
);
775 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
777 scoped_refptr
<UsbDeviceHandle
> device_handle
=
778 GetDeviceHandle(parameters
->handle
);
779 if (!device_handle
.get()) {
780 return RespondNow(Error(kErrorNoConnection
));
783 const UsbConfigDescriptor
* config_descriptor
=
784 device_handle
->GetDevice()->GetConfiguration();
785 if (config_descriptor
) {
786 ConfigDescriptor config
;
787 ConvertConfigDescriptor(*config_descriptor
, &config
);
788 return RespondNow(OneArgument(config
.ToValue().release()));
790 return RespondNow(Error(kErrorNotConfigured
));
794 UsbListInterfacesFunction::UsbListInterfacesFunction() {
797 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
800 ExtensionFunction::ResponseAction
UsbListInterfacesFunction::Run() {
801 scoped_ptr
<extensions::core_api::usb::ListInterfaces::Params
> parameters
=
802 ListInterfaces::Params::Create(*args_
);
803 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
805 scoped_refptr
<UsbDeviceHandle
> device_handle
=
806 GetDeviceHandle(parameters
->handle
);
807 if (!device_handle
.get()) {
808 return RespondNow(Error(kErrorNoConnection
));
811 const UsbConfigDescriptor
* config_descriptor
=
812 device_handle
->GetDevice()->GetConfiguration();
813 if (config_descriptor
) {
814 ConfigDescriptor config
;
815 ConvertConfigDescriptor(*config_descriptor
, &config
);
817 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
818 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
819 result
->Append(config
.interfaces
[i
]->ToValue().release());
822 return RespondNow(OneArgument(result
.release()));
824 return RespondNow(Error(kErrorNotConfigured
));
828 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
831 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
834 ExtensionFunction::ResponseAction
UsbCloseDeviceFunction::Run() {
835 scoped_ptr
<extensions::core_api::usb::CloseDevice::Params
> parameters
=
836 CloseDevice::Params::Create(*args_
);
837 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
839 scoped_refptr
<UsbDeviceHandle
> device_handle
=
840 GetDeviceHandle(parameters
->handle
);
841 if (!device_handle
.get()) {
842 return RespondNow(Error(kErrorNoConnection
));
845 // The device handle is closed when the resource is destroyed.
846 ReleaseDeviceHandle(parameters
->handle
);
847 return RespondNow(NoArguments());
850 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
853 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
856 ExtensionFunction::ResponseAction
UsbClaimInterfaceFunction::Run() {
857 scoped_ptr
<extensions::core_api::usb::ClaimInterface::Params
> parameters
=
858 ClaimInterface::Params::Create(*args_
);
859 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
861 scoped_refptr
<UsbDeviceHandle
> device_handle
=
862 GetDeviceHandle(parameters
->handle
);
863 if (!device_handle
.get()) {
864 return RespondNow(Error(kErrorNoConnection
));
867 device_handle
->ClaimInterface(
868 parameters
->interface_number
,
869 base::Bind(&UsbClaimInterfaceFunction::OnComplete
, this));
870 return RespondLater();
873 void UsbClaimInterfaceFunction::OnComplete(bool success
) {
875 Respond(NoArguments());
877 Respond(Error(kErrorCannotClaimInterface
));
881 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
884 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
887 ExtensionFunction::ResponseAction
UsbReleaseInterfaceFunction::Run() {
888 scoped_ptr
<extensions::core_api::usb::ReleaseInterface::Params
> parameters
=
889 ReleaseInterface::Params::Create(*args_
);
890 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
892 scoped_refptr
<UsbDeviceHandle
> device_handle
=
893 GetDeviceHandle(parameters
->handle
);
894 if (!device_handle
.get()) {
895 return RespondNow(Error(kErrorNoConnection
));
898 if (device_handle
->ReleaseInterface(parameters
->interface_number
)) {
899 return RespondNow(NoArguments());
901 return RespondNow(Error(kErrorCannotReleaseInterface
));
905 UsbSetInterfaceAlternateSettingFunction::
906 UsbSetInterfaceAlternateSettingFunction() {
909 UsbSetInterfaceAlternateSettingFunction::
910 ~UsbSetInterfaceAlternateSettingFunction() {
913 ExtensionFunction::ResponseAction
914 UsbSetInterfaceAlternateSettingFunction::Run() {
915 scoped_ptr
<extensions::core_api::usb::SetInterfaceAlternateSetting::Params
>
916 parameters
= SetInterfaceAlternateSetting::Params::Create(*args_
);
917 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
919 scoped_refptr
<UsbDeviceHandle
> device_handle
=
920 GetDeviceHandle(parameters
->handle
);
921 if (!device_handle
.get()) {
922 return RespondNow(Error(kErrorNoConnection
));
925 device_handle
->SetInterfaceAlternateSetting(
926 parameters
->interface_number
, parameters
->alternate_setting
,
927 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete
, this));
928 return RespondLater();
931 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success
) {
933 Respond(NoArguments());
935 Respond(Error(kErrorCannotSetInterfaceAlternateSetting
));
939 UsbControlTransferFunction::UsbControlTransferFunction() {
942 UsbControlTransferFunction::~UsbControlTransferFunction() {
945 ExtensionFunction::ResponseAction
UsbControlTransferFunction::Run() {
946 scoped_ptr
<extensions::core_api::usb::ControlTransfer::Params
> parameters
=
947 ControlTransfer::Params::Create(*args_
);
948 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
950 scoped_refptr
<UsbDeviceHandle
> device_handle
=
951 GetDeviceHandle(parameters
->handle
);
952 if (!device_handle
.get()) {
953 return RespondNow(Error(kErrorNoConnection
));
956 const ControlTransferInfo
& transfer
= parameters
->transfer_info
;
957 UsbEndpointDirection direction
;
958 UsbDeviceHandle::TransferRequestType request_type
;
959 UsbDeviceHandle::TransferRecipient recipient
;
962 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
963 return RespondNow(Error(kErrorConvertDirection
));
966 if (!ConvertRequestTypeFromApi(transfer
.request_type
, &request_type
)) {
967 return RespondNow(Error(kErrorConvertRequestType
));
970 if (!ConvertRecipientFromApi(transfer
.recipient
, &recipient
)) {
971 return RespondNow(Error(kErrorConvertRecipient
));
974 if (!GetTransferSize(transfer
, &size
)) {
975 return RespondNow(Error(kErrorInvalidTransferLength
));
978 scoped_refptr
<net::IOBuffer
> buffer
=
979 CreateBufferForTransfer(transfer
, direction
, size
);
981 return RespondNow(Error(kErrorMalformedParameters
));
984 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
986 return RespondNow(Error(kErrorInvalidTimeout
));
989 device_handle
->ControlTransfer(
990 direction
, request_type
, recipient
, transfer
.request
, transfer
.value
,
991 transfer
.index
, buffer
.get(), size
, timeout
,
992 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
993 return RespondLater();
996 UsbBulkTransferFunction::UsbBulkTransferFunction() {
999 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1002 ExtensionFunction::ResponseAction
UsbBulkTransferFunction::Run() {
1003 scoped_ptr
<extensions::core_api::usb::BulkTransfer::Params
> parameters
=
1004 BulkTransfer::Params::Create(*args_
);
1005 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1007 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1008 GetDeviceHandle(parameters
->handle
);
1009 if (!device_handle
.get()) {
1010 return RespondNow(Error(kErrorNoConnection
));
1013 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1014 UsbEndpointDirection direction
;
1017 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1018 return RespondNow(Error(kErrorConvertDirection
));
1021 if (!GetTransferSize(transfer
, &size
)) {
1022 return RespondNow(Error(kErrorInvalidTransferLength
));
1025 scoped_refptr
<net::IOBuffer
> buffer
=
1026 CreateBufferForTransfer(transfer
, direction
, size
);
1027 if (!buffer
.get()) {
1028 return RespondNow(Error(kErrorMalformedParameters
));
1031 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1033 return RespondNow(Error(kErrorInvalidTimeout
));
1036 device_handle
->BulkTransfer(
1037 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1038 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1039 return RespondLater();
1042 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1045 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1048 ExtensionFunction::ResponseAction
UsbInterruptTransferFunction::Run() {
1049 scoped_ptr
<extensions::core_api::usb::InterruptTransfer::Params
> parameters
=
1050 InterruptTransfer::Params::Create(*args_
);
1051 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1053 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1054 GetDeviceHandle(parameters
->handle
);
1055 if (!device_handle
.get()) {
1056 return RespondNow(Error(kErrorNoConnection
));
1059 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1060 UsbEndpointDirection direction
;
1063 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1064 return RespondNow(Error(kErrorConvertDirection
));
1067 if (!GetTransferSize(transfer
, &size
)) {
1068 return RespondNow(Error(kErrorInvalidTransferLength
));
1071 scoped_refptr
<net::IOBuffer
> buffer
=
1072 CreateBufferForTransfer(transfer
, direction
, size
);
1073 if (!buffer
.get()) {
1074 return RespondNow(Error(kErrorMalformedParameters
));
1077 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1079 return RespondNow(Error(kErrorInvalidTimeout
));
1082 device_handle
->InterruptTransfer(
1083 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1084 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1085 return RespondLater();
1088 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1091 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1094 ExtensionFunction::ResponseAction
UsbIsochronousTransferFunction::Run() {
1095 scoped_ptr
<extensions::core_api::usb::IsochronousTransfer::Params
>
1096 parameters
= IsochronousTransfer::Params::Create(*args_
);
1097 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1099 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1100 GetDeviceHandle(parameters
->handle
);
1101 if (!device_handle
.get()) {
1102 return RespondNow(Error(kErrorNoConnection
));
1105 const IsochronousTransferInfo
& transfer
= parameters
->transfer_info
;
1106 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1108 UsbEndpointDirection direction
;
1110 if (!ConvertDirectionFromApi(generic_transfer
.direction
, &direction
)) {
1111 return RespondNow(Error(kErrorConvertDirection
));
1114 if (!GetTransferSize(generic_transfer
, &size
)) {
1115 return RespondNow(Error(kErrorInvalidTransferLength
));
1118 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1119 return RespondNow(Error(kErrorInvalidNumberOfPackets
));
1122 unsigned int packets
= transfer
.packets
;
1123 if (transfer
.packet_length
< 0 ||
1124 transfer
.packet_length
>= kMaxPacketLength
) {
1125 return RespondNow(Error(kErrorInvalidPacketLength
));
1128 unsigned int packet_length
= transfer
.packet_length
;
1129 const uint64 total_length
= packets
* packet_length
;
1130 if (packets
> size
|| total_length
> size
) {
1131 return RespondNow(Error(kErrorTransferLength
));
1134 scoped_refptr
<net::IOBuffer
> buffer
=
1135 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1136 if (!buffer
.get()) {
1137 return RespondNow(Error(kErrorMalformedParameters
));
1140 int timeout
= generic_transfer
.timeout
? *generic_transfer
.timeout
: 0;
1142 return RespondNow(Error(kErrorInvalidTimeout
));
1145 device_handle
->IsochronousTransfer(
1146 direction
, generic_transfer
.endpoint
, buffer
.get(), size
, packets
,
1147 packet_length
, timeout
,
1148 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1149 return RespondLater();
1152 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1155 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1158 ExtensionFunction::ResponseAction
UsbResetDeviceFunction::Run() {
1159 parameters_
= ResetDevice::Params::Create(*args_
);
1160 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1162 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1163 GetDeviceHandle(parameters_
->handle
);
1164 if (!device_handle
.get()) {
1165 return RespondNow(Error(kErrorNoConnection
));
1168 device_handle
->ResetDevice(
1169 base::Bind(&UsbResetDeviceFunction::OnComplete
, this));
1170 return RespondLater();
1173 void UsbResetDeviceFunction::OnComplete(bool success
) {
1175 Respond(OneArgument(new base::FundamentalValue(true)));
1177 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1178 GetDeviceHandle(parameters_
->handle
);
1179 if (device_handle
.get()) {
1180 device_handle
->Close();
1182 ReleaseDeviceHandle(parameters_
->handle
);
1184 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
1185 error_args
->AppendBoolean(false);
1186 // Returning arguments with an error is wrong but we're stuck with it.
1187 Respond(ErrorWithArguments(error_args
.Pass(), kErrorResetDevice
));
1191 } // namespace extensions