WebUSB API
The WebUSB API provides a way to expose non-standard Universal Serial Bus (USB) compatible devices to the web. It allows web pages to find and communicate with devices, which previously required native drivers or specialized software.
1. The Concept
Traditionally, accessing USB devices from a browser was impossible for security reasons. WebUSB bridges this gap securely, enabling use cases like:
- Firmware updates for hardware.
- Interacting with educational robots or toys.
- Accessing specialized hardware (e.g., 3D printers, crypto wallets) without installing drivers.
2. The Connection Flow
Connecting to a USB device involves several steps:
- Request Device: Ask the user to select a device.
- Open: Start a session with the device.
- Select Configuration: Choose a configuration (usually #1).
- Claim Interface: Lock an interface for exclusive access.
- Transfer Data: Use Control, Interrupt, Isochronous, or Bulk transfers.
3. Requesting a Device
Like Web Bluetooth, WebUSB requires a user gesture (click) and HTTPS.
const button = document.getElementById('connect');
button.addEventListener('click', async () => {
try {
// Request a device with specific vendor ID (filters are optional but recommended)
const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
console.log('Device selected:', device.productName);
console.log('Vendor ID:', device.vendorId);
await connectToDevice(device);
} catch (error) {
console.error('Error:', error);
}
});
4. Connecting and Transferring Data
Once a device is selected, you must open it and set it up before sending data.
async function connectToDevice(device) {
await device.open();
if (device.configuration === null) {
await device.selectConfiguration(1);
}
await device.claimInterface(0);
console.log('Connected!');
// Example: Sending data (Control Transfer)
// setup: { requestType, recipient, request, value, index }
await device.controlTransferOut({
requestType: 'vendor',
recipient: 'device',
request: 0x01,
value: 0x00,
index: 0x00
});
// Example: Receiving data (Transfer In)
const result = await device.transferIn(1, 64); // endpointNumber, length
const decoder = new TextDecoder();
console.log('Received:', decoder.decode(result.data));
}
5. Security and Privacy
- HTTPS: Only works on secure contexts.
- User Gesture:
requestDevicemust be called inside a user-triggered event handler. - Permission: The browser shows a native chooser dialog. The website cannot see any devices until the user explicitly selects one.
6. Events
You can listen for connection and disconnection events.
navigator.usb.addEventListener('connect', (event) => {
console.log('Device connected:', event.device.productName);
});
navigator.usb.addEventListener('disconnect', (event) => {
console.log('Device disconnected:', event.device.productName);
});
programming/javascript/vanilla/javascript programming/javascript/vanilla/promises-async-await programming/javascript/vanilla/typed-arrays