Convert WebUSB article from WebFu #4095
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,369 @@ | ||||||||||||||||||
--- | ||||||||||||||||||
title: Access USB Devices on the Web | ||||||||||||||||||
subhead: | | ||||||||||||||||||
The WebUSB API makes USB safer and easier to use by bringing it to the Web. | ||||||||||||||||||
authors: | ||||||||||||||||||
- beaufortfrancois | ||||||||||||||||||
date: 2016-03-30 | ||||||||||||||||||
updated: 2020-10-19 | ||||||||||||||||||
hero: hero.jpg | ||||||||||||||||||
thumbnail: thumbnail.jpg | ||||||||||||||||||
alt: A photo of an Arduino Micro board | ||||||||||||||||||
description: | | ||||||||||||||||||
The WebUSB API makes USB safer and easier to use by bringing it to the Web. | ||||||||||||||||||
tags: | ||||||||||||||||||
- blog # blog is a required tag for the article to show up in the blog. | ||||||||||||||||||
- capabilities | ||||||||||||||||||
- devices | ||||||||||||||||||
feedback: | ||||||||||||||||||
- api | ||||||||||||||||||
--- | ||||||||||||||||||
|
||||||||||||||||||
If I said plain and simple "USB", there is a good chance that you will | ||||||||||||||||||
immediately think of keyboards, mice, audio, video and storage devices. You're | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
right but you'll find other kinds of Universal Serial Bus (USB) devices out | ||||||||||||||||||
there. | ||||||||||||||||||
|
||||||||||||||||||
These non-standardized USB devices require hardware vendors to write native | ||||||||||||||||||
drivers and SDKs in order for you (the developer) to take advantage of them. | ||||||||||||||||||
Sadly this native code has historically prevented these devices from being used | ||||||||||||||||||
by the Web. And that's one of the reasons the WebUSB API has been created: to | ||||||||||||||||||
provide a way to expose USB device services to the Web. With this API, hardware | ||||||||||||||||||
manufacturers will be able to build cross-platform JavaScript SDKs for their | ||||||||||||||||||
devices. | ||||||||||||||||||
But most importantly this will **make USB safer and easier to use by bringing | ||||||||||||||||||
it to the Web**. | ||||||||||||||||||
|
||||||||||||||||||
Let's see what you could expect with the WebUSB API: | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The language is a little more specific. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
1. Buy a USB device. | ||||||||||||||||||
2. Plug it into your computer. | ||||||||||||||||||
3. A notification appears right away, with the right website to go to for this | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A best practice is that the steps always begin with the user action. Responses of a system are tacked to the end of the steps that initiated them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
device. | ||||||||||||||||||
4. Simply click on it. Website is there and ready to use! | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
5. Click to connect and a USB device chooser shows up in Chrome, where you can | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
pick your device. | ||||||||||||||||||
6. Tada! | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And the result of a procedure should be a paragraph after the procedure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
What would this procedure be like without the WebUSB API? | ||||||||||||||||||
|
||||||||||||||||||
- Read a box, label, or search on line and possibly end up on the wrong website. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should be numbered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the next few steps I suggest a rewrite to make this follow the same standards as I've outlined above. |
||||||||||||||||||
- Have to install a native application. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||||||||||||
- Is it supported on my operating system? Make sure you download the "right" | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
thing. | ||||||||||||||||||
- Scary OS prompts popup and warn you about installing drivers/applications from | ||||||||||||||||||
the Internet. | ||||||||||||||||||
- Malfunctioning code harms the whole computer. The Web is built to [contain | ||||||||||||||||||
malfunctioning websites]. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
- Only use the USB device once? On the Web, the website is gone once you closed | ||||||||||||||||||
tab. On a computer the code sticks around. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
## Before we start | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
This article assumes you have some basic knowledge of how USB works. If not, I | ||||||||||||||||||
recommend reading [USB in a NutShell]. For background information about USB, | ||||||||||||||||||
check out the [official USB specifications]. | ||||||||||||||||||
|
||||||||||||||||||
The [WebUSB API] is available in Chrome 61. | ||||||||||||||||||
|
||||||||||||||||||
### Available for Origin Trials | ||||||||||||||||||
|
||||||||||||||||||
In order to get as much feedback as possible from developers using the WebUSB | ||||||||||||||||||
API in the field, we've previously added this feature in Chrome 54 and Chrome | ||||||||||||||||||
57 as an [origin trial]. | ||||||||||||||||||
|
||||||||||||||||||
The latest trial has successfully ended in September 2017. | ||||||||||||||||||
|
||||||||||||||||||
## Privacy and security | ||||||||||||||||||
|
||||||||||||||||||
### HTTPS only | ||||||||||||||||||
|
||||||||||||||||||
Because this experimental API is a powerful new feature added to the Web, it is | ||||||||||||||||||
made available only to [secure contexts]. This means you'll need to build with | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
TLS in mind. | ||||||||||||||||||
|
||||||||||||||||||
### User gesture required | ||||||||||||||||||
|
||||||||||||||||||
As a security feature, getting access to connected USB devices with | ||||||||||||||||||
`navigator.usb.requestDevice` must be called via a user gesture | ||||||||||||||||||
like a touch or mouse click. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
### Feature Policy | ||||||||||||||||||
|
||||||||||||||||||
A feature policy is a mechanism that allows developers to selectively enable | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
and disable various browser features and APIs. It can be defined via a HTTP | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
header and/or an iframe "allow" attribute. | ||||||||||||||||||
|
||||||||||||||||||
You can define a feature that controls whether the usb attribute is exposed on | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
the Navigator object, or in other words if you allow WebUSB. | ||||||||||||||||||
|
||||||||||||||||||
Below is an example of a header policy where WebUSB is not allowed: | ||||||||||||||||||
|
||||||||||||||||||
```http | ||||||||||||||||||
Feature-Policy: fullscreen "*"; usb "none"; payment "self" https://payment.example.com | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
Below is another example of a different container policy where USB is allowed: | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
```html | ||||||||||||||||||
<iframe allowpaymentrequest allow="usb; fullscreen"></iframe> | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
## Let's start coding | ||||||||||||||||||
|
||||||||||||||||||
The WebUSB API relies heavily on JavaScript [Promises]. If you're not familiar | ||||||||||||||||||
with them, check out this great [Promises tutorial]. One more thing, `() => {}` | ||||||||||||||||||
are simply ECMAScript 2015 [Arrow functions] -- they have a shorter syntax | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we still need to explain promises and arrow functions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As noted in #4090, I've removed the explanation but kept links as developers interested in Bluetooth or USB may not necessarily be web developers. |
||||||||||||||||||
compared to function expressions and lexically bind the `this` value. | ||||||||||||||||||
|
||||||||||||||||||
### Get access to USB devices | ||||||||||||||||||
|
||||||||||||||||||
You can either prompt the user to select a single connected USB device using | ||||||||||||||||||
`navigator.usb.requestDevice` or call `navigator.usb.getDevices` to get a list | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
of all connected USB devices the origin has access to. | ||||||||||||||||||
|
||||||||||||||||||
The `navigator.usb.requestDevice` function takes a mandatory JavaScript object | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
that defines `filters`. These filters are used to match any USB device with the | ||||||||||||||||||
given vendor (`vendorId`) and optionally product (`productId`) identifiers. The | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
`classCode`, `protocolCode`, `serialNumber`, and `subclassCode` keys can also be | ||||||||||||||||||
defined there as well. | ||||||||||||||||||
|
||||||||||||||||||
<figure class="w-figure"> | ||||||||||||||||||
<img src="./usb-device-chooser.png" class="w-screenshot" alt="Screenshot of the USB device user prompt in Chrome"> | ||||||||||||||||||
<figcaption class="w-figcaption">USB device user prompt.</figcaption> | ||||||||||||||||||
</figure> | ||||||||||||||||||
|
||||||||||||||||||
For instance, here's how to get access to a connected Arduino device configured | ||||||||||||||||||
to allow the origin. | ||||||||||||||||||
|
||||||||||||||||||
```js | ||||||||||||||||||
navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] }) | ||||||||||||||||||
.then(device => { | ||||||||||||||||||
console.log(device.productName); // "Arduino Micro" | ||||||||||||||||||
console.log(device.manufacturerName); // "Arduino LLC" | ||||||||||||||||||
}) | ||||||||||||||||||
.catch(error => { console.log(error); }); | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
Before you ask, I didn't magically come up with this `0x2341` hexadecimal | ||||||||||||||||||
number. I simply searched for the word "Arduino" in this [List of USB ID's]. | ||||||||||||||||||
|
||||||||||||||||||
The USB `device` returned in the fulfilled promise above has some basic, yet | ||||||||||||||||||
important information about the device such as the supported USB version, | ||||||||||||||||||
maximum packet size, vendor and product IDs, the number of possible | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
configurations the device can have - basically all fields contained in the | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
[device USB Descriptor]. | ||||||||||||||||||
|
||||||||||||||||||
For info, if a USB device announces its [support for WebUSB], as well as | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
defining a landing page URL, Chrome will show a persistent notification when the | ||||||||||||||||||
USB device is plugged in. Clicking on this notification will open the landing page. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
<figure class="w-figure"> | ||||||||||||||||||
<img src="./web-usb-notification.png" class="w-screenshot" alt="Screenshot of the WebUSB notification in Chrome"> | ||||||||||||||||||
<figcaption class="w-figcaption">WebUSB notification.</figcaption> | ||||||||||||||||||
</figure> | ||||||||||||||||||
|
||||||||||||||||||
From there, you can simply call `navigator.usb.getDevices` and get access to | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
your Arduino device as shown below. | ||||||||||||||||||
|
||||||||||||||||||
```js | ||||||||||||||||||
navigator.usb.getDevices().then(devices => { | ||||||||||||||||||
devices.forEach(device => { | ||||||||||||||||||
console.log(device.productName); // "Arduino Micro" | ||||||||||||||||||
console.log(device.manufacturerName); // "Arduino LLC" | ||||||||||||||||||
}); | ||||||||||||||||||
}) | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
### Talk to an Arduino USB board | ||||||||||||||||||
|
||||||||||||||||||
Okay, now let's see how easy it is to communicate from a WebUSB compatible | ||||||||||||||||||
Arduino board over the USB port. Check out instructions at | ||||||||||||||||||
[https://github.com/webusb/arduino] to WebUSB-enable your [sketches]. | ||||||||||||||||||
|
||||||||||||||||||
Don't worry, I'll cover all the WebUSB device methods mentioned below later in | ||||||||||||||||||
this article. | ||||||||||||||||||
|
||||||||||||||||||
```js | ||||||||||||||||||
let device; | ||||||||||||||||||
|
||||||||||||||||||
navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] }) | ||||||||||||||||||
.then(selectedDevice => { | ||||||||||||||||||
device = selectedDevice; | ||||||||||||||||||
return device.open(); // Begin a session. | ||||||||||||||||||
}) | ||||||||||||||||||
.then(() => device.selectConfiguration(1)) // Select configuration #1 for the device. | ||||||||||||||||||
.then(() => device.claimInterface(2)) // Request exclusive control over interface #2. | ||||||||||||||||||
.then(() => device.controlTransferOut({ | ||||||||||||||||||
requestType: 'class', | ||||||||||||||||||
recipient: 'interface', | ||||||||||||||||||
request: 0x22, | ||||||||||||||||||
value: 0x01, | ||||||||||||||||||
index: 0x02})) // Ready to receive data | ||||||||||||||||||
.then(() => device.transferIn(5, 64)) // Waiting for 64 bytes of data from endpoint #5. | ||||||||||||||||||
.then(result => { | ||||||||||||||||||
const decoder = new TextDecoder(); | ||||||||||||||||||
console.log('Received: ' + decoder.decode(result.data)); | ||||||||||||||||||
}) | ||||||||||||||||||
.catch(error => { console.log(error); }); | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
Please keep in mind that the WebUSB library we are using here is just | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
implementing one example protocol (based on the standard USB serial protocol) | ||||||||||||||||||
and that manufacturers can create any set and types of endpoints they wish. | ||||||||||||||||||
Control transfers are especially nice for small configuration commands as | ||||||||||||||||||
they get bus priority and have a well defined structure. | ||||||||||||||||||
|
||||||||||||||||||
And here's the sketch that has been uploaded to the Arduino board. | ||||||||||||||||||
|
||||||||||||||||||
```arduino | ||||||||||||||||||
// Third-party WebUSB Arduino library | ||||||||||||||||||
#include <WebUSB.h> | ||||||||||||||||||
|
||||||||||||||||||
WebUSB WebUSBSerial(1 /* https:// */, "webusb.github.io/arduino/demos"); | ||||||||||||||||||
|
||||||||||||||||||
#define Serial WebUSBSerial | ||||||||||||||||||
|
||||||||||||||||||
void setup() { | ||||||||||||||||||
Serial.begin(9600); | ||||||||||||||||||
while (!Serial) { | ||||||||||||||||||
; // Wait for serial port to connect. | ||||||||||||||||||
} | ||||||||||||||||||
Serial.write("WebUSB FTW!"); | ||||||||||||||||||
Serial.flush(); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
void loop() { | ||||||||||||||||||
// Nothing here for now. | ||||||||||||||||||
} | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
The third-party [WebUSB Arduino library] used in the sample code above does | ||||||||||||||||||
basically two things: | ||||||||||||||||||
- The device acts as a WebUSB device enabling Chrome to read the [landing page | ||||||||||||||||||
URL]. | ||||||||||||||||||
- It exposes a WebUSB Serial API that you may use to override the default one. | ||||||||||||||||||
|
||||||||||||||||||
Let's look at the JavaScript code again. Once we get the `device` picked by the | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
user, `device.open` simply runs all platform-specific steps to start a session | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
with the USB device. Then, we have to select an available USB Configuration | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
with `device.selectConfiguration`. Remember that a Configuration specifies how | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
the device is powered, its maximum power consumption and its number of | ||||||||||||||||||
interfaces. Talking about interfaces, we also need to request exclusive access | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
with `device.claimInterface` since data can only be transferred to an interface | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
or associated endpoints when the interface is claimed. Finally calling | ||||||||||||||||||
`device.controlTransferOut` is needed to set up the Arduino device with the | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
appropriate commands to communicate through the WebUSB Serial API. | ||||||||||||||||||
|
||||||||||||||||||
From there, `device.transferIn` performs a bulk transfer onto the | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
device to inform it that the host is ready to receive bulk data. Then, the | ||||||||||||||||||
promise is fulfilled with a `result` object containing a [DataView] `data` that | ||||||||||||||||||
has to be parsed appropriately. | ||||||||||||||||||
|
||||||||||||||||||
For those who are familiar with USB, all of this should look pretty familiar. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
### I want more | ||||||||||||||||||
|
||||||||||||||||||
The WebUSB API lets you interact with the all USB transfer/endpoint types: | ||||||||||||||||||
|
||||||||||||||||||
- CONTROL transfers, used to send or receive configuration or command | ||||||||||||||||||
parameters to a USB device are handled with `controlTransferIn(setup, | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
length)` and `controlTransferOut(setup, data)`. | ||||||||||||||||||
- INTERRUPT transfers, used for a small amount of time sensitive data are | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
handled with the same methods as BULK transfers with | ||||||||||||||||||
`transferIn(endpointNumber, length)` and `transferOut(endpointNumber, data)`. | ||||||||||||||||||
- ISOCHRONOUS transfers, used for streams of data like video and sound are | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
handled with `isochronousTransferIn(endpointNumber, packetLengths)` and | ||||||||||||||||||
`isochronousTransferOut(endpointNumber, data, packetLengths)`. | ||||||||||||||||||
- BULK transfers, used to transfer a large amount of non-time-sensitive data in | ||||||||||||||||||
a reliable way are handled with `transferIn(endpointNumber, length)` and | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
`transferOut(endpointNumber, data)`. | ||||||||||||||||||
|
||||||||||||||||||
You may also want to have a look at Mike Tsao's [WebLight project] which | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you verified that the project is still up? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep. I still have some devices as well ;) |
||||||||||||||||||
provides a ground-up example of building a USB-controlled LED device designed | ||||||||||||||||||
for the WebUSB API (not using an Arduino here). You'll find hardware, software, | ||||||||||||||||||
and firmware. | ||||||||||||||||||
|
||||||||||||||||||
## Tips | ||||||||||||||||||
|
||||||||||||||||||
Debugging USB in Chrome is easier with the internal page `chrome://device-log` | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the information on the Chrome pages up to date? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep! |
||||||||||||||||||
where you can see all USB device related events in one single place. | ||||||||||||||||||
|
||||||||||||||||||
<figure class="w-figure"> | ||||||||||||||||||
<img src="./web-usb-device-log-page.png" class="w-screenshot" alt="Screenshot of the device log page to debug WebUSB in Chrome"> | ||||||||||||||||||
<figcaption class="w-figcaption">Device log page in Chrome for debugging the WebUSB API.</figcaption> | ||||||||||||||||||
</figure> | ||||||||||||||||||
|
||||||||||||||||||
The internal page `chrome://usb-internals` also comes in handy and allows you | ||||||||||||||||||
to simulate connection connection and disconnection of virtual WebUSB devices. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
This is be useful for doing UI testing without the need for real hardware. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
|
||||||||||||||||||
<figure class="w-figure"> | ||||||||||||||||||
<img src="./web-usb-internals-page.png" class="w-screenshot" alt="Screenshot of the internal page to debug WebUSB in Chrome"> | ||||||||||||||||||
<figcaption class="w-figcaption">Internal page in Chrome for debugging the WebUSB API.</figcaption> | ||||||||||||||||||
</figure> | ||||||||||||||||||
|
||||||||||||||||||
On most Linux systems, USB devices are mapped with read-only permissions by | ||||||||||||||||||
default. To allow Chrome to open a USB device, you will need to add a new [udev | ||||||||||||||||||
rule]. Create a file at `/etc/udev/rules.d/50-yourdevicename.rules` with the | ||||||||||||||||||
following content: | ||||||||||||||||||
|
||||||||||||||||||
```vim | ||||||||||||||||||
SUBSYSTEM=="usb", ATTR{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev" | ||||||||||||||||||
``` | ||||||||||||||||||
|
||||||||||||||||||
where `[yourdevicevendor]` is `2341` if your device is an Arduino for instance. | ||||||||||||||||||
`ATTR{idProduct}` can also be added for a more specific rule. Make sure your | ||||||||||||||||||
`user` is a member of the `plugdev` group. Then, just reconnect your device. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added a link that includes both answers. |
||||||||||||||||||
|
||||||||||||||||||
## What's next | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this section need to be updated? I couldn't find any features for shared or service workers on Chrome Status. I did find this: https://www.chromestatus.com/features/5928209916887040 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I've missed this. You're right. |
||||||||||||||||||
|
||||||||||||||||||
A second iteration of the WebUSB API will look at [Shared Worker] and [Service | ||||||||||||||||||
Worker] support. Imagine for instance a security key website using the WebUSB | ||||||||||||||||||
API that would install a service worker to act as a middle man to authenticate | ||||||||||||||||||
users. | ||||||||||||||||||
|
||||||||||||||||||
{% Aside %} | ||||||||||||||||||
Microsoft OS 2.0 Descriptors used by the Arduino examples only work on Windows | ||||||||||||||||||
8.1 and later. Without that Windows support still requires manual installation | ||||||||||||||||||
of an INF file. | ||||||||||||||||||
{% endAside %} | ||||||||||||||||||
|
||||||||||||||||||
## Resources | ||||||||||||||||||
|
||||||||||||||||||
- Stack Overflow: [https://stackoverflow.com/questions/tagged/webusb](https://stackoverflow.com/questions/tagged/webusb) | ||||||||||||||||||
- WebUSB API Spec: [http://wicg.github.io/webusb/](https://wicg.github.io/webusb/) | ||||||||||||||||||
- Chrome Feature Status: [https://www.chromestatus.com/feature/5651917954875392](https://www.chromestatus.com/feature/5651917954875392) | ||||||||||||||||||
- Spec Issues: [https://github.com/WICG/webusb/issues](https://github.com/WICG/webusb/issues) | ||||||||||||||||||
- Implementation Bugs: [http://crbug.com?q=component:Blink>USB](http://crbug.com?q=component:Blink>USB) | ||||||||||||||||||
- WebUSB ❤ ️Arduino: [https://github.com/webusb/arduino](https://github.com/webusb/arduino) | ||||||||||||||||||
- IRC: [#webusb](irc://irc.w3.org:6665/#webusb) on W3C's IRC | ||||||||||||||||||
- WICG Mailing list: [https://lists.w3.org/Archives/Public/public-wicg/](https://lists.w3.org/Archives/Public/public-wicg/) | ||||||||||||||||||
- WebLight project: [https://github.com/sowbug/weblight](https://github.com/sowbug/weblight) | ||||||||||||||||||
|
||||||||||||||||||
Please share your WebUSB demos with the [#webusb] hashtag. | ||||||||||||||||||
|
||||||||||||||||||
<!-- lint disable definition-case --> | ||||||||||||||||||
[contain malfunctioning websites]: https://www.youtube.com/watch?v=29e0CtgXZSI | ||||||||||||||||||
[USB in a NutShell]: http://www.beyondlogic.org/usbnutshell | ||||||||||||||||||
[official USB specifications]: https://www.usb.org/ | ||||||||||||||||||
[WebUSB API]: https://wicg.github.io/webusb/ | ||||||||||||||||||
[origin trial]: https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md | ||||||||||||||||||
[secure contexts]: https://w3c.github.io/webappsec/specs/powerfulfeatures/#intro | ||||||||||||||||||
[Promises]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise | ||||||||||||||||||
[Promises tutorial]: /promises | ||||||||||||||||||
[Arrow functions]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions | ||||||||||||||||||
[List of USB ID's]: http://www.linux-usb.org/usb.ids | ||||||||||||||||||
[device USB Descriptor]: http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors | ||||||||||||||||||
[support for WebUSB]: https://wicg.github.io/webusb/#webusb-platform-capability-descriptor | ||||||||||||||||||
[https://github.com/webusb/arduino]: https://github.com/webusb/arduino | ||||||||||||||||||
[sketches]: http://www.arduino.cc/en/Tutorial/Sketch | ||||||||||||||||||
[WebUSB Arduino library]: https://github.com/webusb/arduino/tree/gh-pages/library/WebUSB | ||||||||||||||||||
[landing page URL]: https://wicg.github.io/webusb/#webusb-platform-capability-descriptor | ||||||||||||||||||
[DataView]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView | ||||||||||||||||||
[WebLight project]: https://github.com/sowbug/weblight | ||||||||||||||||||
[udev rule]: https://www.freedesktop.org/software/systemd/man/udev.html | ||||||||||||||||||
[Shared Worker]: https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker | ||||||||||||||||||
[Service Worker]: https://jakearchibald.github.io/isserviceworkerready/resources.html | ||||||||||||||||||
[#webusb]: https://twitter.com/search?q=webusb | ||||||||||||||||||
<!-- lint enable definition-case --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be either:
or
I think the first is closer to what you're after.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done