Commit 7c403e06 authored by reillyg's avatar reillyg Committed by Commit bot

Add more generic filters to the chrome.usb.getDevices API.

Instead of specifying each of the USB vendor and product ID pairs an
app has permission to open this API extension allows filtering of
devices by vendor and product IDs as well as USB interface classes, sub-
classes and protocols. The 'vendorId' and 'productId' properties of
EnumerateDevicesOptions are still supported for backwards compatibility.

BUG=

Review URL: https://codereview.chromium.org/517923002

Cr-Commit-Position: refs/heads/master@{#293032}
parent 95aa6b1a
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "base/values.h" #include "base/values.h"
#include "components/usb_service/usb_device.h" #include "components/usb_service/usb_device.h"
#include "components/usb_service/usb_device_handle.h"
#include "components/usb_service/usb_interface.h" #include "components/usb_service/usb_interface.h"
namespace usb_service { namespace usb_service {
...@@ -57,7 +56,7 @@ void UsbDeviceFilter::SetInterfaceProtocol(uint8 interface_protocol) { ...@@ -57,7 +56,7 @@ void UsbDeviceFilter::SetInterfaceProtocol(uint8 interface_protocol) {
interface_protocol_ = interface_protocol; interface_protocol_ = interface_protocol;
} }
bool UsbDeviceFilter::Matches(scoped_refptr<UsbDevice> device) { bool UsbDeviceFilter::Matches(scoped_refptr<UsbDevice> device) const {
if (vendor_id_set_) { if (vendor_id_set_) {
if (device->vendor_id() != vendor_id_) { if (device->vendor_id() != vendor_id_) {
return false; return false;
...@@ -125,4 +124,17 @@ base::Value* UsbDeviceFilter::ToValue() const { ...@@ -125,4 +124,17 @@ base::Value* UsbDeviceFilter::ToValue() const {
return obj.release(); return obj.release();
} }
// static
bool UsbDeviceFilter::MatchesAny(scoped_refptr<UsbDevice> device,
const std::vector<UsbDeviceFilter>& filters) {
for (std::vector<UsbDeviceFilter>::const_iterator i = filters.begin();
i != filters.end();
++i) {
if (i->Matches(device)) {
return true;
}
}
return false;
}
} // namespace usb_service } // namespace usb_service
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef COMPONENTS_USB_SERVICE_USB_DEVICE_FILTER_H_ #ifndef COMPONENTS_USB_SERVICE_USB_DEVICE_FILTER_H_
#define COMPONENTS_USB_SERVICE_USB_DEVICE_FILTER_H_ #define COMPONENTS_USB_SERVICE_USB_DEVICE_FILTER_H_
#include <vector>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "components/usb_service/usb_service_export.h" #include "components/usb_service/usb_service_export.h"
...@@ -27,9 +29,12 @@ class USB_SERVICE_EXPORT UsbDeviceFilter { ...@@ -27,9 +29,12 @@ class USB_SERVICE_EXPORT UsbDeviceFilter {
void SetInterfaceSubclass(uint8 interface_subclass); void SetInterfaceSubclass(uint8 interface_subclass);
void SetInterfaceProtocol(uint8 interface_protocol); void SetInterfaceProtocol(uint8 interface_protocol);
bool Matches(scoped_refptr<UsbDevice> device); bool Matches(scoped_refptr<UsbDevice> device) const;
base::Value* ToValue() const; base::Value* ToValue() const;
static bool MatchesAny(scoped_refptr<UsbDevice> device,
const std::vector<UsbDeviceFilter>& filters);
private: private:
uint16 vendor_id_; uint16 vendor_id_;
uint16 product_id_; uint16 product_id_;
......
...@@ -237,3 +237,20 @@ TEST_F(UsbFilterTest, MatchInterfaceProtocolNegative) { ...@@ -237,3 +237,20 @@ TEST_F(UsbFilterTest, MatchInterfaceProtocolNegative) {
filter.SetInterfaceProtocol(0x02); filter.SetInterfaceProtocol(0x02);
ASSERT_FALSE(filter.Matches(android_phone_)); ASSERT_FALSE(filter.Matches(android_phone_));
} }
TEST_F(UsbFilterTest, MatchAnyEmptyListNegative) {
std::vector<UsbDeviceFilter> filters;
ASSERT_FALSE(UsbDeviceFilter::MatchesAny(android_phone_, filters));
}
TEST_F(UsbFilterTest, MatchesAnyVendorId) {
std::vector<UsbDeviceFilter> filters(1);
filters.back().SetVendorId(0x18d1);
ASSERT_TRUE(UsbDeviceFilter::MatchesAny(android_phone_, filters));
}
TEST_F(UsbFilterTest, MatchesAnyVendorIdNegative) {
std::vector<UsbDeviceFilter> filters(1);
filters.back().SetVendorId(0x1d6b);
ASSERT_FALSE(UsbDeviceFilter::MatchesAny(android_phone_, filters));
}
...@@ -52,6 +52,7 @@ using usb::TransferType; ...@@ -52,6 +52,7 @@ using usb::TransferType;
using usb::UsageType; using usb::UsageType;
using usb_service::UsbConfigDescriptor; using usb_service::UsbConfigDescriptor;
using usb_service::UsbDevice; using usb_service::UsbDevice;
using usb_service::UsbDeviceFilter;
using usb_service::UsbDeviceHandle; using usb_service::UsbDeviceHandle;
using usb_service::UsbEndpointDescriptor; using usb_service::UsbEndpointDescriptor;
using usb_service::UsbEndpointDirection; using usb_service::UsbEndpointDirection;
...@@ -417,35 +418,51 @@ bool UsbAsyncApiFunction::Respond() { ...@@ -417,35 +418,51 @@ bool UsbAsyncApiFunction::Respond() {
return error_.empty(); return error_.empty();
} }
scoped_refptr<UsbDevice> UsbAsyncApiFunction::GetDeviceOrOrCompleteWithError( // static
const Device& input_device) { void UsbAsyncApiFunction::CreateDeviceFilter(const usb::DeviceFilter& input,
const uint16_t vendor_id = input_device.vendor_id; UsbDeviceFilter* output) {
const uint16_t product_id = input_device.product_id; if (input.vendor_id) {
UsbDevicePermission::CheckParam param( output->SetVendorId(*input.vendor_id);
vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE); }
if (!extension()->permissions_data()->CheckAPIPermissionWithParam( if (input.product_id) {
APIPermission::kUsbDevice, &param)) { output->SetProductId(*input.product_id);
LOG(WARNING) << "Insufficient permissions to access device."; }
CompleteWithError(kErrorPermissionDenied); if (input.interface_class) {
return NULL; output->SetInterfaceClass(*input.interface_class);
} }
if (input.interface_subclass) {
output->SetInterfaceSubclass(*input.interface_subclass);
}
if (input.interface_protocol) {
output->SetInterfaceProtocol(*input.interface_protocol);
}
}
bool UsbAsyncApiFunction::HasDevicePermission(
scoped_refptr<usb_service::UsbDevice> device) {
UsbDevicePermission::CheckParam param(
device->vendor_id(),
device->product_id(),
UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
return extension()->permissions_data()->CheckAPIPermissionWithParam(
APIPermission::kUsbDevice, &param);
}
scoped_refptr<UsbDevice> UsbAsyncApiFunction::GetDeviceOrCompleteWithError(
const Device& input_device) {
UsbService* service = device::DeviceClient::Get()->GetUsbService(); UsbService* service = device::DeviceClient::Get()->GetUsbService();
if (!service) { if (!service) {
CompleteWithError(kErrorInitService); CompleteWithError(kErrorInitService);
return NULL; return NULL;
} }
scoped_refptr<UsbDevice> device;
device = service->GetDeviceById(input_device.device);
scoped_refptr<UsbDevice> device = service->GetDeviceById(input_device.device);
if (!device.get()) { if (!device.get()) {
CompleteWithError(kErrorNoDevice); CompleteWithError(kErrorNoDevice);
return NULL; return NULL;
} }
if (device->vendor_id() != input_device.vendor_id || if (!HasDevicePermission(device)) {
device->product_id() != input_device.product_id) {
// Must act as if there is no such a device. // Must act as if there is no such a device.
// Otherwise can be used to finger print unauthorized devices. // Otherwise can be used to finger print unauthorized devices.
CompleteWithError(kErrorNoDevice); CompleteWithError(kErrorNoDevice);
...@@ -624,17 +641,20 @@ bool UsbGetDevicesFunction::Prepare() { ...@@ -624,17 +641,20 @@ bool UsbGetDevicesFunction::Prepare() {
} }
void UsbGetDevicesFunction::AsyncWorkStart() { void UsbGetDevicesFunction::AsyncWorkStart() {
scoped_ptr<base::ListValue> result(new base::ListValue()); std::vector<UsbDeviceFilter> filters;
if (parameters_->options.filters) {
const uint16_t vendor_id = parameters_->options.vendor_id; filters.resize(parameters_->options.filters->size());
const uint16_t product_id = parameters_->options.product_id; for (size_t i = 0; i < parameters_->options.filters->size(); ++i) {
UsbDevicePermission::CheckParam param( CreateDeviceFilter(*parameters_->options.filters->at(i).get(),
vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE); &filters[i]);
if (!extension()->permissions_data()->CheckAPIPermissionWithParam( }
APIPermission::kUsbDevice, &param)) { }
LOG(WARNING) << "Insufficient permissions to access device."; if (parameters_->options.vendor_id) {
CompleteWithError(kErrorPermissionDenied); filters.resize(filters.size() + 1);
return; filters.back().SetVendorId(*parameters_->options.vendor_id);
if (parameters_->options.product_id) {
filters.back().SetProductId(*parameters_->options.product_id);
}
} }
UsbService* service = device::DeviceClient::Get()->GetUsbService(); UsbService* service = device::DeviceClient::Get()->GetUsbService();
...@@ -646,18 +666,15 @@ void UsbGetDevicesFunction::AsyncWorkStart() { ...@@ -646,18 +666,15 @@ void UsbGetDevicesFunction::AsyncWorkStart() {
DeviceVector devices; DeviceVector devices;
service->GetDevices(&devices); service->GetDevices(&devices);
for (DeviceVector::iterator it = devices.begin(); it != devices.end();) { scoped_ptr<base::ListValue> result(new base::ListValue());
if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) { for (DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) {
it = devices.erase(it); scoped_refptr<UsbDevice> device = *it;
} else { if ((filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) &&
++it; HasDevicePermission(device)) {
result->Append(PopulateDevice(it->get()));
} }
} }
for (size_t i = 0; i < devices.size(); ++i) {
result->Append(PopulateDevice(devices[i].get()));
}
SetResult(result.release()); SetResult(result.release());
AsyncWorkCompleted(); AsyncWorkCompleted();
} }
...@@ -677,7 +694,7 @@ bool UsbRequestAccessFunction::Prepare() { ...@@ -677,7 +694,7 @@ bool UsbRequestAccessFunction::Prepare() {
void UsbRequestAccessFunction::AsyncWorkStart() { void UsbRequestAccessFunction::AsyncWorkStart() {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
scoped_refptr<UsbDevice> device = scoped_refptr<UsbDevice> device =
GetDeviceOrOrCompleteWithError(parameters_->device); GetDeviceOrCompleteWithError(parameters_->device);
if (!device) if (!device)
return; return;
...@@ -709,7 +726,7 @@ bool UsbOpenDeviceFunction::Prepare() { ...@@ -709,7 +726,7 @@ bool UsbOpenDeviceFunction::Prepare() {
void UsbOpenDeviceFunction::AsyncWorkStart() { void UsbOpenDeviceFunction::AsyncWorkStart() {
scoped_refptr<UsbDevice> device = scoped_refptr<UsbDevice> device =
GetDeviceOrOrCompleteWithError(parameters_->device); GetDeviceOrCompleteWithError(parameters_->device);
if (!device.get()) if (!device.get())
return; return;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "components/usb_service/usb_device.h" #include "components/usb_service/usb_device.h"
#include "components/usb_service/usb_device_filter.h"
#include "components/usb_service/usb_device_handle.h" #include "components/usb_service/usb_device_handle.h"
#include "extensions/browser/api/api_resource_manager.h" #include "extensions/browser/api/api_resource_manager.h"
#include "extensions/browser/api/async_api_function.h" #include "extensions/browser/api/async_api_function.h"
...@@ -31,7 +32,13 @@ class UsbAsyncApiFunction : public AsyncApiFunction { ...@@ -31,7 +32,13 @@ class UsbAsyncApiFunction : public AsyncApiFunction {
virtual bool PrePrepare() OVERRIDE; virtual bool PrePrepare() OVERRIDE;
virtual bool Respond() OVERRIDE; virtual bool Respond() OVERRIDE;
scoped_refptr<usb_service::UsbDevice> GetDeviceOrOrCompleteWithError( static void CreateDeviceFilter(
const extensions::core_api::usb::DeviceFilter& input,
usb_service::UsbDeviceFilter* output);
bool HasDevicePermission(scoped_refptr<usb_service::UsbDevice> device);
scoped_refptr<usb_service::UsbDevice> GetDeviceOrCompleteWithError(
const extensions::core_api::usb::Device& input_device); const extensions::core_api::usb::Device& input_device);
scoped_refptr<usb_service::UsbDeviceHandle> scoped_refptr<usb_service::UsbDeviceHandle>
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "device/usb/usb_ids.h" #include "device/usb/usb_ids.h"
#include "extensions/common/api/usb_private.h" #include "extensions/common/api/usb_private.h"
namespace usb = extensions::core_api::usb;
namespace usb_private = extensions::core_api::usb_private; namespace usb_private = extensions::core_api::usb_private;
namespace GetDevices = usb_private::GetDevices; namespace GetDevices = usb_private::GetDevices;
namespace GetDeviceInfo = usb_private::GetDeviceInfo; namespace GetDeviceInfo = usb_private::GetDeviceInfo;
...@@ -26,6 +27,8 @@ using usb_service::UsbDeviceFilter; ...@@ -26,6 +27,8 @@ using usb_service::UsbDeviceFilter;
using usb_service::UsbDeviceHandle; using usb_service::UsbDeviceHandle;
using usb_service::UsbService; using usb_service::UsbService;
typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
namespace { namespace {
const char kErrorInitService[] = "Failed to initialize USB service."; const char kErrorInitService[] = "Failed to initialize USB service.";
...@@ -58,46 +61,16 @@ void UsbPrivateGetDevicesFunction::AsyncWorkStart() { ...@@ -58,46 +61,16 @@ void UsbPrivateGetDevicesFunction::AsyncWorkStart() {
std::vector<UsbDeviceFilter> filters; std::vector<UsbDeviceFilter> filters;
filters.resize(parameters_->filters.size()); filters.resize(parameters_->filters.size());
for (size_t i = 0; i < parameters_->filters.size(); ++i) { for (size_t i = 0; i < parameters_->filters.size(); ++i) {
UsbDeviceFilter& filter = filters[i]; CreateDeviceFilter(*parameters_->filters[i].get(), &filters[i]);
const usb_private::DeviceFilter* filter_param =
parameters_->filters[i].get();
if (filter_param->vendor_id) {
filter.SetVendorId(*filter_param->vendor_id);
}
if (filter_param->product_id) {
filter.SetProductId(*filter_param->product_id);
}
if (filter_param->interface_class) {
filter.SetInterfaceClass(*filter_param->interface_class);
}
if (filter_param->interface_subclass) {
filter.SetInterfaceSubclass(*filter_param->interface_subclass);
}
if (filter_param->interface_protocol) {
filter.SetInterfaceProtocol(*filter_param->interface_protocol);
}
} }
std::vector<scoped_refptr<UsbDevice> > devices; DeviceVector devices;
service->GetDevices(&devices); service->GetDevices(&devices);
scoped_ptr<base::ListValue> result(new base::ListValue()); scoped_ptr<base::ListValue> result(new base::ListValue());
for (size_t i = 0; i < devices.size(); ++i) { for (DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) {
scoped_refptr<UsbDevice> device = devices[i]; scoped_refptr<UsbDevice> device = *it;
bool matched = false; if (filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) {
if (filters.empty()) {
matched = true;
} else {
for (size_t j = 0; !matched && j < filters.size(); ++j) {
if (filters[j].Matches(device)) {
matched = true;
}
}
}
if (matched) {
result->Append(new base::FundamentalValue((int)device->unique_id())); result->Append(new base::FundamentalValue((int)device->unique_id()));
} }
} }
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
// Use the <code>chrome.usb</code> API to interact with connected USB // Use the <code>chrome.usb</code> API to interact with connected USB
// devices. This API provides access to USB operations from within the context // devices. This API provides access to USB operations from within the context
// of an app. Using this API, apps can function as drivers for hardware devices. // of an app. Using this API, apps can function as drivers for hardware devices.
//
// Errors generated by this API are reported by setting
// $(ref:runtime.lastError) and executing the function's regular callback. The
// callback's regular parameters will be undefined in this case.
namespace usb { namespace usb {
// Direction, Recipient, RequestType, and TransferType all map to their // Direction, Recipient, RequestType, and TransferType all map to their
...@@ -19,110 +23,107 @@ namespace usb { ...@@ -19,110 +23,107 @@ namespace usb {
enum SynchronizationType {asynchronous, adaptive, synchronous}; enum SynchronizationType {asynchronous, adaptive, synchronous};
enum UsageType {data, feedback, explicitFeedback}; enum UsageType {data, feedback, explicitFeedback};
// Returned by |getDevices| to identify a connected USB device.
dictionary Device { dictionary Device {
// The id of the USB device. It remains unchanged until the device is // An opaque ID for the USB device. It remains unchanged until the device is
// unplugged. // unplugged.
long device; long device;
// The device vendor ID.
long vendorId; long vendorId;
// The product ID.
long productId; long productId;
}; };
// Returned by |openDevice| to be used for USB communication.
// Every time a device is opened, a new connection handle is created.
//
// A connection handle represents the underlying data structure that contains
// all the data we need to communicate with a USB device, including the status
// of interfaces, the pending transfers, the descriptors, and etc. A connectin
// handle id is different from a USB device id.
//
// All connection handles can work together if the device allows it.
// The connection handle will be automatically closed when the app is reloaded
// or suspended.
//
// When a connection handle is closed, all the interfaces it claimed will be
// released and all the transfers in progress will be canceled immediately.
dictionary ConnectionHandle { dictionary ConnectionHandle {
// The id of the USB connection handle. // An opaque handle representing this connection to the USB device and all
// associated claimed interfaces and pending transfers. A new handle is
// created each time the device is opened. The connection handle is
// different from $(ref:Device.device).
long handle; long handle;
// The device vendor ID.
long vendorId; long vendorId;
// The product ID.
long productId; long productId;
}; };
dictionary EndpointDescriptor { [noinline_doc] dictionary EndpointDescriptor {
// Endpoint address.
long address; long address;
// Transfer type.
TransferType type; TransferType type;
// Transfer direction.
Direction direction; Direction direction;
// Maximum packet size.
long maximumPacketSize; long maximumPacketSize;
// Transfer synchronization mode (isochronous only).
// Used for isochronous mode.
SynchronizationType? synchronization; SynchronizationType? synchronization;
// Endpoint usage hint.
UsageType? usage; UsageType? usage;
// Polling interval (interrupt and isochronous only).
// If this is an interrupt endpoint, this will be 1-255.
long? pollingInterval; long? pollingInterval;
}; };
dictionary InterfaceDescriptor { [noinline_doc] dictionary InterfaceDescriptor {
// The interface number.
long interfaceNumber; long interfaceNumber;
// The interface alternate setting number (defaults to <code>0</code).
long alternateSetting; long alternateSetting;
// The USB interface class.
long interfaceClass; long interfaceClass;
// The USB interface sub-class.
long interfaceSubclass; long interfaceSubclass;
// The USB interface protocol.
long interfaceProtocol; long interfaceProtocol;
// Description of the interface.
DOMString? description; DOMString? description;
// Available endpoints.
EndpointDescriptor[] endpoints; EndpointDescriptor[] endpoints;
}; };
// ControlTransferInfo represents that parameters to a single USB control
// transfer.
dictionary ControlTransferInfo { dictionary ControlTransferInfo {
// The direction of this transfer. // The transfer direction (<code>"in"</code> or <code>"out"</code>).
Direction direction; Direction direction;
// The intended recipient for this transfer. // The transfer target. The target given by <code>index</code> must be
// claimed if <code>"interface"</code> or <code>"endpoint"</code>.
Recipient recipient; Recipient recipient;
// The type of this request. // The request type.
RequestType requestType; RequestType requestType;
// The <code>bRequest</code> field, see <i>Universal Serial Bus Specification
// Revision 1.1</i> &sect; 9.3.
long request; long request;
// The <code>wValue</code> field, see <i>Ibid</i>.
long value; long value;
// The <code>wIndex</code> field, see <i>Ibid</i>.
long index; long index;
// If this transfer is an input transfer, then this field must be set to // The amount of data to receive (required only by input transfers).
// indicate the expected data length. If this is an output transfer, then
// this field is ignored.
long? length; long? length;
// The data payload carried by this transfer. If this is an output transfer // The data to transmit (required only by output transfers).
// then this field must be set.
ArrayBuffer? data; ArrayBuffer? data;
}; };
// GenericTransferInfo is used by both bulk and interrupt transfers to
// specify the parameters of the transfer.
dictionary GenericTransferInfo { dictionary GenericTransferInfo {
// The direction of this transfer. // The transfer direction (<code>"in"</code> or <code>"out"</code>).
Direction direction; Direction direction;
// The target endpoint address. The interface containing this endpoint must
// be claimed.
long endpoint; long endpoint;
// If this is an input transfer then this field indicates the size of the // The amount of data to receive (required only by input transfers).
// input buffer. If this is an output transfer then this field is ignored.
long? length; long? length;
// If this is an output transfer then this field must be populated. // The data to transmit (required only by output transfers).
// Otherwise, it will be ignored.
ArrayBuffer? data; ArrayBuffer? data;
}; };
// IsochronousTransferInfo describes a single multi-packet isochronous
// transfer.
dictionary IsochronousTransferInfo { dictionary IsochronousTransferInfo {
// All of the normal transfer parameters are encapsulated in the // Transfer parameters. The transfer length or data buffer specified in this
// transferInfo parameters. Note that the data specified in this parameter // parameter block is split along <code>packetLength</code> boundaries to
// block is split along packetLength boundaries to form the individual // form the individual packets of the transfer.
// packets of the transfer.
GenericTransferInfo transferInfo; GenericTransferInfo transferInfo;
// The total number of packets in this transfer. // The total number of packets in this transfer.
...@@ -133,174 +134,177 @@ namespace usb { ...@@ -133,174 +134,177 @@ namespace usb {
}; };
dictionary TransferResultInfo { dictionary TransferResultInfo {
// A value of 0 indicates that the transfer was a success. Other values // A value of <code>0</code> indicates that the transfer was a success.
// indicate failure. // Other values indicate failure.
long? resultCode; long? resultCode;
// If the transfer was an input transfer then this field will contain all // The data returned by an input transfer. <code>undefined</code> for output
// of the input data requested. // transfers.
ArrayBuffer? data; ArrayBuffer? data;
}; };
// Describes the properties of devices which are found via |getDevices|. [noinline_doc] dictionary DeviceFilter {
// Device vendor ID.
long? vendorId;
// Device product ID, checked only if the vendor ID matches.
long? productId;
// USB interface class, matches any interface on the device.
long? interfaceClass;
// USB interface sub-class, checked only if the interface class matches.
long? interfaceSubclass;
// USB interface protocol, checked only if the interface sub-class matches.
long? interfaceProtocol;
};
dictionary EnumerateDevicesOptions { dictionary EnumerateDevicesOptions {
long vendorId; [deprecated="Equivalent to setting $(ref:DeviceFilter.vendorId)."]
long productId; long? vendorId;
[deprecated="Equivalent to setting $(ref:DeviceFilter.productId)."]
long? productId;
// A device matching any given filter will be returned. An empty filter list
// will return all devices the app has permission for.
DeviceFilter[]? filters;
}; };
// Describes the properties of devices which are found via |findDevices|.
dictionary EnumerateDevicesAndRequestAccessOptions { dictionary EnumerateDevicesAndRequestAccessOptions {
// The device vendor ID.
long vendorId; long vendorId;
// The product ID.
long productId; long productId;
// The interface id to request access against. // The interface ID to request access to.
// Only available on ChromeOS. It has no effect on other platforms. // Only available on ChromeOS. It has no effect on other platforms.
long? interfaceId; long? interfaceId;
}; };
callback VoidCallback = void (); callback VoidCallback = void ();
callback GetDevicesCallback = void (Device[] devices); callback GetDevicesCallback = void (Device[] devices);
callback RequestAccessCallback = void (boolean sucess); callback RequestAccessCallback = void (boolean success);
callback OpenDeviceCallback = void (ConnectionHandle handle); callback OpenDeviceCallback = void (ConnectionHandle handle);
callback FindDevicesCallback = void (ConnectionHandle[] handles); callback FindDevicesCallback = void (ConnectionHandle[] handles);
callback ListInterfacesCallback = void (InterfaceDescriptor[] descriptors); callback ListInterfacesCallback = void (InterfaceDescriptor[] descriptors);
callback CloseDeviceCallback = void (); callback CloseDeviceCallback = void ();
callback TransferCallback = void (TransferResultInfo info); callback TransferCallback = void (TransferResultInfo info);
callback ResetDeviceCallback = void(boolean result); callback ResetDeviceCallback = void(boolean success);
interface Functions { interface Functions {
// Lists USB devices specified by vendorId/productId/interfaceId tuple. // Enumerates connected USB devices.
// |options|: The properties to search for on target devices. // |options|: The properties to search for on target devices.
// |callback|: Invoked with a list of |Device|s on complete.
static void getDevices(EnumerateDevicesOptions options, static void getDevices(EnumerateDevicesOptions options,
GetDevicesCallback callback); GetDevicesCallback callback);
// This method is ChromeOS specific. Calling this method on other platforms // Requests access from the permission broker to a device claimed by
// will fail. // ChromeOS if the given interface on the device is not claimed.
// Requests access from the permission broker to an OS claimed device if the //
// given interface on the device is not claimed. // <b>Note:</b> This method is ChromeOS specific. Calling this method on
// other platforms will fail.
// //
// |device|: The device to request access to. // |device|: The $(ref:Device) to request access to.
// |interfaceId|: // |interfaceId|: The particular interface requested.
static void requestAccess(Device device, static void requestAccess(Device device,
long interfaceId, long interfaceId,
RequestAccessCallback callback); RequestAccessCallback callback);
// Opens a USB device returned by |getDevices|. // Opens a USB device returned by $(ref:getDevices).
// |device|: The device to open. // |device|: The $(ref:Device) to open.
// |callback|: Invoked with the created ConnectionHandle on complete.
static void openDevice(Device device, OpenDeviceCallback callback); static void openDevice(Device device, OpenDeviceCallback callback);
// Finds USB devices specified by the vendorId/productId/interfaceId tuple // Finds USB devices specified by the vendor, product and (optionally)
// and, if permissions allow, opens them for use. // interface IDs and if permissions allow opens them for use.
// //
// On Chrome OS, you can specify the interfaceId. In that case the method // On Chrome OS, you can specify the interface ID. In that case the method
// will request access from permission broker in the same way as in // will request access from permission broker in the same way as
// |requestUsbAcess|. // $(ref:requestUsbAccess).
// //
// If the access request is rejected, or the device is failed to be opened, // If the access request is rejected or the device fails to be opened a
// its connection handle will not be created or returned. // connection handle will not be created or returned.
// //
// Calling this method is equivalent to calling |getDevices| followed by // Calling this method is equivalent to calling $(ref:getDevices followed by
// a series of |requestAccess| (if it is on ChromeOs) and |openDevice| // $(ref:requestAccess) (if it is on ChromeOS) and $(ref:openDevice) for
// calls, and returning all the successfully opened connection handles. // each device.
// //
// |options|: The properties to search for on target devices. // |options|: The properties to search for on target devices.
// |callback|: Invoked with the opened ConnectionHandle on complete.
static void findDevices(EnumerateDevicesAndRequestAccessOptions options, static void findDevices(EnumerateDevicesAndRequestAccessOptions options,
FindDevicesCallback callback); FindDevicesCallback callback);
// Closes a connection handle. Invoking operations on a device after it // Closes a connection handle. Invoking operations on a handle after it
// has been closed is a safe operation, but causes no action to be taken. // has been closed is a safe operation but causes no action to be taken.
// |handle|: The connection handle to close. // |handle|: The $(ref:ConnectionHandle) to close.
// |callback|: The callback to invoke once the device is closed.
static void closeDevice(ConnectionHandle handle, static void closeDevice(ConnectionHandle handle,
optional CloseDeviceCallback callback); optional CloseDeviceCallback callback);
// Lists all the interfaces on the USB device. // Lists all interfaces on a USB device.
// |handle|: The device from which the interfaces should be listed. // |handle|: An open connection to the device.
// |callback|: The callback to invoke when the interfaces are enumerated.
static void listInterfaces(ConnectionHandle handle, static void listInterfaces(ConnectionHandle handle,
ListInterfacesCallback callback); ListInterfacesCallback callback);
// Claims an interface on the specified USB device. // Claims an interface on a USB device.
// Before you can transfer data with endpoints, you must claim their parent // Before data can be transfered to an interface or associated endpoints the
// interfaces. Only one connection handle on the same host can claim each // interface must be claimed. Only one connection handle can claim an
// interface. If the interface is already claimed, this call will fail. // interface at any given time. If the interface is already claimed, this
// call will fail.
// //
// You shall call releaseInterface when the interface is not needed anymore. // $(ref:releaseInterface) should be called when the interface is no longer
// needed.
// //
// |handle|: The device on which the interface is to be claimed. // |handle|: An open connection to the device.
// |interface|: The interface number to be claimed. // |interfaceNumber|: The interface to be claimed.
// |callback|: The callback to invoke once the interface is claimed.
static void claimInterface(ConnectionHandle handle, long interfaceNumber, static void claimInterface(ConnectionHandle handle, long interfaceNumber,
VoidCallback callback); VoidCallback callback);
// Releases a claim to an interface on the provided device. // Releases a claimed interface.
// |handle|: The device on which the interface is to be released. // |handle|: An open connection to the device.
// |interface|: The interface number to be released. // |interfaceNumber|: The interface to be released.
// |callback|: The callback to invoke once the interface is released.
static void releaseInterface(ConnectionHandle handle, long interfaceNumber, static void releaseInterface(ConnectionHandle handle, long interfaceNumber,
VoidCallback callback); VoidCallback callback);
// Selects an alternate setting on a previously claimed interface on a // Selects an alternate setting on a previously claimed interface.
// device. // |handle|: An open connection to the device where this interface has been
// |handle|: The device on which the interface settings are to be set. // claimed.
// |interface|: The interface number to be set. // |interfaceNumber|: The interface to configure.
// |alternateSetting|: The alternate setting to set. // |alternateSetting|: The alternate setting to configure.
// |callback|: The callback to invoke once the interface setting is set.
static void setInterfaceAlternateSetting(ConnectionHandle handle, static void setInterfaceAlternateSetting(ConnectionHandle handle,
long interfaceNumber, long interfaceNumber,
long alternateSetting, long alternateSetting,
VoidCallback callback); VoidCallback callback);
// Performs a control transfer on the specified device. See the // Performs a control transfer on the specified device.
// ControlTransferInfo structure for the parameters required to make a
// transfer.
// //
// Conceptually control transfer talks to the device itself. You do not need // Control transfers refer to either the device, an interface or an
// to claim interface 0 to perform a control transfer. // endpoint. Transfers to an interface or endpoint require the interface to
// be claimed.
// //
// |handle|: A connection handle to make the transfer on. // |handle|: An open connection to the device.
// |transferInfo|: The parameters to the transfer. See ControlTransferInfo.
// |callback|: Invoked once the transfer has completed.
static void controlTransfer(ConnectionHandle handle, static void controlTransfer(ConnectionHandle handle,
ControlTransferInfo transferInfo, ControlTransferInfo transferInfo,
TransferCallback callback); TransferCallback callback);
// Performs a bulk transfer on the specified device. // Performs a bulk transfer on the specified device.
// |handle|: A connection handle to make the transfer on. // |handle|: An open connection to the device.
// |transferInfo|: The parameters to the transfer. See GenericTransferInfo. // |transferInfo|: The transfer parameters.
// |callback|: Invoked once the transfer has completed.
static void bulkTransfer(ConnectionHandle handle, static void bulkTransfer(ConnectionHandle handle,
GenericTransferInfo transferInfo, GenericTransferInfo transferInfo,
TransferCallback callback); TransferCallback callback);
// Performs an interrupt transfer on the specified device. // Performs an interrupt transfer on the specified device.
// |handle|: A connection handle to make the transfer on. // |handle|: An open connection to the device.
// |transferInfo|: The parameters to the transfer. See GenericTransferInfo. // |transferInfo|: The transfer parameters.
// |callback|: Invoked once the transfer has completed.
static void interruptTransfer(ConnectionHandle handle, static void interruptTransfer(ConnectionHandle handle,
GenericTransferInfo transferInfo, GenericTransferInfo transferInfo,
TransferCallback callback); TransferCallback callback);
// Performs an isochronous transfer on the specific device. // Performs an isochronous transfer on the specific device.
// |handle|: A connection handle to make the transfer on. // |handle|: An open connection to the device.
// |transferInfo|: The parameters to the transfer. See
// IsochronousTransferInfo.
// |callback|: Invoked once the transfer has been completed.
static void isochronousTransfer(ConnectionHandle handle, static void isochronousTransfer(ConnectionHandle handle,
IsochronousTransferInfo transferInfo, IsochronousTransferInfo transferInfo,
TransferCallback callback); TransferCallback callback);
// Tries to reset the USB device and restores it to the previous status. // Tries to reset the USB device.
// If the reset fails, the given connection handle will be closed and the // If the reset fails, the given connection handle will be closed and the
// USB device will appear to be disconnected then reconnected. // USB device will appear to be disconnected then reconnected.
// In that case you must call |getDevices| or |findDevices| again to acquire // In this case $(ref:getDevices) or $(ref:findDevices) must be called again
// the device. // to acquire the device.
// //
// |handle|: A connection handle to reset. // |handle|: A connection handle to reset.
// |callback|: Invoked once the device is reset with a boolean indicating
// whether the reset is completed successfully.
static void resetDevice(ConnectionHandle handle, static void resetDevice(ConnectionHandle handle,
ResetDeviceCallback callback); ResetDeviceCallback callback);
}; };
......
...@@ -7,22 +7,6 @@ ...@@ -7,22 +7,6 @@
// API which should only be available to trusted pages. // API which should only be available to trusted pages.
namespace usbPrivate { namespace usbPrivate {
// Properties for matching devices. A device matches of any of its interfaces
// match the given properties. An empty dictionary matches any device.
dictionary DeviceFilter {
// Device-level matching criteria:
long? vendorId;
// Checked only if the vendorId matches.
long? productId;
// Per-interface matching criteria:
long? interfaceClass;
// Checked only if the interfaceClass matches.
long? interfaceSubclass;
// Checked only if the interfaceSubclass matches.
long? interfaceProtocol;
};
dictionary DeviceInfo { dictionary DeviceInfo {
long vendorId; // idVendor from the device long vendorId; // idVendor from the device
long productId; // idProduct from the device long productId; // idProduct from the device
...@@ -44,7 +28,7 @@ namespace usbPrivate { ...@@ -44,7 +28,7 @@ namespace usbPrivate {
// Lists USB devices matching any of the given filters. // Lists USB devices matching any of the given filters.
// |filters|: The properties to search for on target devices. // |filters|: The properties to search for on target devices.
// |callback|: Invoked with a list of device IDs on complete. // |callback|: Invoked with a list of device IDs on complete.
static void getDevices(DeviceFilter[] filters, static void getDevices(usb.DeviceFilter[] filters,
GetDevicesCallback callback); GetDevicesCallback callback);
// Gets basic display information about a device. // Gets basic display information about a device.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment