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::core_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 base::Value
* PopulateDevice(const UsbDevice
* device
, int id
) {
260 result
.vendor_id
= device
->vendor_id();
261 result
.product_id
= device
->product_id();
262 return result
.ToValue().release();
265 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
267 case device::USB_TRANSFER_CONTROL
:
268 return usb::TRANSFER_TYPE_CONTROL
;
269 case device::USB_TRANSFER_INTERRUPT
:
270 return usb::TRANSFER_TYPE_INTERRUPT
;
271 case device::USB_TRANSFER_ISOCHRONOUS
:
272 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
273 case device::USB_TRANSFER_BULK
:
274 return usb::TRANSFER_TYPE_BULK
;
277 return usb::TRANSFER_TYPE_NONE
;
281 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
283 case device::USB_DIRECTION_INBOUND
:
284 return usb::DIRECTION_IN
;
285 case device::USB_DIRECTION_OUTBOUND
:
286 return usb::DIRECTION_OUT
;
289 return usb::DIRECTION_NONE
;
293 SynchronizationType
ConvertSynchronizationTypeToApi(
294 const UsbSynchronizationType
& input
) {
296 case device::USB_SYNCHRONIZATION_NONE
:
297 return usb::SYNCHRONIZATION_TYPE_NONE
;
298 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
299 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
300 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
301 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
302 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
303 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
306 return usb::SYNCHRONIZATION_TYPE_NONE
;
310 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
312 case device::USB_USAGE_DATA
:
313 return usb::USAGE_TYPE_DATA
;
314 case device::USB_USAGE_FEEDBACK
:
315 return usb::USAGE_TYPE_FEEDBACK
;
316 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
317 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
320 return usb::USAGE_TYPE_NONE
;
324 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
325 EndpointDescriptor
* output
) {
326 output
->address
= input
.address
;
327 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
328 output
->direction
= ConvertDirectionToApi(input
.direction
);
329 output
->maximum_packet_size
= input
.maximum_packet_size
;
330 output
->synchronization
=
331 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
332 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
333 output
->polling_interval
.reset(new int(input
.polling_interval
));
334 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
337 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
338 InterfaceDescriptor
* output
) {
339 output
->interface_number
= input
.interface_number
;
340 output
->alternate_setting
= input
.alternate_setting
;
341 output
->interface_class
= input
.interface_class
;
342 output
->interface_subclass
= input
.interface_subclass
;
343 output
->interface_protocol
= input
.interface_protocol
;
344 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
345 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
346 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
347 output
->endpoints
.push_back(endpoint
);
349 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
352 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
353 ConfigDescriptor
* output
) {
354 output
->configuration_value
= input
.configuration_value
;
355 output
->self_powered
= input
.self_powered
;
356 output
->remote_wakeup
= input
.remote_wakeup
;
357 output
->max_power
= input
.maximum_power
;
358 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
359 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
360 ConvertInterfaceDescriptor(input_interface
, interface
.get());
361 output
->interfaces
.push_back(interface
);
363 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
366 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
367 UsbDeviceFilter
* output
) {
368 if (input
.vendor_id
) {
369 output
->SetVendorId(*input
.vendor_id
);
371 if (input
.product_id
) {
372 output
->SetProductId(*input
.product_id
);
374 if (input
.interface_class
) {
375 output
->SetInterfaceClass(*input
.interface_class
);
377 if (input
.interface_subclass
) {
378 output
->SetInterfaceSubclass(*input
.interface_subclass
);
380 if (input
.interface_protocol
) {
381 output
->SetInterfaceProtocol(*input
.interface_protocol
);
387 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
388 : device_permissions_manager_(nullptr) {
391 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
394 bool UsbPermissionCheckingFunction::HasDevicePermission(
395 scoped_refptr
<UsbDevice
> device
) {
396 if (!device_permissions_manager_
) {
397 device_permissions_manager_
=
398 DevicePermissionsManager::Get(browser_context());
401 DevicePermissions
* device_permissions
=
402 device_permissions_manager_
->GetForExtension(extension_id());
403 DCHECK(device_permissions
);
405 permission_entry_
= device_permissions
->FindUsbDeviceEntry(device
);
406 if (permission_entry_
.get()) {
410 UsbDevicePermission::CheckParam
param(
412 device
->product_id(),
413 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
414 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
415 APIPermission::kUsbDevice
, ¶m
)) {
422 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
423 if (permission_entry_
.get()) {
424 device_permissions_manager_
->UpdateLastUsed(extension_id(),
429 UsbConnectionFunction::UsbConnectionFunction() {
432 UsbConnectionFunction::~UsbConnectionFunction() {
435 scoped_refptr
<device::UsbDeviceHandle
> UsbConnectionFunction::GetDeviceHandle(
436 const extensions::core_api::usb::ConnectionHandle
& handle
) {
437 ApiResourceManager
<UsbDeviceResource
>* manager
=
438 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
443 UsbDeviceResource
* resource
= manager
->Get(extension_id(), handle
.handle
);
448 return resource
->device();
451 void UsbConnectionFunction::ReleaseDeviceHandle(
452 const extensions::core_api::usb::ConnectionHandle
& handle
) {
453 ApiResourceManager
<UsbDeviceResource
>* manager
=
454 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
455 manager
->Remove(extension_id(), handle
.handle
);
458 UsbTransferFunction::UsbTransferFunction() {
461 UsbTransferFunction::~UsbTransferFunction() {
464 void UsbTransferFunction::OnCompleted(UsbTransferStatus status
,
465 scoped_refptr
<net::IOBuffer
> data
,
467 scoped_ptr
<base::DictionaryValue
> transfer_info(new base::DictionaryValue());
468 transfer_info
->SetInteger(kResultCodeKey
, status
);
469 transfer_info
->Set(kDataKey
, base::BinaryValue::CreateWithCopiedBuffer(
470 data
->data(), length
));
472 if (status
== device::USB_TRANSFER_COMPLETED
) {
473 Respond(OneArgument(transfer_info
.release()));
475 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
476 error_args
->Append(transfer_info
.release());
477 // Returning arguments with an error is wrong but we're stuck with it.
478 Respond(ErrorWithArguments(error_args
.Pass(),
479 ConvertTransferStatusToApi(status
)));
483 UsbFindDevicesFunction::UsbFindDevicesFunction() {
486 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
489 ExtensionFunction::ResponseAction
UsbFindDevicesFunction::Run() {
490 scoped_ptr
<extensions::core_api::usb::FindDevices::Params
> parameters
=
491 FindDevices::Params::Create(*args_
);
492 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
494 vendor_id_
= parameters
->options
.vendor_id
;
495 product_id_
= parameters
->options
.product_id
;
496 int interface_id
= parameters
->options
.interface_id
.get()
497 ? *parameters
->options
.interface_id
.get()
498 : UsbDevicePermissionData::ANY_INTERFACE
;
499 UsbDevicePermission::CheckParam
param(vendor_id_
, product_id_
, interface_id
);
500 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
501 APIPermission::kUsbDevice
, ¶m
)) {
502 return RespondNow(Error(kErrorPermissionDenied
));
505 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
507 return RespondNow(Error(kErrorInitService
));
511 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete
, this));
512 return RespondLater();
515 void UsbFindDevicesFunction::OnGetDevicesComplete(
516 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
517 result_
.reset(new base::ListValue());
518 barrier_
= base::BarrierClosure(
519 devices
.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete
, this));
521 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
522 if (device
->vendor_id() != vendor_id_
||
523 device
->product_id() != product_id_
) {
526 device
->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened
, this));
531 void UsbFindDevicesFunction::OnDeviceOpened(
532 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
533 if (device_handle
.get()) {
534 ApiResourceManager
<UsbDeviceResource
>* manager
=
535 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
536 UsbDeviceResource
* resource
=
537 new UsbDeviceResource(extension_id(), device_handle
);
538 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
539 result_
->Append(PopulateConnectionHandle(
540 manager
->Add(resource
), device
->vendor_id(), device
->product_id()));
545 void UsbFindDevicesFunction::OpenComplete() {
546 Respond(OneArgument(result_
.release()));
549 UsbGetDevicesFunction::UsbGetDevicesFunction() {
552 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
555 ExtensionFunction::ResponseAction
UsbGetDevicesFunction::Run() {
556 scoped_ptr
<extensions::core_api::usb::GetDevices::Params
> parameters
=
557 GetDevices::Params::Create(*args_
);
558 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
560 if (parameters
->options
.filters
) {
561 filters_
.resize(parameters
->options
.filters
->size());
562 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
563 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
567 if (parameters
->options
.vendor_id
) {
568 filters_
.resize(filters_
.size() + 1);
569 filters_
.back().SetVendorId(*parameters
->options
.vendor_id
);
570 if (parameters
->options
.product_id
) {
571 filters_
.back().SetProductId(*parameters
->options
.product_id
);
575 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
577 return RespondNow(Error(kErrorInitService
));
581 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete
, this));
582 return RespondLater();
585 void UsbGetDevicesFunction::OnGetDevicesComplete(
586 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
587 scoped_ptr
<base::ListValue
> result(new base::ListValue());
588 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
589 for (const scoped_refptr
<UsbDevice
>& device
: devices
) {
590 if ((filters_
.empty() || UsbDeviceFilter::MatchesAny(device
, filters_
)) &&
591 HasDevicePermission(device
)) {
592 result
->Append(PopulateDevice(device
.get(),
593 guid_map
->GetIdFromGuid(device
->guid())));
597 Respond(OneArgument(result
.release()));
600 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
603 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
606 ExtensionFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
607 scoped_ptr
<extensions::core_api::usb::GetUserSelectedDevices::Params
>
608 parameters
= GetUserSelectedDevices::Params::Create(*args_
);
609 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
611 if (!user_gesture()) {
612 return RespondNow(OneArgument(new base::ListValue()));
615 bool multiple
= false;
616 if (parameters
->options
.multiple
) {
617 multiple
= *parameters
->options
.multiple
;
620 std::vector
<UsbDeviceFilter
> filters
;
621 if (parameters
->options
.filters
) {
622 filters
.resize(parameters
->options
.filters
->size());
623 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
624 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
629 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
630 GetAssociatedWebContents());
632 return RespondNow(Error(kErrorNotSupported
));
635 prompt_
->AskForUsbDevices(
636 extension(), browser_context(), multiple
, filters
,
637 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen
, this));
638 return RespondLater();
641 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
642 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
643 scoped_ptr
<base::ListValue
> result(new base::ListValue());
644 UsbGuidMap
* guid_map
= UsbGuidMap::Get(browser_context());
645 for (const auto& device
: devices
) {
647 PopulateDevice(device
.get(), guid_map
->GetIdFromGuid(device
->guid())));
650 Respond(OneArgument(result
.release()));
653 UsbRequestAccessFunction::UsbRequestAccessFunction() {
656 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
659 ExtensionFunction::ResponseAction
UsbRequestAccessFunction::Run() {
660 scoped_ptr
<extensions::core_api::usb::RequestAccess::Params
> parameters
=
661 RequestAccess::Params::Create(*args_
);
662 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
663 return RespondNow(OneArgument(new base::FundamentalValue(true)));
666 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
669 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
672 ExtensionFunction::ResponseAction
UsbOpenDeviceFunction::Run() {
673 scoped_ptr
<extensions::core_api::usb::OpenDevice::Params
> parameters
=
674 OpenDevice::Params::Create(*args_
);
675 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
677 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
679 return RespondNow(Error(kErrorInitService
));
683 if (!UsbGuidMap::Get(browser_context())
684 ->GetGuidFromId(parameters
->device
.device
, &guid
)) {
685 return RespondNow(Error(kErrorNoDevice
));
688 scoped_refptr
<UsbDevice
> device
= service
->GetDevice(guid
);
690 return RespondNow(Error(kErrorNoDevice
));
693 if (!HasDevicePermission(device
)) {
694 // This function must act as if there is no such device. Otherwise it can be
695 // used to fingerprint unauthorized devices.
696 return RespondNow(Error(kErrorNoDevice
));
699 device
->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened
, this));
700 return RespondLater();
703 void UsbOpenDeviceFunction::OnDeviceOpened(
704 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
705 if (!device_handle
.get()) {
706 Respond(Error(kErrorOpen
));
710 RecordDeviceLastUsed();
712 ApiResourceManager
<UsbDeviceResource
>* manager
=
713 ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
714 scoped_refptr
<UsbDevice
> device
= device_handle
->GetDevice();
715 Respond(OneArgument(PopulateConnectionHandle(
716 manager
->Add(new UsbDeviceResource(extension_id(), device_handle
)),
717 device
->vendor_id(), device
->product_id())));
720 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
723 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
726 ExtensionFunction::ResponseAction
UsbSetConfigurationFunction::Run() {
727 scoped_ptr
<extensions::core_api::usb::SetConfiguration::Params
> parameters
=
728 SetConfiguration::Params::Create(*args_
);
729 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
731 scoped_refptr
<UsbDeviceHandle
> device_handle
=
732 GetDeviceHandle(parameters
->handle
);
733 if (!device_handle
.get()) {
734 return RespondNow(Error(kErrorNoConnection
));
737 device_handle
->SetConfiguration(
738 parameters
->configuration_value
,
739 base::Bind(&UsbSetConfigurationFunction::OnComplete
, this));
740 return RespondLater();
743 void UsbSetConfigurationFunction::OnComplete(bool success
) {
745 Respond(NoArguments());
747 Respond(Error(kErrorCannotSetConfiguration
));
751 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
754 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
757 ExtensionFunction::ResponseAction
UsbGetConfigurationFunction::Run() {
758 scoped_ptr
<extensions::core_api::usb::GetConfiguration::Params
> parameters
=
759 GetConfiguration::Params::Create(*args_
);
760 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
762 scoped_refptr
<UsbDeviceHandle
> device_handle
=
763 GetDeviceHandle(parameters
->handle
);
764 if (!device_handle
.get()) {
765 return RespondNow(Error(kErrorNoConnection
));
768 const UsbConfigDescriptor
* config_descriptor
=
769 device_handle
->GetDevice()->GetConfiguration();
770 if (config_descriptor
) {
771 ConfigDescriptor config
;
772 ConvertConfigDescriptor(*config_descriptor
, &config
);
773 return RespondNow(OneArgument(config
.ToValue().release()));
775 return RespondNow(Error(kErrorNotConfigured
));
779 UsbListInterfacesFunction::UsbListInterfacesFunction() {
782 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
785 ExtensionFunction::ResponseAction
UsbListInterfacesFunction::Run() {
786 scoped_ptr
<extensions::core_api::usb::ListInterfaces::Params
> parameters
=
787 ListInterfaces::Params::Create(*args_
);
788 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
790 scoped_refptr
<UsbDeviceHandle
> device_handle
=
791 GetDeviceHandle(parameters
->handle
);
792 if (!device_handle
.get()) {
793 return RespondNow(Error(kErrorNoConnection
));
796 const UsbConfigDescriptor
* config_descriptor
=
797 device_handle
->GetDevice()->GetConfiguration();
798 if (config_descriptor
) {
799 ConfigDescriptor config
;
800 ConvertConfigDescriptor(*config_descriptor
, &config
);
802 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
803 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
804 result
->Append(config
.interfaces
[i
]->ToValue().release());
807 return RespondNow(OneArgument(result
.release()));
809 return RespondNow(Error(kErrorNotConfigured
));
813 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
816 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
819 ExtensionFunction::ResponseAction
UsbCloseDeviceFunction::Run() {
820 scoped_ptr
<extensions::core_api::usb::CloseDevice::Params
> parameters
=
821 CloseDevice::Params::Create(*args_
);
822 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
824 scoped_refptr
<UsbDeviceHandle
> device_handle
=
825 GetDeviceHandle(parameters
->handle
);
826 if (!device_handle
.get()) {
827 return RespondNow(Error(kErrorNoConnection
));
830 // The device handle is closed when the resource is destroyed.
831 ReleaseDeviceHandle(parameters
->handle
);
832 return RespondNow(NoArguments());
835 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
838 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
841 ExtensionFunction::ResponseAction
UsbClaimInterfaceFunction::Run() {
842 scoped_ptr
<extensions::core_api::usb::ClaimInterface::Params
> parameters
=
843 ClaimInterface::Params::Create(*args_
);
844 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
846 scoped_refptr
<UsbDeviceHandle
> device_handle
=
847 GetDeviceHandle(parameters
->handle
);
848 if (!device_handle
.get()) {
849 return RespondNow(Error(kErrorNoConnection
));
852 device_handle
->ClaimInterface(
853 parameters
->interface_number
,
854 base::Bind(&UsbClaimInterfaceFunction::OnComplete
, this));
855 return RespondLater();
858 void UsbClaimInterfaceFunction::OnComplete(bool success
) {
860 Respond(NoArguments());
862 Respond(Error(kErrorCannotClaimInterface
));
866 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
869 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
872 ExtensionFunction::ResponseAction
UsbReleaseInterfaceFunction::Run() {
873 scoped_ptr
<extensions::core_api::usb::ReleaseInterface::Params
> parameters
=
874 ReleaseInterface::Params::Create(*args_
);
875 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
877 scoped_refptr
<UsbDeviceHandle
> device_handle
=
878 GetDeviceHandle(parameters
->handle
);
879 if (!device_handle
.get()) {
880 return RespondNow(Error(kErrorNoConnection
));
883 if (device_handle
->ReleaseInterface(parameters
->interface_number
)) {
884 return RespondNow(NoArguments());
886 return RespondNow(Error(kErrorCannotReleaseInterface
));
890 UsbSetInterfaceAlternateSettingFunction::
891 UsbSetInterfaceAlternateSettingFunction() {
894 UsbSetInterfaceAlternateSettingFunction::
895 ~UsbSetInterfaceAlternateSettingFunction() {
898 ExtensionFunction::ResponseAction
899 UsbSetInterfaceAlternateSettingFunction::Run() {
900 scoped_ptr
<extensions::core_api::usb::SetInterfaceAlternateSetting::Params
>
901 parameters
= SetInterfaceAlternateSetting::Params::Create(*args_
);
902 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
904 scoped_refptr
<UsbDeviceHandle
> device_handle
=
905 GetDeviceHandle(parameters
->handle
);
906 if (!device_handle
.get()) {
907 return RespondNow(Error(kErrorNoConnection
));
910 device_handle
->SetInterfaceAlternateSetting(
911 parameters
->interface_number
, parameters
->alternate_setting
,
912 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete
, this));
913 return RespondLater();
916 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success
) {
918 Respond(NoArguments());
920 Respond(Error(kErrorCannotSetInterfaceAlternateSetting
));
924 UsbControlTransferFunction::UsbControlTransferFunction() {
927 UsbControlTransferFunction::~UsbControlTransferFunction() {
930 ExtensionFunction::ResponseAction
UsbControlTransferFunction::Run() {
931 scoped_ptr
<extensions::core_api::usb::ControlTransfer::Params
> parameters
=
932 ControlTransfer::Params::Create(*args_
);
933 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
935 scoped_refptr
<UsbDeviceHandle
> device_handle
=
936 GetDeviceHandle(parameters
->handle
);
937 if (!device_handle
.get()) {
938 return RespondNow(Error(kErrorNoConnection
));
941 const ControlTransferInfo
& transfer
= parameters
->transfer_info
;
942 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
943 UsbDeviceHandle::TransferRequestType request_type
;
944 UsbDeviceHandle::TransferRecipient recipient
;
947 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
948 return RespondNow(Error(kErrorConvertDirection
));
951 if (!ConvertRequestTypeFromApi(transfer
.request_type
, &request_type
)) {
952 return RespondNow(Error(kErrorConvertRequestType
));
955 if (!ConvertRecipientFromApi(transfer
.recipient
, &recipient
)) {
956 return RespondNow(Error(kErrorConvertRecipient
));
959 if (!GetTransferSize(transfer
, &size
)) {
960 return RespondNow(Error(kErrorInvalidTransferLength
));
963 scoped_refptr
<net::IOBuffer
> buffer
=
964 CreateBufferForTransfer(transfer
, direction
, size
);
966 return RespondNow(Error(kErrorMalformedParameters
));
969 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
971 return RespondNow(Error(kErrorInvalidTimeout
));
974 device_handle
->ControlTransfer(
975 direction
, request_type
, recipient
, transfer
.request
, transfer
.value
,
976 transfer
.index
, buffer
.get(), size
, timeout
,
977 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
978 return RespondLater();
981 UsbBulkTransferFunction::UsbBulkTransferFunction() {
984 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
987 ExtensionFunction::ResponseAction
UsbBulkTransferFunction::Run() {
988 scoped_ptr
<extensions::core_api::usb::BulkTransfer::Params
> parameters
=
989 BulkTransfer::Params::Create(*args_
);
990 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
992 scoped_refptr
<UsbDeviceHandle
> device_handle
=
993 GetDeviceHandle(parameters
->handle
);
994 if (!device_handle
.get()) {
995 return RespondNow(Error(kErrorNoConnection
));
998 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
999 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1002 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1003 return RespondNow(Error(kErrorConvertDirection
));
1006 if (!GetTransferSize(transfer
, &size
)) {
1007 return RespondNow(Error(kErrorInvalidTransferLength
));
1010 scoped_refptr
<net::IOBuffer
> buffer
=
1011 CreateBufferForTransfer(transfer
, direction
, size
);
1012 if (!buffer
.get()) {
1013 return RespondNow(Error(kErrorMalformedParameters
));
1016 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1018 return RespondNow(Error(kErrorInvalidTimeout
));
1021 device_handle
->BulkTransfer(
1022 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1023 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1024 return RespondLater();
1027 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1030 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1033 ExtensionFunction::ResponseAction
UsbInterruptTransferFunction::Run() {
1034 scoped_ptr
<extensions::core_api::usb::InterruptTransfer::Params
> parameters
=
1035 InterruptTransfer::Params::Create(*args_
);
1036 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1038 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1039 GetDeviceHandle(parameters
->handle
);
1040 if (!device_handle
.get()) {
1041 return RespondNow(Error(kErrorNoConnection
));
1044 const GenericTransferInfo
& transfer
= parameters
->transfer_info
;
1045 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1048 if (!ConvertDirectionFromApi(transfer
.direction
, &direction
)) {
1049 return RespondNow(Error(kErrorConvertDirection
));
1052 if (!GetTransferSize(transfer
, &size
)) {
1053 return RespondNow(Error(kErrorInvalidTransferLength
));
1056 scoped_refptr
<net::IOBuffer
> buffer
=
1057 CreateBufferForTransfer(transfer
, direction
, size
);
1058 if (!buffer
.get()) {
1059 return RespondNow(Error(kErrorMalformedParameters
));
1062 int timeout
= transfer
.timeout
? *transfer
.timeout
: 0;
1064 return RespondNow(Error(kErrorInvalidTimeout
));
1067 device_handle
->InterruptTransfer(
1068 direction
, transfer
.endpoint
, buffer
.get(), size
, timeout
,
1069 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1070 return RespondLater();
1073 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1076 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1079 ExtensionFunction::ResponseAction
UsbIsochronousTransferFunction::Run() {
1080 scoped_ptr
<extensions::core_api::usb::IsochronousTransfer::Params
>
1081 parameters
= IsochronousTransfer::Params::Create(*args_
);
1082 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
1084 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1085 GetDeviceHandle(parameters
->handle
);
1086 if (!device_handle
.get()) {
1087 return RespondNow(Error(kErrorNoConnection
));
1090 const IsochronousTransferInfo
& transfer
= parameters
->transfer_info
;
1091 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1093 UsbEndpointDirection direction
= device::USB_DIRECTION_INBOUND
;
1095 if (!ConvertDirectionFromApi(generic_transfer
.direction
, &direction
)) {
1096 return RespondNow(Error(kErrorConvertDirection
));
1099 if (!GetTransferSize(generic_transfer
, &size
)) {
1100 return RespondNow(Error(kErrorInvalidTransferLength
));
1103 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1104 return RespondNow(Error(kErrorInvalidNumberOfPackets
));
1107 unsigned int packets
= transfer
.packets
;
1108 if (transfer
.packet_length
< 0 ||
1109 transfer
.packet_length
>= kMaxPacketLength
) {
1110 return RespondNow(Error(kErrorInvalidPacketLength
));
1113 unsigned int packet_length
= transfer
.packet_length
;
1114 const uint64 total_length
= packets
* packet_length
;
1115 if (packets
> size
|| total_length
> size
) {
1116 return RespondNow(Error(kErrorTransferLength
));
1119 scoped_refptr
<net::IOBuffer
> buffer
=
1120 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1121 if (!buffer
.get()) {
1122 return RespondNow(Error(kErrorMalformedParameters
));
1125 int timeout
= generic_transfer
.timeout
? *generic_transfer
.timeout
: 0;
1127 return RespondNow(Error(kErrorInvalidTimeout
));
1130 device_handle
->IsochronousTransfer(
1131 direction
, generic_transfer
.endpoint
, buffer
.get(), size
, packets
,
1132 packet_length
, timeout
,
1133 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1134 return RespondLater();
1137 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1140 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1143 ExtensionFunction::ResponseAction
UsbResetDeviceFunction::Run() {
1144 parameters_
= ResetDevice::Params::Create(*args_
);
1145 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1147 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1148 GetDeviceHandle(parameters_
->handle
);
1149 if (!device_handle
.get()) {
1150 return RespondNow(Error(kErrorNoConnection
));
1153 device_handle
->ResetDevice(
1154 base::Bind(&UsbResetDeviceFunction::OnComplete
, this));
1155 return RespondLater();
1158 void UsbResetDeviceFunction::OnComplete(bool success
) {
1160 Respond(OneArgument(new base::FundamentalValue(true)));
1162 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1163 GetDeviceHandle(parameters_
->handle
);
1164 if (device_handle
.get()) {
1165 device_handle
->Close();
1167 ReleaseDeviceHandle(parameters_
->handle
);
1169 scoped_ptr
<base::ListValue
> error_args(new base::ListValue());
1170 error_args
->AppendBoolean(false);
1171 // Returning arguments with an error is wrong but we're stuck with it.
1172 Respond(ErrorWithArguments(error_args
.Pass(), kErrorResetDevice
));
1176 } // namespace extensions