This document describes an API for securely providing access to Universal Serial Bus devices from web pages.

This specification was published by the Web Platform Incubator Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

1. Introduction

This section is non-normative.

The Universal Serial Bus (USB) is the de-facto standard for wired peripherals. Most USB devices implement one of roughly a dozen standard "device classes" which specify a way for the device to advertise the features it supports and commands and data formats for using those features. Standard device classes include keyboard, mice, audio, video and storage devices. Operating systems support such devices using the "class driver" provided by the OS vendor. There is however a long tail of devices that do not fit into one of the standardized device classes. These devices require hardware vendors to write native drivers and SDKs in order for developers to take advantage of them and this native code prevents these devices from being used by the web.

The WebUSB API provides a way to safely expose USB device services to the web. It provides an API familiar to developers who have used existing native USB libraries and exposes the device interfaces defined by existing specifications. With this API hardware manufacturers will have the ability to build cross-platform JavaScript SDKs for their devices. This will be good for the web because, instead of waiting for a new kind of device to be popular enough for browsers to provide a specific API, new and innovative hardware can be built for the web from day one.

For more information about USB see § 9 Appendix: A Brief Introduction to USB.

2. Motivating Applications

This section is non-normative.

2.1. Educational Devices

The software delivery model of the web is a key enabler for educational applications because they can be quickly loaded on any computer without questions of platform compatibility or administrative credentials. Science classes are incorporating computerized measurement and data logging into their lessons. These tools require bundled software that may be difficult to install on managed computers as every new native application adds overhead to an already stressed IT department. Web-based hardware APIs allow support for these devices to be built directly into existing online course materials, providing a completely seamless experience.

Students learning to code with one of the many microcontroller development kits can take advantage of online developer tools to write and upload their code. These tools already exist however they require a native component to interface between the browser and the hardware. These native extensions add a barrier to entry and may expose the user to security vulnerabilities in a way that that code running in the sandboxed web environment does not.

2.2. Web Drivers

The composablity of the web allows a new ecosystem of hardware support to be built entirely from web technology. Taking 3D printers an example, imagine that a site hosting 3D object designs wants to integrate printing directly into their page. The web supports 2D printing but there is no API for the 3D variety. If manufacturers host embeddable pages that use the WebUSB API to send data to their printers, sites can use these pages to integrate support for the hardware in the same way that features such as embedded maps are added to many existing sites.

While wireless protocols such as Bluetooth are often the more convenient choice for consumer devices USB ports continue to proliferate because they are an easy solution for power delivery and can serve as the connection of last resort when the device isn’t working. By integrating update and diagnostic tools into their support site a hardware manufacturer can provide tools for customers on any platform and collect better diagnostic data when a customer reaches out for support through their website. The landing page provides a way for the device manufacturer to direct the user to the right part of their website for help with their device.

3. Security and Privacy Considerations

This section is non-normative.

The WebUSB API is a powerful feature and has the possibility to expose users to a number of new privacy and security risks. These risks can be broadly divided into three categories that will be described in the sections below.

3.1. Abusing Access to a Device

Peripheral devices can serve a number of purposes. They may store data, as a flash drive does. They may collect information about the outside world as a camera or microphone does. They may manipulate objects in the outside world as a printer does. Each of the examples above have high-level APIs in the web platform with security features that aim to prevent their abuse by a malicious website. Storing data to or from an external drive requires the user to select the file manually. Turning on the microphone or camera requires permission from the user and may activate an indicator to let the user know data collection is in progress. Printing a document requires explicit action as well. This API provides a generic mechanism to connect to devices not covered by these existing high-level APIs and so it requires a similarly generic mechanism for preventing a malicious page from abusing a device.

The first of these protections is the requestDevice() function. The UA may display a permission prompt when this function is called. Even for a non-malicious page this action also preserves user privacy by preventing a site from connecting to a device before the user is aware that such a connection is possible. The UA may also display an indicator when a device connection is active.

Secondly, this specification requires that only secure contexts as described in [powerful-features] can access USB devices. This ensures both the authenticity of the code executing on behalf of the origin and that data read from the device may not be intercepted in transit.

Lastly, since USB devices are unable to distinguish requests from multiple sources, operating systems only allow a USB interface to have a single owning user-space or kernel-space driver. The UA acts as a user-space driver, therefore allowing only a single execution context to claim a USB interface at a time. The claimInterface() function will fail if multiple execution contexts attempt to claim an interface.

3.2. Attacking a Device

Historically, unless they were created for high security applications, USB devices have been designed to trust the host they are connected to and so the host is the traditional guardian of access to the capabilities a device provides. In the development of this specification two possibilities were considered. First, the UA could notify the device of the origin from which a request originated. This would be similar to the Referrer header included in HTTP request. The difficulty of this approach is that it places the burden of access control on the device. Devices often have very limited processing and storage capabilities and so an effort was made to limit the amount of work necessary on the part of the device.

The approach initially chosen during drafting of this specification was to instead require that the UA control access though a mechanism similiar to [CORS]. The device could provide the UA with a set of static data structures defining a set of origins that are allowed to connect to it. To support a transition period for existing devices it was proposed that information about allowed origins could also be provided out of band through some kind of public registry.

A downside of this approach was two-fold. First, it required vendors to build new devices with WebUSB in mind or rely on a public registry system that proved difficult to specify. Product development cycles are long and as only an Editor’s Draft this specification does not have the clout necessary to influence product planning. Second, it provided no mechanism for third-party developers to use this API with a device. This limited innovation and the number of developers who could take advantage of this new capability.

After considering these options the authors have decided that the permission prompt encouraged by the requestDevice() method and the integration with § 7.1 Feature Policy provide adequate protection against unwanted access to a device.

3.3. Attacking the Host

If a device is compromised then in addition to abusing its own capabilities the attacker may also use it to in turn attack the host to which it is connected or if the exploit is persistent any host it is connected to later. The methods above are the ways in which this specification attempts to mitigate this attack vector for once the device is under the control of an attacker (for example, by uploading a malicious firmware image) there is nothing that can be done by the UA to prevent further damage.

This specification recommends device manufacturers practice defense in depth by designing their devices to only accept signed firmware updates and/or require physical access to the device in order to apply some configuration changes.

4. WebUSB Descriptors and Requests

This specification defines descriptors and commands the UA MAY use to gather information about the device specific to implementing this API.

4.1. WebUSB Platform Capability Descriptor

A device announces support for the WebUSB command set by including the following Platform Descriptor in its Binary Object Store:

Offset Field Size Value Description 0 bLength 1 Number Size of this descriptor. Must be set to 24. 1 bDescriptorType 1 Constant DEVICE CAPABILITY descriptor type ([USB31] Table 9-6). 2 bDevCapabilityType 1 Constant PLATFORM capability type ([USB31] Table 9-14). 3 bReserved 1 Number This field is reserved and shall be set to zero. 4 PlatformCapabilityUUID 16 UUID Must be set to {3408b638-09a9-47a0-8bfd-a0768815b665}. 20 bcdVersion 2 BCD Protocol version supported. Must be set to 0x0100. 22 bVendorCode 1 Number bRequest value used for issuing WebUSB requests. 23 iLandingPage 1 Number URL descriptor index of the device’s landing page.

The iLandingPage field, when non-zero, indicates a landing page which the device manufacturer would like the user to visit in order to control their device. The UA MAY suggest the user navigate to this URL when the device is connected.

Note: The USB is a little-endian bus and so according to [RFC4122] the UUID above MUST be sent over the wire as the byte sequence {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} .

4.2. WebUSB Device Requests

All control transfers defined by this specification are considered to be vendor-specific requests. The bVendorCode value found in the WebUSB Platform Capability Descriptor provides the UA with the bRequest the device expects the host to use when issuing control transfers these requests. The request type is then specified in the wIndex field.

WebUSB Request Codes Constant Value (Reserved) 1 GET_URL 2

4.2.1. Get URL

This request fetches the URL descriptor with the given index.

The device MUST respond with the URL Descriptor at the given index or stall the transfer if the index is invalid.

bmRequestType bRequest wValue wIndex wLength Data 11000000B bVendorCode Descriptor Index GET_URL Descriptor Length Descriptor

4.3. WebUSB Descriptors

These descriptor types are returned by requests defined in this specification.

WebUSB Descriptor Types Constant Value (Reserved) 0-2 WEBUSB_URL 3

4.3.1. URL Descriptor

This descriptor contains a single URL and is returned by the Get URL request.

Offset Field Size Value Description 0 bLength 1 Number Size of this descriptor. 1 bDescriptorType 1 Constant WEBUSB_URL. 2 bScheme 1 Number URL scheme prefix. 3 URL Variable String UTF-8 encoded URL (excluding the scheme prefix).

The bScheme field MUST be one of these values:

URL Prefixes Value Prefix 0 "http://" 1 "https://" 255 ""

The special value 255 indicates that the entire URL, including scheme, is encoded in the URL field.

5. Device Enumeration

⚠ MDN USB In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+

⚠ MDN USB/getDevices In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USB/onconnect In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USB/ondisconnect In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USB/requestDevice In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+

getDevices() , document . addEventListener ( 'DOMContentLoaded' , async () => { let devices = await navigator . usb . getDevices (); devices . forEach ( device => { // Add |device| to the UI. }); }); In this example, we retrieve some devices to include in a UI. When the page is first loaded, it should check if it already has permission to access any connected devices by calling After the page is loaded the user may connect or disconnect a device from their system so script should also register for these events in order to keep the interface up-to-date, navigator . usb . addEventListener ( 'connect' , event => { // Add |event.device| to the UI. }); navigator . usb . addEventListener ( 'disconnect' , event => { // Remove |event.device| from the UI. }); If this is the first time the user has visited the page then it won’t have permission to access any devices so the page must first call requestDevice() while the relevant global object has a transient activation. In this case the page supports devices from vendor 0xABCD that carry the vendor-specific subclass 0x01 , let button = document . getElementById ( 'request-device' ); button . addEventListener ( 'click' , async () => { let device ; try { device = await navigator . usb . requestDevice ({ filters : [{ vendorId : 0xABCD , classCode : 0xFF , // vendor-specific protocolCode : 0x01 }]}); } catch ( err ) { // No device was selected. } if ( device !== undefined ) { // Add |device| to the UI. } });

A USB device device matches a device filter filter if the following steps return match :

Let deviceDesc be device ’s device descriptor. If filter . vendorId is present and deviceDesc .idVendor does not equal filter . vendorId , return mismatch . If filter . productId is present and deviceDesc .idProduct does not equal filter . productId , return mismatch . If filter . serialNumber is present then, let serialNumber be the string descriptor with index deviceDesc .iSerialNumber . If device returns an error when requesting serialNumber or serialNumber is not equal to filter . serialNumber , return mismatch . If filter . classCode is present and, for any of device ’s interface’s interface , interface matches the interface filter filter , return match . If filter . classCode is present and deviceDesc .bDeviceClass is not equal to filter . classCode , return mismatch . If filter . subclassCode is present and deviceDesc .bDeviceSubClass is not equal to filter . subclassCode , return mismatch . If filter . protocolCode is present and deviceDesc .bDeviceProtocol is not equal to filter . protocolCode , return mismatch . Return match .

Note: The steps above treat the bDeviceClass , bDeviceSubClass and bDeviceProtocol fields of the device descriptor as though they were part of an interface descriptor which is also compared against the provided filter.

A USB interface interface matches an interface filter filter if the following steps return match :

Let desc be interface ’s interface descriptor. If filter . classCode is present and desc .bInterfaceClass is not equal to filter . classCode , return mismatch . If filter . subclassCode is present and desc .bInterfaceSubClass is not equal to filter . subclassCode , return mismatch . If filter . protocolCode is present and desc .bInterfaceProtocol is not equal to filter . protocolCode , return mismatch . Return match .

A USBDeviceFilter filter is valid if the following steps return valid :

If filter . productId is present and filter . vendorId is not present, return invalid . If filter . subclassCode is present and filter . classCode is not present, return invalid . If filter . protocolCode is present and filter . subclassCode is not present, return invalid . Return valid .

The UA MUST be able to enumerate all devices attached to the system . It is, however NOT required to perform this work each time an algorithm requests an enumeration. The UA MAY cache the result of the first enumeration it performs and then begin monitoring for device connection and disconnection events, adding connected devices to its cached enumeration and removing disconnected devices. This mode of operation is preferred as it reduces the number of operating system calls made and amount of bus traffic generated by the getDevices() and requestDevice() methods.

The onconnect attribute is an Event handler IDL attribute for the connect event type.

The ondisconnect attribute is an Event handler IDL attribute for the disconnect event type.

The getDevices() method, when invoked, MUST return a new Promise and run the following steps in parallel:

The requestDevice() method, when invoked, MUST run the following steps:

Request permission to use the following descriptor, { name : "usb" filters : options . filters } Let permissionResult be the resulting Promise . Upon fulfillment of permissionResult with result run the following steps: If result . devices is empty, throw a NotFoundError and abort these steps. Return result . devices [0] .

To request the "usb" permission , given a USBPermissionStorage storage , a USBPermissionDescriptor options and a USBPermissionResult status , the UA MUST return a new Promise promise and run the following steps in parallel:

To add an allowed USB device device to USBPermissionStorage storage , the UA MUST run the following steps:

Search for an element allowedDevice in storage . allowedDevices where device is in allowedDevice @ [[devices]] . If one is found, abort these steps. Let vendorId and productId be device ’s vendor ID and product ID. Let serialNumber be device ’s serial number if it has one, otherwise undefined . Append { vendorId: vendorId , productId: productId , serialNumber: serialNumber } , with a [[devices]] internal slot containing a single entry device to storage . allowedDevices .

To check permissions for a new USB device device , given a USBPermissionStorage storage , the UA MUST run the following steps:

Let vendorId and productId be device ’s vendor ID and product ID. Let serialNumber be device ’s if it has one, otherwise undefined . Search for an element allowedDevice in storage . allowedDevices where: allowedDevice . vendorId equals vendorId .

allowedDevice . productId equals productId .

allowedDevice . serialNumber equals serialNumber . If no such element exists, return null . Add device to allowedDevice @ [[devices]] . Return allowedDevice .

5.1. Events

dictionary USBConnectionEventInit : EventInit { required USBDevice device ; }; [ Exposed =( DedicatedWorker , SharedWorker , Window ), SecureContext ] interface USBConnectionEvent : Event { constructor ( DOMString type , USBConnectionEventInit eventInitDict ); [ SameObject ] readonly attribute USBDevice device ; };

When the UA detects a new USB device device connected to the host it MUST perform the following steps for each script execution environment:

Let storage be the USBPermissionStorage object in the current script execution environment. Check permissions for device with storage and let allowedDevice be the result. If allowedDevice is null , abort these steps. Let deviceObj be the USBDevice object representing device . Let event be a new USBConnectionEvent , with the device attribute set to deviceObj . Fire an event named connect on usb , using event as the event object.

When the UA detects a USB device device has been disconnected from the host it MUST perform the following steps for each script execution environment:

Let storage be the USBPermissionStorage object in the current script execution environment. Search for an element allowedDevice in storage . allowedDevices where device is in allowedDevice @ [[devices]] , if no such element exists, abort these steps. Remove device from allowedDevice @ [[devices]] . If allowedDevice . serialNumber is undefined and allowedDevice @ [[devices]] is empty remove allowedDevice from storage . allowedDevices . Let device be the USBDevice object representing device . Let event be a new USBConnectionEvent , with the device attribute set to device . Fire an event named disconnect on usb , using event as the event object.

6. Device Usage

⚠ MDN USBDevice In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+

⚠ MDN USBDevice/claimInterface In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/clearHalt In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/close In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/configuration In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/configurations In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/controlTransferIn In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/controlTransferOut In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceClass In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceProtocol In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceSubclass In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceVersionMajor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceVersionMinor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/deviceVersionSubminor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/isochronousTransferIn In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/isochronousTransferOut In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/manufacturerName In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/open In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/opened In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/productId In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/productName In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/releaseInterface In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/reset In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/selectAlternateInterface In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/selectConfiguration In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/serialNumber In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/transferIn In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/transferOut In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/usbVersionMajor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/usbVersionMinor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/usbVersionSubminor In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+ USBDevice/vendorId In only one current engine. Firefox None Safari None Chrome 61+ Opera 48+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 61+ Android WebView None Samsung Internet 8.0+ Opera Mobile 45+

bConfigurationValue 1 ) with a single interface ( bInterfaceNumber 1 ) with a single bulk endpoint ( bEndpointAddress 0x81 which means that it is endpoint 1 and an IN endpoint). When data is sampled it is available on this endpoint. The maximum packet size on this endpoint is 16 bytes to support all 8 channels being activated at the same time. To save bus bandwidth, however, any combination of channels can be activated and deactivated. The packet will only be the length necessary to transmit the data collected. In this example we imagine a data logging device supporting up to 8 16-bit data channels. It has a single configuration () with a single interface () with a single bulk endpoint (which means that it is endpoint 1 and an IN endpoint). When data is sampled it is available on this endpoint. The maximum packet size on this endpoint is 16 bytes to support all 8 channels being activated at the same time. To save bus bandwidth, however, any combination of channels can be activated and deactivated. The packet will only be the length necessary to transmit the data collected. To get started we open the device, select the first configuration (it only has one but the operating system may not have already done this during enumeration) and claim the data logging interface, await device . open (); if ( device . configuration === null ) await device . selectConfiguration ( 1 ); await device . claimInterface ( 1 ); For this particular application we care about reading from channels 1, 2 and 5 so we issue a control transfer to activate these channels, await device . controlTransferOut ({ requestType : ' vendor ' , recipient : ' interface ' , request : 0x01 , // vendor-specific request: enable channels value : 0x0013 , // 0b00010011 (channels 1, 2 and 5) index : 0x0001 // Interface 1 is the recipient }); The application may now start polling the device for data. As we only expect data from 3 channels we request a 6 byte buffer. As long as we receive a complete buffer the captured values (transmitted in big endian) are printed to the console log. If the device has encountered an error and signals this by stalling the endpoint then the error is cleared before continuing, while ( true ) { let result = await data . transferIn ( 1 , 6 ); if ( result . data && result . data . byteLength === 6 ) { console . log ( 'Channel 1: ' + result . data . getUint16 ( 0 )); console . log ( 'Channel 2: ' + result . data . getUint16 ( 2 )); console . log ( 'Channel 5: ' + result . data . getUint16 ( 4 )); } if ( result . status === 'stall' ) { console . warn ( 'Endpoint stalled. Clearing.' ); await device . clearHalt ( 1 ); } }

The usbVersionMajor , usbVersionMinor and usbVersionSubminor attributes declare the USB protocol version supported by the device. They SHALL correspond to the value of the bcdUSB field of the device descriptor such that a value of 0xJJMN has major version JJ , minor version M and subminor version N .

The deviceClass , deviceSubclass and deviceProtocol attributes declare the communication interface supported by the device. They MUST correspond respectively to the values of the bDeviceClass , bDeviceSubClass and bDeviceProtocol fields of the device descriptor.

The vendorId and productId MUST be equal to the device’s vendor ID and product ID.

The deviceVersionMajor , deviceVersionMinor and deviceVersionSubminor attributes declare the device release number as defined by the device manufacturer. It SHALL correspond to the value of the bcdDevice field of the device descriptor such that a value of 0xJJMN has major version JJ , minor version M and subminor version N .

The manufacturerName , productName and serialNumber attributes SHOULD contain the values of the string descriptors indexed by the iManufacturer , iProduct and iSerialNumber fields of the device descriptor if each is defined.

The configuration attribute contains the currently selected configuration for the device and SHALL be one of the configurations listed in configurations . It MAY be null if the device is in an unconfigured state and MUST be updated by selectConfiguration() .

The configurations attribute contains a list of configurations supported by the device. These configurations SHALL be populated from the configuration descriptors reported by the device and the number of elements in this list SHALL match the value of the bNumConfigurations field of the device descriptor.

The opened attribute SHALL be set to true when the device is opened by the current execution context and SHALL be set to false otherwise.

The open() method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. If device . opened is true resolve promise and abort these steps. Perform the necessary platform-specific steps to begin a session with the device. If these fail for any reason reject promise with a NetworkError and abort these steps. Set device . opened to true and resolve promise .

The close() method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. If device . opened is false resolve promise and abort these steps. Abort all other algorithms currently running against this device and reject their associated promises with an AbortError . Perform the necessary platform-specific steps to release any claimed interfaces as if releaseInterface(interfaceNumber) had been called for each claimed interface. Perform the necessary platform-specific steps to end the session with the device. Set device . opened to false and resolve promise .

When no [ECMAScript] code can observe an instance of USBDevice device anymore, the UA SHOULD run device . close() .

The selectConfiguration(configurationValue) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let configuration be the device configuration with bConfigurationValue equal to configurationValue . If no such configuration exists, reject promise with a NotFoundError and abort these steps. If device . opened is not equal to true reject promise with an InvalidStateError and abort these steps. Abort all transfers currently scheduled on endpoints other than the default control pipe and reject their associated promises with a AbortError . Issue a SET_CONFIGURATION control transfer to the device to set configurationValue as its active configuration. If this step fails reject promise with a NetworkError and abort these steps. Set device . configuration to configuration and resolve promise .

The claimInterface(interfaceNumber) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

If the device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let interface be the interface in the active configuration with bInterfaceNumber equal to interfaceNumber . If no such interface exists, reject promise with a NotFoundError and abort these steps. If device . opened is not true , reject promise with an InvalidStateError and abort these steps. If interface . claimed is true , resolve promise and abort these steps. Perform the necessary platform-specific steps to request exclusive control over interface for the current execution context. If this fails, reject promise with a NetworkError and abort these steps. Set interface . claimed to true and resolve promise .

The releaseInterface(interfaceNumber) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let interface be the interface in the active configuration with bInterfaceNumber equal to interfaceNumber . If no such interface exists, reject promise with a NotFoundError and abort these steps. If device . opened is not true , reject promise with an InvalidStateError and abort these steps. If interface . claimed is false , resolve promise and abort these steps. Perform the necessary platform-specific steps to reliquish exclusive control over interface . Set interface . claimed to false and resolve promise .

The selectAlternateInterface(interfaceNumber, alternateSetting) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let interface be the interface in the active configuration with bInterfaceNumber equal to interfaceNumber . If no such interface exists, reject promise with a NotFoundError and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. Abort all transfers currently scheduled on endpoints associated with the previously selected alternate setting of interface and reject their associated promises with a AbortError . Issue a SET_INTERFACE control transfer to the device to set alternateSetting as the current configuration of interface . If this step fails reject promise with a NetworkError and abort these steps. Resolve promise .

The controlTransferIn(setup, length) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

The controlTransferOut(setup, data) method, when invoked, must return a new Promise promise and run the following steps in parallel:

The clearHalt(direction, endpointNumber) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

If the device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let endpoint be the endpoint in the active configuration with bEndpointAddress corresponding to direction and endpointNumber . If no such endpoint exists reject promise and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. Issue a ClearFeature(ENDPOINT_HALT) control transfer to the device to clear the halt condition on endpoint . On failure reject promise with a NetworkError , otherwise resolve promise .

The transferIn(endpointNumber, length) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let endpoint be the IN endpoint in the active configuration with bEndpointAddress corresponding to endpointNumber . If there is no such endpoint reject promise with a NotFoundError and abort these steps. If endpoint is not a bulk or interrupt endpoint reject promise with an InvalidAccessError and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. Let buffer be a host buffer with space for length bytes. As appropriate for endpoint enqueue a bulk or interrupt IN transfer on endpoint to receive length bytes of data from the device into buffer . Let bytesTransferred be the number of bytes written to buffer . Let result be a new USBInTransferResult . If data was received from device create a new ArrayBuffer containing the first bytesTransferred bytes of buffer and set result . data to a new DataView constructed over it. If device responded with more than length bytes of data set result . status to "babble" . If the transfer ended because endpoint is halted set result . status to "stall" . If device acknowledged the complete transfer set result . status to "ok" . If the transfer failed for any other reason reject promise with a NetworkError and abort these steps. Resolve promise with result .

The transferOut(endpointNumber, data) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

If the device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let endpoint be the OUT endpoint in the active configuration with bEndpointAddress corresponding to endpointNumber . If there is no such endpoint reject promise with a NotFoundError and abort these steps. If endpoint is not a bulk or interrupt endpoint reject promise with an InvalidAccessError and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. As appropriate for endpoint enqueue a bulk or interrupt OUT transfer on endpoint to transmit data to the device. Let result be a new USBOutTransferResult . Set result . bytesWritten to the amount of data successfully sent to the device. If the endpoint is stalled set result . status to "stall" . If the device acknowledges the complete transfer set result . status to "ok" . If the transfer fails for any other reason reject promise with a NetworkError and abort these steps. Resolve promise with result .

The isochronousTransferIn(endpointNumber, packetLengths) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

If the device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let endpoint be the IN endpoint in the active configuration with bEndpointAddress corresponding to endpointNumber . If there is no such endpoint reject promise with a NotFoundError and abort these steps. If endpoint is not an isochronous endpoint reject promise with an InvalidAccessError and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. Let length be the sum of the elements of packetLengths . Let buffer be a new ArrayBuffer of length bytes. Let result be a new USBIsochronousInTransferResult and set result . data to a new DataView constructed over buffer . Enqueue an isochronous IN transfer on endpoint that will write up to length bytes of data from the device into buffer . For each packet i from 0 to packetLengths .length - 1 : Let packet be a new USBIsochronousInTransferPacket and set result . packets [i] to packet . Let view be a new DataView over the portion of buffer containing the data received from the device for this packet and set packet . data to view . If the device responds with more than packetLengths [i] bytes of data set packet . status to "babble" . If the transfer ends because endpoint is stalled set packet . status to "stall" . If the device acknowledges the complete transfer set packet . status to "ok" . If the transfer fails for any other reason reject promise with a NetworkError and abort these steps. Resolve promise with result .

The isochronousTransferOut(endpointNumber, data, packetLengths) method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

If the device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. Let endpoint be the OUT endpoint in the active configuration with bEndpointAddress corresponding to endpointNumber . If there is no such endpoint reject promise with a NotFoundError and abort these steps. If endpoint is not an isochronous endpoint reject promise with an InvalidAccessError and abort these steps. If device . opened or interface . claimed is not true , reject promise with an InvalidStateError and abort these steps. Let length be the sum of the elements of packetLengths . Let result be a new USBIsochronousOutTransferResult . Enqueue an isochronous OUT transfer on endpoint that will write buffer to the device, divided into packetLength .length packets of packetLength [i] bytes (for packets i from 0 to packetLengths .length - 1 ). For each packet i from 0 to packetLengths .length - 1 the host attempts to send to the device: Let packet be a new USBIsochronousOutTransferPacket and set result . packets [i] to packet . Let packet . bytesWritten be the amount of data successfully sent to the device as part of this packet. If the transfer ends because endpoint is stalled set packet . status to "stall" . If the device acknowledges the complete transfer set packet . status to "ok" . If the transfer fails for any other reason reject promise with a NetworkError and abort these steps. Resolve promise with result .

The reset() method, when invoked, MUST return a new Promise promise and run the following steps in parallel:

Let device be the target USBDevice object. If device is no longer connected to the system, reject promise with a NotFoundError and abort these steps. If device . opened is not equal to true reject promise with an InvalidStateError and abort these steps. Abort all operations on the device and reject their associated promises with an AbortError . Perform the necessary platform-specific operation to soft reset the device. On failure reject promise with a NetworkError , otherwise resolve promise .

What configuration is the device in after it resets? <https://github.com/WICG/webusb/issues/36>

6.1. Transfers

A control transfer is a special class of USB traffic most commonly used for configuring a device. It consists of three stages: setup, data and status. In the setup stage a setup packet is transmitted to the device containing request parameters including the transfer direction and size of the data to follow. In the data stage that data is either sent to or received from the device. In the status stage successful handling of the request is acknowledged or a failure is signaled.

All USB devices MUST have a default control pipe which is endpointNumber 0 .

The requestType attribute populates part of the bmRequestType field of the setup packet to indicate whether this request is part of the USB standard, a particular USB device class specification or a vendor-specific protocol.

The recipient attribute populates part of the bmRequestType field of the setup packet to indicate whether the control transfer is addressed to the entire device, or a specific interface or endpoint.

The request attribute populates the bRequest field of the setup packet. Valid requests are defined by the USB standard, USB device class specifications or the device vendor.

The value and index attributes populate the wValue and wIndex fields of the setup packet respectively. The meaning of these fields depends on the request being made.

To check the validity of the control transfer parameters perform the following steps:

Let setup be the USBControlTransferParameters created for the transfer. Let promise be the promise created for the transfer. Let configuration be the active configuration. If the device is not configured abort these steps. If setup . recipient is "interface" , perform the following steps: Let interfaceNumber be the lower 8 bits of setup . index . Let interface be the interface in the | configuration| with bInterfaceNumber equal to interfaceNumber . If no such interface exists, reject promise with a NotFoundError and abort these steps. If interface . claimed is not equal to true , reject promise with an InvalidStateError and abort these steps. If setup . recipient is "endpoint" , run the following steps: Let endpointNumber be defined as the lower 4 bits of setup . index . Let direction be defined as "in" if the 8th bit of setup . index is 1 and "out" otherwise. Let endpoint be the endpoint in the active configuration with bEndpointAddress corresponding to direction and endpointNumber . If no such endpoint exists, reject promise with a NotFoundError and abort these steps. Let interface be the interface in which endpoint is defined. If interface . claimed is not equal to true , reject promise with an InvalidStateError .

6.2. Configurations

[ Exposed =( DedicatedWorker , SharedWorker , Window ), SecureContext ] interface USBConfiguration { constructor ( USBDevice device , octet configurationValue ); readonly attribute octet configurationValue ; readonly attribute DOMString ? configurationName ; readonly attribute FrozenArray < USBInterface > interfaces ; };

Each device configuration SHALL have a unique configurationValue that matches the bConfigurationValue fields of the configuration descriptor that defines it.

The configurationName attribute SHOULD contain the value of the string descriptor referenced by the iConfiguration field of the configuration descriptor, if defined.

The interfaces attribute SHALL contain a list of interfaces exposed by this device configuration. These interfaces SHALL by populated by collecting the interface descriptors contained within this configuration descriptor and organizing them by bInterfaceNumber .

Include some non-normative information about device configurations. <https://github.com/WICG/webusb/issues/46>

6.3. Interfaces

[ Exposed =( DedicatedWorker , SharedWorker , Window ), SecureContext ] interface USBInterface { constructor ( USBConfiguration configuration , octet interfaceNumber ); readonly attribute octet interfaceNumber ; readonly attribute USBAlternateInterface alternate ; readonly attribute FrozenArray < USBAlternateInterface > alternates ; readonly attribute boolean claimed ; }; [ Exposed =( DedicatedWorker , SharedWorker , Window ), SecureContext ] interface USBAlternateInterface { constructor ( USBInterface deviceInterface , octet alternateSetting ); readonly attribute octet alternateSetting ; readonly attribute octet interfaceClass ; readonly attribute octet interfaceSubclass ; readonly attribute octet interfaceProtocol ; readonly attribute DOMString ? interfaceName ; readonly attribute FrozenArray < USBEndpoint > endpoints ; };

Each interface provides a collection of alternates identified by a single bInterfaceNumber field found in their interface descriptors. The interfaceNumber attribute MUST match this field.

The alternate attribute SHALL be set to the USBAlternateInterface that is currently selected for this interface, which by default SHALL be the one with bAlternateSetting equal to 0 .

The alternates attribute SHALL contain a list of all alternate interface configurations available for this interface.

The claimed attribute SHALL be set to true when the interface is claimed by the current execution context and SHALL be set to false otherwise.

Each alternative interface configuration SHALL have a unique alternateSetting within a given interface that matches the bAlternateSetting field of the interface descriptor that defines it.

The interfaceClass , interfaceSubclass and interfaceProtocol attributes declare the communication interface supported by the interface. They MUST correspond respectively to the values of the bInterfaceClass , bInterfaceSubClass and bInterfaceProtocol fields of the interface descriptor.

The interfaceName attribute SHOULD contain the value of the string descriptor indexed by the iInterface field of the interface descriptor, if defined.

The endpoints attribute SHALL contain a list of endpoints exposed by this interface. These endpoints SHALL by populated from the endpoint descriptors contained within this interface descriptor and the number of elements in this sequence SHALL match the value of the bNumEndpoints field of the interface descriptor.

A device’s active configuration is the combination of the USBConfiguration selected by calling selectConfiguration(configurationValue) and the set of USBAlternateInterface s selected by calling selectAlternateInterface(interfaceNumber, alternateSetting) . A device MAY, by default, be left in an unconfigured state, referred to as configuration 0 or may automatically be set to whatever configuration has bConfigurationValue equal to 1 . When a configuration is set all interfaces within that configuration automatically have the USBAlternateInterface with bAlternateSetting equal to 0 selected by default. It is therefore unnecessary to call selectAlternateInterface(interfaceNumber, alternateSetting) with alternateSetting equal to 0 for each interface when opening a device.

6.4. Endpoints

enum USBDirection { "in" , "out" }; enum USBEndpointType { "bulk" , "interrupt" , "isochronous" }; [ Exposed =( DedicatedWorker , SharedWorker , Window ), SecureContext ] interface USBEndpoint { constructor ( USBAlternateInterface alternate , octet endpointNumber , USBDirection direction ); readonly attribute octet endpointNumber ; readonly attribute USBDirection direction ; readonly attribute USBEndpointType type ; readonly attribute unsigned long packetSize ; };

Each endpoint within a particular device configuration SHALL have a unique combination of endpointNumber and direction . The endpointNumber MUST equal the 4 least significant bits of the bEndpointAddress field of the endpoint descriptor defining the endpoint.

The direction attribute declares the transfer direction supported by this endpoint and is equal to "in" if the most significant bit of the bEndpointAddress is set and "out" otherwise. An endpoint may either carry data IN from the device to host or OUT from host to device.

The type attribute declares the type of data transfer supported by this endpoint.

The packetSize attribute declares the packet size employed by this endpoint and MUST be equal to the value of the wMaxPacketSize of the endpoint descriptor defining it. In a High-Speed, High-Bandwidth endpoint this value will include the multiplication factor provided by issuing multiple transactions per microframe. In a SuperSpeed device this value will include the multiplication factor provided by the bMaxBurst field of the SuperSpeed Endpoint Companion descriptor.

7. Integrations

7.1. Feature Policy

⚠ MDN Headers/Feature-Policy/usb In only one current engine. Firefox None Safari None Chrome 60+ Opera 47+ Edge 79+ Edge (Legacy) None IE None Firefox for Android None iOS Safari None Chrome for Android 60+ Android WebView 60+ Samsung Internet 8.0+ Opera Mobile 44+

This specification defines a feature that controls whether the usb attribute is exposed on the Navigator object.

The feature name for this feature is "usb" .

The default allowlist for this feature is ["self"] .

7.2. Permission API

The [permissions] API provides a uniform way for websites to request permissions from users and query which permissions they have.

The "usb" powerful feature is defined as follows:

8. Terminology

This specification uses several terms taken from [USB31]. While reference is made to version 3.1 of the Universal Serial Bus many of these concepts exist in previous versions as well. Significant differences between USB versions that have bearing on this specification will be called out explicitly.

Descriptors are binary data structures that can be read from a device and describe its properties and function:

The device descriptor contains information applicable to the entire devices and is described in section 9.6.1 of [USB31].

A configuration descriptor describes a particular set of device interfaces and endpoints that can be selected by the host. Its fields are described in section 9.6.3 of [USB31].

An interface descriptor describes the interface of a particular functional component of a device including its protocol and communication endpoints. Its fields are described in section 9.6.5 of [USB31].

An interface association descriptor creates an association between multiple interfaces that are part of a single functional unit of a device. Its fields are described in section 9.6.4 of [USB31].

An endpoint descriptor describes a channel through which data is either sent to or received from the device. Its fields are described in section 9.6.6 of [USB31].

A string descriptor contains a single UTF16-LE string and is referenced by index by other descriptors. Its fields are described in section 9.6.9 of [USB31].

The Binary Object Store ( BOS ) is an additional set of descriptors that are more free-form than the standard device descriptors. Of note is the Platform Descriptor type which allows third parties (such as this specification) to declare their own types of descriptors. Each of these is identified by a UUID. The Binary Object Store is described in section 9.6.2 of [USB31].

A USB device has a single device descriptor which links to one or more configuration descriptors. It’s vendor ID is assigned to the device manufacturer by the USB-IF and is stored in the idVendor field of the device descriptor. It’s product ID is assigned by the manufacturer and is stored in the idProduct field of the device descriptor. It’s serial number is an optional property that is defined if the iSerialNumber field of the device descriptor is not equal to 0 and is the string descriptor referred to by that index.

9. Appendix: A Brief Introduction to USB

This section is non-normative.

USB is a network but it’s very different from traditional TCP/IP networks. It is really more like an RPC system. All traffic is directed by the host, that is, your computer. Though some devices like smartphones can act as both a USB host and USB client they can only take on one role at a time.

9.1. Descriptors

USB devices identify themselves to the host by providing a set of binary structures known as descriptors. The first one read by the host is the device descriptor which contains basic information such as the vendor and product IDs assigned by the USB-IF and the manufacturer. The host may then read the device’s configuration descriptor which is a description of the device’s capabilities including the interfaces and endpoints it exposes. A class can be declared at the device level or for individual interfaces. A device with multiple interfaces providing different functions is known as a composite device.

9.2. Transfers

Whether data is traveling from host to device or the other way around the transfer is always initiated by the host. OUT transfers carry data from host to device and may wait until the device acknowledges the data has been received. IN transfers carry data from device to host and may have to wait until the device has some data to send. Transfers are executed against one of a device’s endpoints and there are different kinds depending on what type of traffic is being sent.