Créer un appareil pour WebUSB

Créez un appareil pour tirer pleinement parti de l'API WebUSB.

Cet article explique comment concevoir un appareil pour tirer pleinement parti des API WebUSB : Pour une brève présentation de l'API elle-même, voir Accéder aux appareils USB sur le Web.

Contexte

Le bus universel en série (USB) est devenu l'interface physique la plus courante pour la connexion de périphériques aux ordinateurs de bureau et aux appareils mobiles. En plus de définissant les caractéristiques électriques du bus et un modèle général communiquant avec un appareil, les spécifications USB incluent un ensemble de classes d'appareils caractéristiques techniques. Il s'agit de modèles généraux adaptés à des classes spécifiques d'appareils, comme le stockage, l'audio, la vidéo, les réseaux, etc. que les fabricants d'appareils peuvent mettre en œuvre. L'avantage de ces spécifications de classe d'appareil est qu'un du système d'exploitation peut implémenter un seul pilote en fonction de la classe (un "pilote de classe"), et tout appareil implémentant cette classe compatibles. C'était une grande amélioration par rapport à chaque fabricant qui avait besoin d'écrire leurs propres pilotes de périphérique.

Toutefois, certains appareils ne correspondent pas à l'une de ces classes standardisées. A le fabricant peut choisir d'étiqueter son appareil pour indiquer qu'il respecte spécifique au fournisseur. Dans ce cas, le système d'exploitation choisit l'appareil le pilote à charger en fonction des informations fournies dans le package de pilotes du fournisseur, généralement un ensemble d'identifiants de fournisseurs et de produits connus pour implémenter une un protocole spécifique spécifique au fournisseur.

Une autre caractéristique de l'USB est que les appareils peuvent fournir plusieurs interfaces pour l'hôte auquel ils sont connectés. Chaque interface peut mettre en œuvre soit standardisés ou être spécifique à un fournisseur. Lorsqu’un système d’exploitation choisit le les bons pilotes pour gérer l’appareil. Chaque interface peut être revendiquée par une pilote. Par exemple, une webcam USB fournit généralement deux interfaces, une implémentant la classe vidéo USB (pour la caméra) et l'autre mettant en œuvre la classe USB (pour le micro). Le système d'exploitation ne charge pas "pilote de webcam" mais charge des pilotes de classe audio et vidéo indépendants qui assurent les différentes fonctions de l'appareil. Ce la composition des classes d'interface offre une plus grande flexibilité.

Principes de base des API

De nombreuses classes USB standards ont des API Web correspondantes. Par exemple, un peut capturer une vidéo à partir d'un appareil de classe vidéo à l'aide de getUserMedia() ou recevoir des événements d'entrée depuis un appareil de classe HID (Human Interface) en écoutant pour les événements KeyboardEvents ou PointerEvents, ou à l'aide de la manette de jeu ou de la l'API WebHID. De la même manière, tous les appareils n'appliquent pas une définition de classe standardisée, les appareils mettent en œuvre des fonctionnalités qui correspondent aux API de plate-forme Web existantes. Quand ? c'est le cas, l'API WebUSB peut combler cette lacune en fournissant aux sites pour revendiquer une interface spécifique au fournisseur et en assurer la prise en charge directement sur leur page.

Les exigences spécifiques pour qu'un appareil soit accessible via WebUSB varient légèrement d’une plateforme à l’autre en raison des différences dans la façon dont les systèmes d’exploitation gèrent les clés USB d'appareils, mais l'exigence de base est qu'un appareil ne doit pas déjà avoir le conducteur revendiquant l'interface que la page souhaite contrôler. Il peut s'agir pilote de classe générique fourni par le fournisseur du système d’exploitation ou un pilote de périphérique fourni par le fournisseur. Comme les périphériques USB peuvent fournir plusieurs interfaces, chacune d’entre elles peut dispose de son propre pilote, il est possible de créer un périphérique pour lequel certaines interfaces sont revendiquées par un conducteur, tandis que les autres restent accessibles au navigateur.

Par exemple, un clavier USB haut de gamme peut fournir une interface de classe HID qui est revendiqué par le sous-système d'entrée du système d'exploitation interface qui reste disponible pour WebUSB pour être utilisée par un outil de configuration. Ce peut être proposé sur le site Web du fabricant, ce qui permet à l'utilisateur certains aspects du comportement de l'appareil, tels que les touches macro et les effets d'éclairage l’installation de tout logiciel spécifique à la plateforme. Le descripteur de configuration d'un tel appareil quelque chose comme ceci:

Valeur Champ Description
Descripteur de configuration
0x09 bLength Taille de ce descripteur
0x02 bDescriptorType Descripteur de configuration
0x0039 wTotalLength Longueur totale de cette série de descripteurs
0x02 bNumInterfaces Nombre d'interfaces
0x01 bConfigurationValue Configuration 1
0x00 iConfiguration Nom de la configuration (aucun)
0b1010000 bmAttributes Appareil autonome avec activation à distance
0x32 bMaxPower La puissance maximale est exprimée par incréments de 2 mA
Descripteur d'interface
0x09 bLength Taille de ce descripteur
0x04 bDescriptorType Descripteur d'interface
0x00 bInterfaceNumber Interface 0
0x00 bAlternateSetting Paramètre alternatif 0 (par défaut)
0x01 bNumEndpoints 1 point de terminaison
0x03 bInterfaceClass Classe d'interface HID
0x01 bInterfaceSubClass Sous-classe d'interface de démarrage
0x01 bInterfaceProtocol Clavier
0x00 iInterface Nom de l'interface (aucun)
Descripteur HID
0x09 bLength Taille de ce descripteur
0x21 bDescriptorType Descripteur HID
0x0101 bcdHID HID version 1.1
0x00 bCountryCode Pays cible du matériel
0x01 bNumDescriptors Nombre de descripteurs de classe HID à suivre
0x22 bDescriptorType Type de descripteur de rapport
0x003F wDescriptorLength Longueur totale du descripteur du rapport
Descripteur du point de terminaison
0x07 bLength Taille de ce descripteur
0x05 bDescriptorType Descripteur du point de terminaison
0b10000001 bEndpointAddress Point de terminaison 1 (Inde)
0b00000011 bmAttributes Interrompre
0x0008 wMaxPacketSize Paquets de 8 octets
0x0A bInterval Intervalle de 10 ms
Descripteur d'interface
0x09 bLength Taille de ce descripteur
0x04 bDescriptorType Descripteur d'interface
0x01 bInterfaceNumber Interface 1
0x00 bAlternateSetting Paramètre alternatif 0 (par défaut)
0x02 bNumEndpoints 2 points de terminaison
0xFF bInterfaceClass Classe d'interface spécifique au fournisseur
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface Nom de l'interface (aucun)
Descripteur du point de terminaison
0x07 bLength Taille de ce descripteur
0x05 bDescriptorType Descripteur du point de terminaison
0b10000010 bEndpointAddress Point de terminaison 1 (Inde)
0b00000010 bmAttributes Modifications groupées
0x0040 wMaxPacketSize Paquets de 64 octets
0x00 bInterval N/A pour les points de terminaison groupés
Descripteur du point de terminaison
0x07 bLength Taille de ce descripteur
0x05 bDescriptorType Descripteur du point de terminaison
0b00000011 bEndpointAddress Point de terminaison 3 (OUT)
0b00000010 bmAttributes Modifications groupées
0x0040 wMaxPacketSize Paquets de 64 octets
0x00 bInterval N/A pour les points de terminaison groupés

Le descripteur de configuration est constitué de plusieurs descripteurs concaténés. ensemble. Chacune d'elles commence par les champs bLength et bDescriptorType. peut être identifié. La première interface est une interface HID associée un descripteur HID et un point de terminaison unique permettant de transmettre des événements d'entrée au système d'exploitation. La deuxième interface est spécifique au fournisseur points de terminaison permettant d'envoyer des commandes à l'appareil et de recevoir des réponses en retour.

Descripteurs WebUSB

Bien que WebUSB puisse fonctionner avec de nombreux appareils sans modification du micrologiciel, des fonctionnalités supplémentaires peuvent être activées en marquant l'appareil avec des de descripteurs indiquant la compatibilité avec WebUSB. Par exemple, vous pouvez spécifier un URL de la page de destination vers laquelle le navigateur peut rediriger l'utilisateur lorsque votre appareil branché.

<ph type="x-smartling-placeholder">
</ph> Capture d&#39;écran de la notification WebUSB dans Chrome
Notification WebUSB

Le magasin d’objets de périphérique binaire (BOS) est un concept introduit dans l’USB 3.0 mais il a ont également été rétroportés vers les appareils USB 2.0 dans la version 2.1. Déclaration La prise en charge de WebUSB commence par l'inclusion des fonctionnalités de plate-forme suivantes : Descripteur dans le descripteur BOS:

Valeur Champ Description
Descripteur du magasin d'objets de l'appareil binaire
0x05 bLength Taille de ce descripteur
0x0F bDescriptorType Descripteur du magasin d'objets de l'appareil binaire
0x001D wTotalLength Longueur totale de cette série de descripteurs
0x01 bNumDeviceCaps Nombre de descripteurs de capacité de l'appareil dans la BOS
Descripteur des fonctionnalités de la plate-forme WebUSB
0x18 bLength Taille de ce descripteur
0x10 bDescriptorType Descripteur des fonctionnalités de l'appareil
0x05 bDevCapabilityType Descripteur des fonctionnalités de la plate-forme
0x00 bReserved
{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} PlatformCapablityUUID GUID de descripteur des fonctionnalités de la plate-forme WebUSB au format Little-Endian
0x0100 bcdVersion Descripteur WebUSB version 1.0
0x01 bVendorCode Valeur bRequest pour WebUSB
0x01 iLandingPage URL de la page de destination

L'UUID de capacité de la plate-forme l'identifie comme une fonctionnalité de plate-forme WebUSB un descripteur qui fournit des informations de base sur l'appareil. Pour le navigateur Pour récupérer plus d'informations sur l'appareil, il utilise la valeur bVendorCode pour envoyer des requêtes supplémentaires à l'appareil. La seule requête actuellement spécifiée est GET_URL, qui renvoie un descripteur d'URL. Ceux-ci sont similaires aux chaînes mais ils sont conçus pour encoder les URL avec un minimum d'octets. Une URL le descripteur de "https://google.com" se présente comme suit:

Valeur Champ Description
Descripteur de l'URL
0x0D bLength Taille de ce descripteur
0x03 bDescriptorType Descripteur de l'URL
0x01 bScheme https://
"google.com" URL URL encodée en UTF-8

Lorsque votre appareil est branché pour la première fois, le navigateur lit le descripteur BOS par émettant ce transfert de contrôle GET_DESCRIPTOR standard:

bmRequestType bRequest wValue wIndex wLength Données (réponse)
0b10000000 0x06 0x0F00 0x0000 * Descripteur BOS

Cette demande est généralement effectuée deux fois, la première fois avec un wLength suffisamment volumineux afin que l'hôte trouve la valeur du champ wTotalLength sans effectuer un transfert volumineux, puis à nouveau lorsque la longueur totale du descripteur est est connue.

Si le champ iLandingPage du descripteur de capacité de la plate-forme WebUSB est défini sur Avec une valeur non nulle, le navigateur exécute ensuite une requête GET_URL spécifique à WebUSB En émettant un transfert de contrôle avec bRequest défini sur la valeur bVendorCode depuis le descripteur des fonctionnalités de la plate-forme, et wValue est défini sur iLandingPage . Le code de demande pour GET_URL (0x02) est dans wIndex:

bmRequestType bRequest wValue wIndex wLength Données (réponse)
0b11000000 0x01 0x0001 0x0002 * Descripteur d'URL

Encore une fois, cette demande peut être envoyée deux fois afin de vérifier d'abord la longueur du descripteur en cours de lecture.

Considérations propres aux plates-formes

Alors que l'API WebUSB tente de fournir une interface cohérente pour accéder Les développeurs de périphériques USB doivent toujours être conscients des exigences imposées aux applications, telles qu’un navigateur web, la configuration requise pour accéder aux appareils.

macOS

Rien de particulier n’est nécessaire pour macOS. Un site web utilisant WebUSB peut se connecter à le périphérique et de revendiquer toutes les interfaces qui ne sont pas revendiquées par un pilote de noyau ou une autre application.

Linux

Linux est semblable à macOS, mais par défaut, la plupart des distributions ne configurent pas les paramètres autorisés à ouvrir des périphériques USB. Un daemon système appelé udev est responsable de l'attribution de l'utilisateur et du groupe autorisé à accéder à un appareil. Une règle ce type d'appareil assignera la propriété d'un appareil correspondant au fournisseur donné et ID produit au groupe plugdev, qui est un groupe commun pour les utilisateurs ayant accès vers des périphériques:

SUBSYSTEM=="usb", ATTR{idVendor}=="XXXX", ATTR{idProduct}=="XXXX", GROUP="plugdev"

Remplacez XXXX par les ID hexadécimaux du fournisseur et des produits de votre appareil. Ex. : ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e11" correspondrait à un Nexus One. téléphone. Ils doivent être écrits sans le caractère "0x" habituel préfixe et tout en minuscules pour qu'il soit reconnu correctement. Pour trouver les ID de votre appareil, exécutez la ligne de commande Outil lsusb.

Placez cette règle dans un fichier du répertoire /etc/udev/rules.d et prend effet dès que l'appareil est branché. Il n'est pas nécessaire de redémarrer udev.

Android

La plate-forme Android est basée sur Linux, mais ne nécessite aucune modification pour configuration du système. Par défaut, tout appareil sans pilote intégré dans le système d'exploitation est accessible au navigateur. Les développeurs doivent être mais sachez que les utilisateurs devront effectuer une étape supplémentaire lorsqu'ils se connecteront l'appareil. Une fois qu'un utilisateur a sélectionné un appareil en réponse à un appel vers requestDevice(), Android affiche une invite vous demandant s'il faut autoriser Chrome pour y accéder. Cette invite réapparaît également si un utilisateur revient sur un site Web. ayant déjà l'autorisation de se connecter à un appareil et que le site Web appelle open()

De plus, davantage d'appareils seront accessibles sur Android que sur ordinateur Linux. car moins de pilotes sont inclus par défaut. Une omission notable, par exemple, est la classe USB CDC-ACM couramment implémentée par les adaptateurs USB vers série, car il existe le SDK Android ne permet pas de communiquer avec un appareil sériel.

ChromeOS

ChromeOS est également basé sur Linux et ne nécessite aucune modification. à la configuration du système. Le service permission_broker contrôle l'accès à la clé USB et permet au navigateur d'y accéder à condition qu'il y ait au moins une interface non revendiquée.

Windows

Le modèle de pilote Windows introduit une exigence supplémentaire. Contrairement au plates-formes au-dessus de la possibilité d'ouvrir un périphérique USB à partir d'une application utilisateur n'est pas par défaut, même si aucun pilote n'est chargé. À la place, il existe un WinUSB, qui doit être chargé pour fournir l’interface applications utilisent pour accéder à l’appareil. Pour ce faire, vous pouvez utiliser fichier d'informations sur le pilote (INF) installé sur le système ou en modifiant le périphérique afin de fournir les descripteurs de compatibilité du système d'exploitation Microsoft énumération.

Fichier d'informations sur le conducteur (INF)

Un fichier d’informations sur le pilote indique à Windows ce qu’il doit faire lorsqu’il rencontre un périphérique pour la première fois. Étant donné que le système de l’utilisateur inclut déjà le pilote WinUSB il suffit que le fichier INF associe votre fournisseur et l'identifiant produit avec cette nouvelle règle d'installation. Le fichier ci-dessous est un exemple basique. Enregistrez-le dans un comportant l'extension .inf, modifiez les sections marquées de "X", puis vers la droite cliquez dessus et choisissez « Installer » dans le menu contextuel.

[Version]
Signature   = "$Windows NT$"
Class       = USBDevice
ClassGUID   = {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider    = %ManufacturerName%
CatalogFile = WinUSBInstallation.cat
DriverVer   = 09/04/2012,13.54.20.543

; ========== Manufacturer/Models sections ===========

[Manufacturer]
%ManufacturerName% = Standard,NTx86,NTia64,NTamd64

[Standard.NTx86]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTia64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

[Standard.NTamd64]
%USB\MyCustomDevice.DeviceDesc% = USB_Install,USB\VID_XXXX&PID_XXXX

; ========== Class definition ===========

[ClassInstall32]
AddReg = ClassInstall_AddReg

[ClassInstall_AddReg]
HKR,,,,%ClassName%
HKR,,NoInstallClass,,1
HKR,,IconPath,%REG_MULTI_SZ%,"%systemroot%\system32\setupapi.dll,-20"
HKR,,LowerLogoVersion,,5.2

; =================== Installation ===================

[USB_Install]
Include = winusb.inf
Needs   = WINUSB.NT

[USB_Install.Services]
Include = winusb.inf
Needs   = WINUSB.NT.Services

[USB_Install.HW]
AddReg = Dev_AddReg

[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"

; =================== Strings ===================

[Strings]
ManufacturerName              = "Your Company Name Here"
ClassName                     = "Your Company Devices"
USB\MyCustomDevice.DeviceDesc = "Your Device Name Here"

La section [Dev_AddReg] configure l'ensemble d'identifiants DeviceInterfaceGUID pour le appareil. Chaque interface d'appareil doit avoir un GUID pour qu'une application puisse le trouver et s'y connecter via l'API Windows. Utiliser le PowerShell New-Guid cmdlet ou un outil en ligne pour générer un GUID aléatoire.

À des fins de développement, l'outil Zadig fournit une interface simple remplaçant le pilote chargé pour une interface USB par le pilote WinUSB.

Descripteurs de compatibilité de l'OS Microsoft

L'approche du fichier INF ci-dessus est fastidieuse car elle nécessite de configurer tous les la machine de l'utilisateur à l'avance. Windows 8.1 ou version ultérieure offre une alternative via l'utilisation de descripteurs USB personnalisés. Ces descripteurs fournissent des informations au système d'exploitation Windows lorsque l'appareil est branché pour la première fois, ce qui normalement inclus dans le fichier INF.

Une fois les descripteurs WebUSB configurés, vous pouvez facilement ajouter le système d'exploitation de Microsoft également des descripteurs de compatibilité. Commencez par étendre le descripteur BOS descripteur de capacité supplémentaire de la plate-forme. Veillez à mettre à jour wTotalLength et bNumDeviceCaps pour en tenir compte.

Valeur Champ Description
Descripteur des fonctionnalités de la plate-forme Microsoft OS 2.0
0x1C bLength Taille de ce descripteur
0x10 bDescriptorType Descripteur des fonctionnalités de l'appareil
0x05 bDevCapabilityType Descripteur des fonctionnalités de la plate-forme
0x00 bReserved
{0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} PlatformCapablityUUID Descripteur de compatibilité de la plate-forme Microsoft OS 2.0 GUID au format small-endian
0x06030000 dwWindowsVersion Version minimale compatible de Windows (Windows 8.1)
0x00B2 wMSOSDescriptorSetTotalLength Longueur totale de l'ensemble de descripteurs
0x02 bMS_VendorCode Valeur bRequest pour récupérer d'autres descripteurs Microsoft
0x00 bAltEnumCode L'appareil n'est pas compatible avec l'énumération alternative

Comme pour les descripteurs WebUSB, vous devez choisir une valeur bRequest à utiliser des transferts de contrôle liés à ces descripteurs. Dans cet exemple, j'ai choisi 0x02 0x07, placé dans wIndex, est la commande permettant de récupérer le système d'exploitation Microsoft 2.0 Ensemble de descripteurs à partir de l'appareil.

bmRequestType bRequest wValue wIndex wLength Données (réponse)
0b11000000 0x02 0x0000 0x0007 * Ensemble de descripteurs MS OS 2.0

Un périphérique USB peut avoir plusieurs fonctions, donc la première partie du descripteur décrit à quelle fonction les propriétés suivantes sont associées. La L'exemple ci-dessous configure l'interface 1 d'un appareil composite. Le descripteur donne deux informations importantes sur cette interface sur le système d’exploitation. Les Le descripteur d'ID indique à Windows que cet périphérique est compatible avec WinUSB pilote. Le descripteur de la propriété de registre fonctionne de la même manière que la section [Dev_AddReg] de l'exemple INF ci-dessus, en définissant une propriété de registre pour attribuer à cette fonction un GUID d'interface d'appareil.

Valeur Champ Description
En-tête d'ensemble de descripteurs Microsoft OS 2.0
0x000A wLength Taille de ce descripteur
0x0000 wDescriptorType Descripteur d'en-tête de l'ensemble de descripteurs
0x06030000 dwWindowsVersion Version minimale compatible de Windows (Windows 8.1)
0x00B2 wTotalLength Longueur totale de l'ensemble de descripteurs
En-tête du sous-ensemble de configuration Microsoft OS 2.0
0x0008 wLength Taille de ce descripteur
0x0001 wDescriptorType Description de l'en-tête du sous-ensemble de configuration
0x00 bConfigurationValue S'applique à la configuration 1 (indexée à partir de 0 malgré les configurations) normalement indexé à partir de 1)
0x00 bReserved Doit être défini sur 0
0x00A8 wTotalLength Longueur totale du sous-ensemble incluant cet en-tête
En-tête de sous-ensemble de fonctions Microsoft OS 2.0
0x0008 wLength Taille de ce descripteur
0x0002 wDescriptorType Descripteur d'en-tête de sous-ensemble de fonctions
0x01 bFirstInterface Première interface de la fonction
0x00 bReserved Doit être défini sur 0
0x00A0 wSubsetLength Longueur totale du sous-ensemble incluant cet en-tête
Descripteur d'ID compatible avec Microsoft OS 2.0
0x0014 wLength Taille de ce descripteur
0x0003 wDescriptorType Descripteur d'ID compatible
"WINUSB\0\0" CompatibileID Chaîne ASCII complétée de 8 octets
"\0\0\0\0\0\0\0\0" SubCompatibleID Chaîne ASCII complétée de 8 octets
Descripteur de propriété du registre Microsoft OS 2.0
0x0084 wLength Taille de ce descripteur
0x0004 wDescriptorType Descripteur de la propriété de registre
0x0007 wPropertyDataType REG_MULTI_SZ
0x002A wPropertyNameLength Longueur du nom de la propriété
"DeviceInterfaceGUIDs\0" PropertyName Nom de propriété avec un terminator nul encodé au format UTF-16LE
0x0050 wPropertyDataLength Longueur de la valeur de la propriété
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\0\0" PropertyData GUID plus deux terminateurs de valeur nulle codés en UTF-16LE

Windows n'interroge l'appareil qu'une seule fois pour obtenir ces informations. Si l'appareil ne répond pas avec des descripteurs valides, il ne posera plus la question la prochaine fois que le périphérique est connecté. Microsoft a fourni une liste de registres d'appareils USB Entrées décrivant les entrées de registre créées lors de l'énumération d'un appareil Quand ? test, supprimer les entrées créées pour un appareil pour forcer Windows à essayer de lire à nouveau les descripteurs.

Pour en savoir plus sur l'utilisation de ces fonctionnalités, consultez l'article de blog de Microsoft de descripteurs.

Exemples

Exemple de code pour implémenter des appareils compatibles WebUSB qui incluent à la fois WebUSB et les descripteurs de système d'exploitation Microsoft se trouvent dans les projets suivants: