USB

The WebUSB API allows Web applications to interact with the Universal Serial Bus-compatible devices available in the system. In order to authorize the application to get the access to the device, user needs to confirm the intent in the browser's UI that in turn may only be initiated with a gesture (for example, a button click, but not automatically by arbitrary JavaScript).

The API is based on the USB 3.1 specification and exposes all the USB primitives to JavaScript - including configurations, interfaces, endpoints and all the transfer types: CONTROL (suitable for commands), INTERRUPT (suitable for small time-sensitive data), BULK (suitable for large time-sensitive data) and ISOCHRONOUS (suitable for streams, for example media)

The specification, apart from the JavaScript API, defines a Platform Descriptor object that might be implemented at the device side to advertize its support for WebUSB. Google Chrome's implementation uses it to notify the user about the landing page of the plugged in device with the system notification.

API glimpse

Connecting to the device

navigator.usb.requestDevice(filters)
Returns the Promise resolved with the device object that matches the specified filter by predefined vendor ID, product ID, class or subclass code, protocol code or serial number.
navigator.usb.getDevices()
Returns the Promise resolved with the device objects for the devices previously authorized for this application.
navigator.usb.addEventListener('connect', listener)
An event fired when the already authorized device has been connected to the system, containing the connected device object.
navigator.usb.addEventListener('disconnect', listener)
An event fired when the previously connected device has been disconnected from the system, containing the disconnected device object.

Session setup

device.open()
Opens the communication session with the device. Returns a Promise resolved when the session has been opened.
device.close()
Closes the communication session with the device. Returns a Promise resolved when the session has been closed.
device.configurations
Contains the device-provided configuration objects with configurationValue identifier and the list of available interfaces.
device.selectConfiguration(configurationValue)
Selects the configuration of the device. Returns a Promise resolved when the setup has been applied.
device.claimInterface(interfaceNumber)
Claims the interface of the device (by the number specified in configuration.interfaces. Returns a Promise resolved when the setup has been applied.

Data transfers

device.controlTransferIn(setup, length)
Waits for a specified control transfer from the device. Returns the Promise resolved with the transfer data and status.
device.controlTransferOut(setup, data)
Sends a specified control transfer to the device. Returns the Promise resolved with the transfer status and the number of bytes written.
device.transferIn(endpointNumber, length)
Waits for a bulk or interrupt transfer from the device on a specified endpoint. Returns the Promise resolved with the transfer data and status.
device.transferOut(endpointNumber, data)
Sends a bulk or interrupt transfer to the specified endpoint of the device. Returns the Promise resolved with the transfer status and the number of bytes written.
device.isochronousTransferIn(endpointNumber, packetLengths)
Waits for a specified isochronous transfer from the device. Returns the Promise resolved with the list of packets received, each containing data and status.
device.isochronousTransferOut(endpointNumber, data, packetLengths)
Sends a specified isochronous transfer to the device. Returns the Promise resolved with the list of packets sent, each containing status and the number of bytes written.

Live Demo

Demo from Google Developers article.

  • document.getElementById('arduinoButton').addEventListener('click', function () {
      if (navigator.usb) {
        talkToArduino();
      } else {
        alert('WebUSB not supported.');
      }
    });
    
    async function talkToArduino() {
      try {
        let device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
        await device.open(); // Begin a session.
        await device.selectConfiguration(1); // Select configuration #1 for the device.
        await device.claimInterface(2); // Request exclusive control over interface #2.
        await device.controlTransferOut({
          requestType: 'class',
          recipient: 'interface',
          request: 0x22,
          value: 0x01,
          index: 0x02
        });
      
        // Ready to receive data
        let result = device.transferIn(5, 64); // Waiting for 64 bytes of data from endpoint #5.
        let decoder = new TextDecoder();
        document.getElementById('target').innerHTML = 'Received: ' + decoder.decode(result.data);
      } catch (error) {
        document.getElementById('target').innerHTML = error;
      }
    }
  • <button class="btn btn-default" id="arduinoButton">Talk to Arduino</button>
    
    <div id="target"></div>
    
    <p><small>Demo from <a href="https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web" target="_blank">Google Developers</a> article.</small></p>

Resources