Met de WebHID API kunnen websites toegang krijgen tot alternatieve extra toetsenborden en exotische gamepads.
Er is een lange lijst van Human Interface Devices (HID's), zoals alternatieve toetsenborden of exotische gamepads, die te nieuw, te oud of te ongebruikelijk zijn om toegankelijk te zijn voor de apparaatstuurprogramma's van systemen. De WebHID API biedt een oplossing hiervoor door een manier te bieden om apparaatspecifieke logica in JavaScript te implementeren.
Voorgestelde gebruiksscenario's
Een HID-apparaat verwerkt input van of levert output aan mensen. Voorbeelden van apparaten zijn toetsenborden, aanwijsapparaten (muizen, touchscreens, enz.) en gamepads. Het HID-protocol maakt het mogelijk om deze apparaten op desktopcomputers te benaderen met behulp van drivers van het besturingssysteem. Het webplatform ondersteunt HID-apparaten door gebruik te maken van deze drivers.
Het onvermogen om toegang te krijgen tot ongebruikelijke HID-apparaten is vooral pijnlijk als het gaat om alternatieve extra toetsenborden (zoals Elgato Stream Deck , Jabra-headsets , X-toetsen ) en ondersteuning voor exotische gamepads. Gamepads die voor desktops zijn ontworpen, gebruiken vaak HID voor inputs (knoppen, joysticks, triggers) en outputs (leds, trilfunctie). Helaas zijn de inputs en outputs van gamepads niet goed gestandaardiseerd en vereisen webbrowsers vaak aangepaste logica voor specifieke apparaten. Dit is onhoudbaar en resulteert in slechte ondersteuning voor de 'long tail' van oudere en ongebruikelijke apparaten. Het zorgt er ook voor dat de browser afhankelijk is van eigenaardigheden in het gedrag van specifieke apparaten.
Terminologie
HID bestaat uit twee basisconcepten: rapporten en rapportdescriptoren. Rapporten zijn de gegevens die worden uitgewisseld tussen een apparaat en een softwareclient. De rapportdescriptor beschrijft de indeling en betekenis van de gegevens die het apparaat ondersteunt.
Een HID (Human Interface Device) is een apparaat dat input van mensen ontvangt of output aan hen levert. Het verwijst ook naar het HID-protocol, een standaard voor bidirectionele communicatie tussen een host en een apparaat, ontworpen om de installatieprocedure te vereenvoudigen. Het HID-protocol werd oorspronkelijk ontwikkeld voor USB-apparaten, maar is sindsdien geïmplementeerd in vele andere protocollen, waaronder Bluetooth.
Toepassingen en HID-apparaten wisselen binaire gegevens uit via drie rapporttypen:
Rapporttype | Beschrijving |
---|---|
Invoerrapport | Gegevens die van het apparaat naar de applicatie worden verzonden (bijvoorbeeld als er op een knop wordt gedrukt). |
Uitvoerrapport | Gegevens die door de applicatie naar het apparaat worden verzonden (bijvoorbeeld een verzoek om de toetsenbordverlichting in te schakelen.) |
Functieverslag | Gegevens die in beide richtingen kunnen worden verzonden. Het formaat is apparaatspecifiek. |
Een rapportdescriptor beschrijft de binaire indeling van rapporten die door het apparaat worden ondersteund. De structuur is hiërarchisch en kan rapporten groeperen als afzonderlijke verzamelingen binnen de hoogste verzameling. De indeling van de descriptor wordt gedefinieerd door de HID-specificatie.
Een HID-gebruik is een numerieke waarde die verwijst naar een gestandaardiseerde invoer of uitvoer. Met gebruikswaarden kan een apparaat het beoogde gebruik ervan en het doel van elk veld in zijn rapporten beschrijven. Er wordt bijvoorbeeld één waarde gedefinieerd voor de linkermuisknop. Gebruik wordt ook georganiseerd in gebruikspagina's, die een indicatie geven van de hoofdcategorie van het apparaat of rapport.
De WebHID API gebruiken
Functiedetectie
Om te controleren of de WebHID API wordt ondersteund, gebruikt u:
if ("hid" in navigator) {
// The WebHID API is supported.
}
Een HID-verbinding openen
De WebHID API is asynchroon ontworpen om te voorkomen dat de gebruikersinterface van de website blokkeert tijdens het wachten op invoer. Dit is belangrijk omdat HID-gegevens op elk moment kunnen worden ontvangen, wat een manier vereist om ernaar te luisteren.
Om een HID-verbinding te openen, moet u eerst een HIDDevice
object benaderen. Hiervoor kunt u de gebruiker vragen een apparaat te selecteren door navigator.hid.requestDevice()
aan te roepen, of er een kiezen via navigator.hid.getDevices()
, dat een lijst retourneert met apparaten waartoe de website eerder toegang heeft gekregen.
De functie navigator.hid.requestDevice()
accepteert een verplicht object dat filters definieert. Deze worden gebruikt om elk apparaat te matchen dat is verbonden met een USB-leveranciers-ID ( vendorId
), een USB-product-ID ( productId
), een gebruikspaginawaarde ( usagePage
) en een gebruikswaarde ( usage
). U kunt deze vinden in de USB ID Repository en het document met HID-gebruikstabellen .
De verschillende HIDDevice
objecten die door deze functie worden geretourneerd, vertegenwoordigen meerdere HID-interfaces op hetzelfde fysieke apparaat.
// Filter on devices with the Nintendo Switch Joy-Con USB Vendor/Product IDs.
const filters = [
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2006 // Joy-Con Left
},
{
vendorId: 0x057e, // Nintendo Co., Ltd
productId: 0x2007 // Joy-Con Right
}
];
// Prompt user to select a Joy-Con device.
const [device] = await navigator.hid.requestDevice({ filters });
// Get all devices the user has previously granted the website access to.
const devices = await navigator.hid.getDevices();

U kunt ook de optionele sleutel exclusionFilters
in navigator.hid.requestDevice()
gebruiken om bepaalde apparaten waarvan u weet dat ze niet goed functioneren, uit te sluiten van de browserkiezer.
// Request access to a device with vendor ID 0xABCD. The device must also have
// a collection with usage page Consumer (0x000C) and usage ID Consumer
// Control (0x0001). The device with product ID 0x1234 is malfunctioning.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0xabcd, usagePage: 0x000c, usage: 0x0001 }],
exclusionFilters: [{ vendorId: 0xabcd, productId: 0x1234 }],
});
Een HIDDevice
object bevat USB-leveranciers- en product-ID's voor apparaatidentificatie. Het collections
wordt geïnitialiseerd met een hiërarchische beschrijving van de rapportindelingen van het apparaat.
for (let collection of device.collections) {
// An HID collection includes usage, usage page, reports, and subcollections.
console.log(`Usage: ${collection.usage}`);
console.log(`Usage page: ${collection.usagePage}`);
for (let inputReport of collection.inputReports) {
console.log(`Input report: ${inputReport.reportId}`);
// Loop through inputReport.items
}
for (let outputReport of collection.outputReports) {
console.log(`Output report: ${outputReport.reportId}`);
// Loop through outputReport.items
}
for (let featureReport of collection.featureReports) {
console.log(`Feature report: ${featureReport.reportId}`);
// Loop through featureReport.items
}
// Loop through subcollections with collection.children
}
De HIDDevice
-apparaten worden standaard in een gesloten toestand geretourneerd en moeten worden geopend door open()
aan te roepen voordat er gegevens kunnen worden verzonden of ontvangen.
// Wait for the HID connection to open before sending/receiving data.
await device.open();
Ontvang invoerrapporten
Zodra de HID-verbinding tot stand is gebracht, kunt u inkomende invoerrapporten verwerken door te luisteren naar de "inputreport"
-gebeurtenissen van het apparaat. Deze gebeurtenissen bevatten de HID-gegevens als een DataView
object ( data
), het HID-apparaat waartoe het behoort ( device
) en de 8-bits rapport-ID die aan het invoerrapport is gekoppeld ( reportId
).

Als we verdergaan met het vorige voorbeeld, laat de onderstaande code zien hoe je kunt detecteren welke knop de gebruiker op een Joy-Con Right-apparaat heeft ingedrukt, zodat je het hopelijk thuis kunt uitproberen.
device.addEventListener("inputreport", event => {
const { data, device, reportId } = event;
// Handle only the Joy-Con Right device and a specific report ID.
if (device.productId !== 0x2007 && reportId !== 0x3f) return;
const value = data.getUint8(0);
if (value === 0) return;
const someButtons = { 1: "A", 2: "X", 4: "B", 8: "Y" };
console.log(`User pressed button ${someButtons[value]}.`);
});
Bekijk de Pen webhid-joycon-button demo.
Uitvoerrapporten verzenden
Om een uitvoerrapport naar een HID-apparaat te verzenden, geeft u de 8-bits rapport-ID die aan het uitvoerrapport is gekoppeld ( reportId
) en bytes als BufferSource
( data
) door aan device.sendReport()
. De geretourneerde promise wordt verwerkt zodra het rapport is verzonden. Als het HID-apparaat geen rapport-ID's gebruikt, stelt u reportId
in op 0.
Het onderstaande voorbeeld is van toepassing op een Joy-Con-apparaat en toont hoe u het apparaat kunt laten trillen, met uitvoerrapporten.
// First, send a command to enable vibration.
// Magical bytes come from https://github.com/mzyy94/joycon-toolweb
const enableVibrationData = [1, 0, 1, 64, 64, 0, 1, 64, 64, 0x48, 0x01];
await device.sendReport(0x01, new Uint8Array(enableVibrationData));
// Then, send a command to make the Joy-Con device rumble.
// Actual bytes are available in the sample below.
const rumbleData = [ /* ... */ ];
await device.sendReport(0x10, new Uint8Array(rumbleData));
Bekijk de Pen webhid-joycon-rumble demo.
Functierapporten verzenden en ontvangen
Functierapporten zijn het enige type HID-gegevensrapporten dat in beide richtingen kan worden verzonden. Ze stellen HID-apparaten en -applicaties in staat om niet-gestandaardiseerde HID-gegevens uit te wisselen. In tegenstelling tot invoer- en uitvoerrapporten worden functierapporten niet regelmatig door de applicatie ontvangen of verzonden.

Om een functierapport naar een HID-apparaat te verzenden, geeft u de 8-bits rapport-ID die aan het functierapport is gekoppeld ( reportId
) en bytes als BufferSource
( data
) door aan device.sendFeatureReport()
. De geretourneerde promise wordt verwerkt zodra het rapport is verzonden. Als het HID-apparaat geen rapport-ID's gebruikt, stelt u reportId
in op 0.
Het onderstaande voorbeeld illustreert het gebruik van functie-rapporten door te laten zien hoe u een Apple-toetsenbord met achtergrondverlichting kunt aanvragen, het kunt openen en het kunt laten knipperen.
const waitFor = duration => new Promise(r => setTimeout(r, duration));
// Prompt user to select an Apple Keyboard Backlight device.
const [device] = await navigator.hid.requestDevice({
filters: [{ vendorId: 0x05ac, usage: 0x0f, usagePage: 0xff00 }]
});
// Wait for the HID connection to open.
await device.open();
// Blink!
const reportId = 1;
for (let i = 0; i < 10; i++) {
// Turn off
await device.sendFeatureReport(reportId, Uint32Array.from([0, 0]));
await waitFor(100);
// Turn on
await device.sendFeatureReport(reportId, Uint32Array.from([512, 0]));
await waitFor(100);
}
Bekijk de Pen webhid-apple-keyboard-backlight demo.
Om een functierapport van een HID-apparaat te ontvangen, geeft u de 8-bits rapport-ID die aan het functierapport is gekoppeld ( reportId
) door aan device.receiveFeatureReport()
. De geretourneerde promise wordt omgezet in een DataView
object dat de inhoud van het functierapport bevat. Als het HID-apparaat geen rapport-ID's gebruikt, stelt u reportId
in op 0.
// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);
// Read feature report contents with dataView.getInt8(), getUint8(), etc...
Luister naar verbinding en ontkoppeling
Wanneer de website toestemming heeft gekregen om toegang te krijgen tot een HID-apparaat, kan deze actief verbindings- en verbindingsverbrekingsgebeurtenissen ontvangen door te luisteren naar "connect"
en "disconnect"
gebeurtenissen.
navigator.hid.addEventListener("connect", event => {
// Automatically open event.device or warn user a device is available.
});
navigator.hid.addEventListener("disconnect", event => {
// Remove |event.device| from the UI.
});
Toegang tot een HID-apparaat intrekken
De website kan de rechten voor toegang tot een HID-apparaat dat het niet langer wil behouden, opschonen door forget()
aan te roepen op de HIDDevice
instantie. Bijvoorbeeld, voor een educatieve webapplicatie die wordt gebruikt op een gedeelde computer met meerdere apparaten, zorgt een groot aantal verzamelde, door de gebruiker gegenereerde rechten voor een slechte gebruikerservaring.
Als u forget()
aanroept op één HIDDevice
instantie, wordt de toegang tot alle HID-interfaces op hetzelfde fysieke apparaat ingetrokken.
// Voluntarily revoke access to this HID device.
await device.forget();
Omdat forget()
beschikbaar is in Chrome 100 of later, controleer of deze functie wordt ondersteund met het volgende:
if ("hid" in navigator && "forget" in HIDDevice.prototype) {
// forget() is supported.
}
Ontwikkelaarstips
U kunt HID's eenvoudig debuggen in Chrome via de interne pagina about://device-log
Daar ziet u alle gebeurtenissen met betrekking tot HID en USB-apparaten op één plek.

Bekijk de HID-explorer om HID-apparaatgegevens in een voor mensen leesbaar formaat te dumpen. Deze functie koppelt gebruikswaarden aan namen voor elk HID-gebruik.
Op de meeste Linux-systemen worden HID-apparaten standaard toegewezen met alleen-lezenrechten. Om Chrome een HID-apparaat te laten openen, moet u een nieuwe udev-regel toevoegen. Maak een bestand aan in /etc/udev/rules.d/50-yourdevicename.rules
met de volgende inhoud:
KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
In de bovenstaande regel is [yourdevicevendor]
057e
als je apparaat bijvoorbeeld een Nintendo Switch Joy-Con is. ATTRS{idProduct}
kan ook worden toegevoegd voor een specifiekere regel. Zorg ervoor dat je user
lid is van de plugdev
groep. Sluit je apparaat vervolgens opnieuw aan.
Browserondersteuning
De WebHID API is beschikbaar op alle desktopplatforms (ChromeOS, Linux, macOS en Windows) in Chrome 89.
Demo's
Enkele WebHID-demo's staan vermeld op web.dev/hid-examples . Neem eens een kijkje!
Beveiliging en privacy
De auteurs van de specificaties hebben de WebHID API ontworpen en geïmplementeerd met behulp van de kernprincipes die zijn gedefinieerd in 'Toegang tot krachtige webplatformfuncties beheren' , waaronder gebruikerscontrole, transparantie en ergonomie. De mogelijkheid om deze API te gebruiken, wordt primair beperkt door een toestemmingsmodel dat toegang verleent tot slechts één HID-apparaat tegelijk. Naar aanleiding van een prompt van de gebruiker moet de gebruiker actieve stappen ondernemen om een specifiek HID-apparaat te selecteren.
Raadpleeg het gedeelte Beveiligings- en privacyoverwegingen van de WebHID-specificatie voor meer informatie over de beveiligingsafwegingen.
Bovendien controleert Chrome het gebruik van elke collectie op het hoogste niveau. Als een collectie op het hoogste niveau een beschermd gebruik heeft (bijvoorbeeld een algemeen toetsenbord of muis), kan een website geen rapporten verzenden en ontvangen die in die collectie zijn gedefinieerd. De volledige lijst met beschermd gebruik is openbaar beschikbaar .
Houd er rekening mee dat beveiligingsgevoelige HID-apparaten (zoals FIDO HID-apparaten die worden gebruikt voor sterkere authenticatie) ook worden geblokkeerd in Chrome. Zie de USB-blokkeerlijst en HID-blokkeerlijstbestanden .
Feedback
Het Chrome-team hoort graag uw mening en ervaringen met de WebHID API.
Vertel ons over het API-ontwerp
Werkt er iets in de API niet zoals verwacht? Of ontbreken er methoden of eigenschappen die u nodig hebt om uw idee te implementeren?
Dien een spec-probleem in op de WebHID API GitHub-repository of voeg uw mening toe over een bestaand probleem.
Meld een probleem met de implementatie
Heb je een bug gevonden in de implementatie van Chrome? Of wijkt de implementatie af van de specificatie?
Bekijk Hoe u WebHID-bugs kunt melden . Zorg ervoor dat u zoveel mogelijk details verstrekt, eenvoudige instructies geeft voor het reproduceren van de bug en dat Componenten zijn ingesteld op Blink>HID
.
Toon steun
Bent u van plan de WebHID API te gebruiken? Uw publieke steun helpt het Chrome-team bij het prioriteren van functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.
Stuur een tweet naar @ChromiumDev met de hashtag #WebHID
en laat ons weten waar en hoe je deze gebruikt.
Nuttige links
- Specificatie
- Tracking-bug
- ChromeStatus.com-vermelding
- Knippercomponent:
Blink>HID
Dankbetuigingen
Met dank aan Matt Reynolds en Joe Medley voor hun recensies van dit artikel. Foto van de rood-blauwe Nintendo Switch door Sara Kurfeß , en een zwart-zilveren laptop door Athul Cyriac Ajay op Unsplash.