Creazione di un dispositivo per WebUSB

Crea un dispositivo per sfruttare appieno l'API WebUSB.

Questo articolo spiega come realizzare un dispositivo per sfruttare al meglio API WebUSB. Per una breve introduzione all'API stessa, consulta Accesso a dispositivi USB sul web.

Sfondo

L'Universal Serial Bus (USB) è diventato l'interfaccia fisica più comune per collegare le periferiche ai dispositivi informatici e per dispositivi mobili. Oltre a definendo le caratteristiche elettriche dell'autobus e un modello generale per comunicano con un dispositivo, le specifiche USB includono un insieme di classi specifiche. Si tratta di modelli generali per particolari classi di dispositivi, come spazio di archiviazione, audio, video, networking ecc. che i produttori di dispositivi possono da implementare. Il vantaggio di queste specifiche delle classi di dispositivi è che il fornitore del sistema operativo può implementare un singolo driver in base alla classe specifiche (un "driver di classe") e qualsiasi dispositivo che implementa tale classe sarà supportati. Si tratta di un grande miglioramento rispetto a ogni produttore che doveva scrivere i propri driver di dispositivo.

Alcuni dispositivi, tuttavia, non rientrano in una di queste classi di dispositivi standardizzate. R il produttore può scegliere di etichettare il proprio dispositivo come l'implementazione e la classe specifica del fornitore. In questo caso è il sistema operativo a scegliere il dispositivo il conducente da caricare in base alle informazioni fornite nel pacchetto del driver del fornitore di solito un insieme di ID fornitore e prodotto che implementano un protocollo specifico del fornitore.

Un'altra caratteristica delle USB è che i dispositivi possono fornire più interfacce per l'host a cui sono connessi. Ogni interfaccia può implementare standardizzata o specifica del fornitore. Quando un sistema operativo sceglie i driver giusti per gestire il dispositivo; ciascuna interfaccia può essere conducente. Ad esempio, una webcam USB in genere fornisce due interfacce, una che implementa la classe video USB (per la videocamera) e una che implementa la classe USB audio (per il microfono). Il sistema operativo non carica "driver della webcam" ma carica driver di classe audio e video indipendenti che si assumono la responsabilità delle singole funzioni del dispositivo. Questo delle classi di interfaccia offre una maggiore flessibilità.

Nozioni di base sulle API

Molte classi USB standard hanno API web corrispondenti. Ad esempio, un pagina può acquisire video da un dispositivo di classe video utilizzando getUserMedia() o ricevere eventi di input da un dispositivo di classe HID (Human Interface) ascoltando per KeyboardEvents o PointerEvents oppure utilizzando il Gamepad o il API WebHID. Così come non tutti i dispositivi implementano una definizione di classe standardizzata, non tutti I dispositivi implementano funzionalità che corrispondono alle API delle piattaforme web esistenti. Quando In questo caso, l'API WebUSB può colmare questa lacuna fornendo ai siti richiedere un'interfaccia specifica del fornitore e implementarne il supporto direttamente all'interno della pagina.

I requisiti specifici per l'accessibilità di un dispositivo tramite WebUSB variano leggermente da una piattaforma all'altra a causa delle differenze nel modo in cui i sistemi operativi gestiscono le porte USB dispositivi mobili, ma il requisito di base è che un dispositivo non dovrebbe già disporre che dichiara l'interfaccia che la pagina vuole controllare. Potrebbe essere un driver di classe generico fornito dal fornitore del sistema operativo o driver di dispositivo fornito da il fornitore. I dispositivi USB possono fornire più interfacce, ognuna delle quali può avere un proprio driver, è possibile creare un dispositivo per il quale alcune interfacce vengono rivendicati da un conducente e altri vengono lasciati accessibili al browser.

Ad esempio, una tastiera USB di fascia alta può fornire un'interfaccia di classe HID verranno rivendicati dal sottosistema di input del sistema operativo e da un che rimane disponibile per WebUSB per l'utilizzo da parte di uno strumento di configurazione. Questo strumento può essere pubblicato sul sito web del produttore consentendo all'utente di modificare aspetti del comportamento del dispositivo, ad esempio i tasti macro ed effetti di luce senza installando software specifico della piattaforma. Il descrittore di configurazione di un dispositivo avrà un aspetto simile al seguente:

Valore Campo Descrizione
Descrittore di configurazione
0x09 bLength Dimensioni di questo descrittore
0x02 bDescriptorType Descrittore di configurazione
0x0039 wTotalLength Lunghezza totale di questa serie di descrittori
0x02 bNumInterfaces Numero di interfacce
0x01 bConfigurationValue Configurazione 1
0x00 iConfiguration Nome configurazione (nessuno)
0b1010000 bmAttributes Dispositivo autoalimentato con riattivazione remota
0x32 bMaxPower La potenza massima è espressa in incrementi di 2 mA
Descrittore dell'interfaccia
0x09 bLength Dimensioni di questo descrittore
0x04 bDescriptorType Descrittore dell'interfaccia
0x00 bInterfaceNumber Interfaccia 0
0x00 bAlternateSetting Impostazione alternativa 0 (impostazione predefinita)
0x01 bNumEndpoints 1 endpoint
0x03 bInterfaceClass Classe dell'interfaccia HID
0x01 bInterfaceSubClass Sottoclasse dell'interfaccia di avvio
0x01 bInterfaceProtocol Tastiera
0x00 iInterface Nome interfaccia (nessuno)
Descrittore HID
0x09 bLength Dimensioni di questo descrittore
0x21 bDescriptorType Descrittore HID
0x0101 bcdHID HID versione 1.1
0x00 bCountryCode Paese di destinazione hardware
0x01 bNumDescriptors Numero di descrittori classe HID da seguire
0x22 bDescriptorType Tipo di descrittore del report
0x003F wDescriptorLength Lunghezza totale del descrittore del report
Descrittore endpoint
0x07 bLength Dimensioni di questo descrittore
0x05 bDescriptorType Descrittore endpoint
0b10000001 bEndpointAddress Endpoint 1 (India)
0b00000011 bmAttributes Interrompi
0x0008 wMaxPacketSize Pacchetti da 8 byte
0x0A bInterval Intervallo di 10 ms
Descrittore dell'interfaccia
0x09 bLength Dimensioni di questo descrittore
0x04 bDescriptorType Descrittore dell'interfaccia
0x01 bInterfaceNumber Interfaccia 1
0x00 bAlternateSetting Impostazione alternativa 0 (impostazione predefinita)
0x02 bNumEndpoints 2 endpoint
0xFF bInterfaceClass Classe di interfaccia specifica del fornitore
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface Nome interfaccia (nessuno)
Descrittore endpoint
0x07 bLength Dimensioni di questo descrittore
0x05 bDescriptorType Descrittore endpoint
0b10000010 bEndpointAddress Endpoint 1 (India)
0b00000010 bmAttributes Collettivo
0x0040 wMaxPacketSize Pacchetti da 64 byte
0x00 bInterval N/D per endpoint collettivi
Descrittore endpoint
0x07 bLength Dimensioni di questo descrittore
0x05 bDescriptorType Descrittore endpoint
0b00000011 bEndpointAddress Endpoint 3 (OUT)
0b00000010 bmAttributes Collettivo
0x0040 wMaxPacketSize Pacchetti da 64 byte
0x00 bInterval N/D per endpoint collettivi

Il descrittore di configurazione è composto da più descrittori concatenati in sinergia. Ognuna inizia con i campi bLength e bDescriptorType in modo che identificabili. La prima interfaccia è un'interfaccia HID con un descrittore HID e un singolo endpoint utilizzato per consegnare eventi di input al un intero sistema operativo. La seconda è un'interfaccia specifica del fornitore con due endpoint che possono essere utilizzati per inviare comandi al dispositivo e ricevere risposte in cambio.

Descrittori WebUSB

Sebbene WebUSB possa funzionare con molti dispositivi senza modifiche firmware, le funzionalità aggiuntive vengono attivate contrassegnando il dispositivo con specifiche che indicano il supporto di WebUSB. Ad esempio, puoi specificare URL pagina di destinazione a cui il browser può indirizzare l'utente quando il tuo dispositivo è collegato alla corrente.

Screenshot della notifica WebUSB in Chrome
Notifica WebUSB.

Il Binary device Object Store (BOS) è un concetto introdotto in USB 3.0 ma ha anche stato retroportato su dispositivi USB 2.0 come parte della versione 2.1. Dichiarazione il supporto per WebUSB inizia con l'inclusione delle seguenti funzionalità della piattaforma Descrittore nel descrittore BOS:

Valore Campo Descrizione
Descrittore archivio oggetti dispositivo binario
0x05 bLength Dimensioni di questo descrittore
0x0F bDescriptorType Descrittore archivio oggetti dispositivo binario
0x001D wTotalLength Lunghezza totale di questa serie di descrittori
0x01 bNumDeviceCaps Numero di descrittori della funzionalità del dispositivo nel BOS
Descrittore della funzionalità della piattaforma WebUSB
0x18 bLength Dimensioni di questo descrittore
0x10 bDescriptorType Descrittore della funzionalità del dispositivo
0x05 bDevCapabilityType Descrittore della funzionalità della piattaforma
0x00 bReserved
{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} PlatformCapablityUUID GUID descrittore della funzionalità della piattaforma WebUSB in formato small-endian
0x0100 bcdVersion Descrittore WebUSB versione 1.0
0x01 bVendorCode Valore bRequest per WebUSB
0x01 iLandingPage URL della pagina di destinazione

L'UUID della funzionalità della piattaforma lo identifica come Funzionalità della piattaforma WebUSB descrittore, che fornisce informazioni di base sul dispositivo. Per il browser per recuperare ulteriori informazioni sul dispositivo per cui usa il valore bVendorCode inviare richieste aggiuntive al dispositivo. L'unica richiesta attualmente specificata è GET_URL che restituisce un descrittore URL. Sono simili alle stringhe ma sono progettati per codificare gli URL con il minor numero di byte. Un URL descrittore di "https://google.com" avrà il seguente aspetto:

Valore Campo Descrizione
Descrittore URL
0x0D bLength Dimensioni di questo descrittore
0x03 bDescriptorType Descrittore URL
0x01 bScheme https://
"google.com" URL Contenuti dell'URL con codifica UTF-8

Quando il dispositivo viene collegato per la prima volta al browser, legge il descrittore BOS che emette questo trasferimento di controllo GET_DESCRIPTOR standard:

bmRequestType bRequest wValue wIndex wLength Dati (risposta)
0b10000000 0x06 0x0F00 0x0000 * Il descrittore BOS

Questa richiesta viene generalmente effettuata due volte, la prima volta con un valore wLength sufficientemente grande in modo che l'host rilevi il valore del campo wTotalLength senza eseguendo un committente su un trasferimento di grandi dimensioni e poi di nuovo quando la lunghezza massima del descrittore noti.

Se il descrittore delle funzionalità della piattaforma WebUSB ha il campo iLandingPage impostato su un valore diverso da zero, il browser esegue quindi una richiesta GET_URL specifica per WebUSB eseguendo un trasferimento del controllo con il valore bRequest impostato sul valore bVendorCode dal descrittore della funzionalità della piattaforma e wValue impostato su iLandingPage valore. Il codice di richiesta per GET_URL (0x02) deve essere inserito in wIndex:

bmRequestType bRequest wValue wIndex wLength Dati (risposta)
0b11000000 0x01 0x0001 0x0002 * Il descrittore dell'URL

Anche in questo caso, questa richiesta può essere inviata due volte per verificare la durata del descrittore letto.

Considerazioni specifiche per la piattaforma

Mentre l'API WebUSB tenta di fornire un'interfaccia coerente per l'accesso Gli sviluppatori di dispositivi USB devono comunque essere a conoscenza dei requisiti imposti di applicazioni quali i requisiti dei browser web per accedere ai dispositivi.

macOS

Non è necessario nulla di speciale per macOS. Un sito web che utilizza WebUSB può collegarsi a il dispositivo e rivendicare le interfacce che non sono richieste da un driver kernel un'altra applicazione.

Linux

Linux è come macOS, ma per impostazione predefinita la maggior parte delle distribuzioni non configura account autorizzati ad aprire i dispositivi USB. Un daemon di sistema chiamato udev responsabile dell'assegnazione dell'utente e del gruppo a cui è consentito accedere a un dispositivo. Una regola come questa assegnerà la proprietà di un dispositivo corrispondente al fornitore specificato ID prodotto al gruppo plugdev, che è un gruppo comune per gli utenti con accesso alle periferiche:

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

Sostituisci XXXX con gli ID esadecimali del fornitore e del prodotto del tuo dispositivo, ad es. ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e11" corrisponde a un Nexus One telefono. Devono essere scritti senza il consueto valore "0x" prefisso e tutte minuscole vengano riconosciuti correttamente. Per trovare gli ID del tuo dispositivo, esegui la riga di comando strumento lsusb.

Questa regola deve essere inserita in un file nella directory /etc/udev/rules.d e hanno effetto non appena il dispositivo viene collegato. Non è necessario riavviare udev.

Android

La piattaforma Android è basata su Linux, ma non richiede alcuna modifica alle configurazione di sistema. Per impostazione predefinita, i dispositivi sprovvisti di driver integrato nel sistema operativo sono disponibili per il browser. Gli sviluppatori dovrebbero tuttavia, gli utenti dovranno eseguire un ulteriore passaggio quando si connetteranno del dispositivo. Una volta che un utente seleziona un dispositivo in risposta a una chiamata a requestDevice(), Android mostrerà un messaggio che chiede se consentire o meno Chrome per accedervi. La richiesta viene visualizzata di nuovo anche se un utente torna su un sito web. che dispone già dell'autorizzazione per connettersi a un dispositivo e alle chiamate dal sito web open()

Inoltre, saranno accessibili più dispositivi su Android che su computer Linux. perché per impostazione predefinita sono inclusi meno driver. Un'omissione notevole, ad esempio, è la classe USB CDC-ACM comunemente implementata dagli adattatori da USB a seriale non è un'API nell'SDK Android per comunicare con un dispositivo seriale.

ChromeOS

ChromeOS è basato anch'esso su Linux e non richiede alcuna modifica. alla configurazione del sistema. Il servizio permission_broker controlla l'accesso a USB dispositivi e consentirà al browser di accedervi purché ci siano almeno a un'interfaccia non rivendicata.

Windows

Il modello di driver Windows introduce un requisito aggiuntivo. A differenza del piattaforme che non consentono di aprire un dispositivo USB da un'applicazione utente non è per impostazione predefinita, anche se non è stato caricato alcun driver. C'è invece un'eccezione WinUSB, che deve essere caricato per fornire l'interfaccia utilizzate dalle applicazioni per accedere al dispositivo. Questa operazione può essere eseguita con una file con le informazioni del driver (INF) installato sul sistema o modificando il dispositivo per fornire i descrittori di compatibilità del sistema operativo Microsoft durante l'enumerazione.

File con informazioni sul conducente (INF)

Un file con le informazioni sul driver indica a Windows cosa fare quando rileva un dispositivo per la prima volta. Poiché il sistema dell'utente include già il driver WinUSB è sufficiente che il file INF associ il tuo fornitore e l'ID prodotto con questa nuova regola di installazione. Il file seguente è un esempio di base. Salvalo in un file con estensione .inf, modifica le sezioni contrassegnate con "X" e poi a destra fai clic sul pulsante e scegli "Installa" dal menu contestuale.

[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 sezione [Dev_AddReg] configura l'insieme di DeviceInterfaceGUID per il parametro dispositivo. Ogni interfaccia del dispositivo deve avere un GUID affinché un'applicazione individuarlo e connetterlo tramite l'API Windows. Utilizza New-Guid PowerShell cmdlet o uno strumento online per generare un GUID casuale.

Ai fini dello sviluppo, lo strumento Zadig offre un'interfaccia semplice per sostituendo il driver caricato per un'interfaccia USB con il driver WinUSB.

Descrittori di compatibilità del sistema operativo Microsoft

L’approccio con il file INF descritto sopra è complicato perché richiede la configurazione di ogni il computer dell'utente in anticipo. Windows 8.1 e versioni successive offrono un'alternativa tramite l'uso di descrittori USB personalizzati. Questi descrittori forniscono informazioni al sistema operativo Windows quando il dispositivo viene collegato per la prima volta. normalmente sono incluse nel file INF.

Una volta configurati i descrittori WebUSB è facile aggiungere il sistema operativo Microsoft di compatibilità. Innanzitutto, estendi il descrittore BOS con questo descrittore aggiuntivo di funzionalità della piattaforma. Assicurati di aggiornare wTotalLength e bNumDeviceCaps.

Valore Campo Descrizione
Descrittore delle funzionalità della piattaforma Microsoft OS 2.0
0x1C bLength Dimensioni di questo descrittore
0x10 bDescriptorType Descrittore della funzionalità del dispositivo
0x05 bDevCapabilityType Descrittore della funzionalità della piattaforma
0x00 bReserved
{0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} PlatformCapablityUUID GUID descrittore di compatibilità della piattaforma Microsoft OS 2.0 in formato small-endian
0x06030000 dwWindowsVersion Versione minima di Windows compatibile (Windows 8.1)
0x00B2 wMSOSDescriptorSetTotalLength Lunghezza totale dell'insieme di descrittori
0x02 bMS_VendorCode Valore bRequest per il recupero di altri descrittori Microsoft
0x00 bAltEnumCode Il dispositivo non supporta l'enumerazione alternativa

Come per i descrittori WebUSB devi scegliere un valore bRequest da utilizzare controllare i trasferimenti relativi a questi descrittori. In questo esempio ho scelto 0x02. 0x07, posizionato in wIndex, è il comando per recuperare il sistema operativo Microsoft 2.0 Descrittore impostato dal dispositivo.

bmRequestType bRequest wValue wIndex wLength Dati (risposta)
0b11000000 0x02 0x0000 0x0007 * Set di descrittori MS OS 2.0

Un dispositivo USB può avere più funzioni, quindi la prima parte del descrittore set descrive a quale funzione sono associate le proprietà che seguono. La L'esempio riportato di seguito configura l'interfaccia 1 di un dispositivo composito. Il descrittore fornisce due parti importanti di questa interfaccia. Il tipo di Il descrittore dell'ID indica a Windows che questo dispositivo è compatibile con l'interfaccia WinUSB conducente. Il descrittore della proprietà del registry funziona in modo simile Sezione [Dev_AddReg] dell'esempio INF precedente, che imposta una proprietà del registry su e assegnare a questa funzione un GUID dell'interfaccia del dispositivo.

Valore Campo Descrizione
Set di descrittori Microsoft OS 2.0 intestazione
0x000A wLength Dimensioni di questo descrittore
0x0000 wDescriptorType Descrittore impostato intestazione
0x06030000 dwWindowsVersion Versione minima di Windows compatibile (Windows 8.1)
0x00B2 wTotalLength Lunghezza totale dell'insieme di descrittori
Intestazione sottoinsieme configurazione Microsoft OS 2.0
0x0008 wLength Dimensioni di questo descrittore
0x0001 wDescriptorType Descrizione intestazione sottoinsieme configurazione
0x00 bConfigurationValue Si applica alla configurazione 1 (valore indicizzato da 0 nonostante le configurazioni) normalmente indicizzato da 1)
0x00 bReserved Deve essere impostato su 0
0x00A8 wTotalLength Lunghezza totale del sottoinsieme inclusa questa intestazione
Intestazione sottoinsieme funzioni Microsoft OS 2.0
0x0008 wLength Dimensioni di questo descrittore
0x0002 wDescriptorType Descrittore intestazione sottoinsieme funzione
0x01 bFirstInterface Prima interfaccia della funzione
0x00 bReserved Deve essere impostato su 0
0x00A0 wSubsetLength Lunghezza totale del sottoinsieme inclusa questa intestazione
Descrittore ID compatibile con Microsoft OS 2.0
0x0014 wLength Dimensioni di questo descrittore
0x0003 wDescriptorType Descrittore ID compatibile
"WINUSB\0\0" CompatibileID Stringa ASCII riempita fino a 8 byte
"\0\0\0\0\0\0\0\0" SubCompatibleID Stringa ASCII riempita fino a 8 byte
Descrittore della proprietà del registro di Microsoft OS 2.0
0x0084 wLength Dimensioni di questo descrittore
0x0004 wDescriptorType Descrittore proprietà del registry
0x0007 wPropertyDataType REG_MULTI_SZ
0x002A wPropertyNameLength Lunghezza del nome della struttura
"DeviceInterfaceGUIDs\0" PropertyName Nome proprietà con carattere di terminazione nullo codificato in UTF-16LE
0x0050 wPropertyDataLength Lunghezza del valore della proprietà
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\0\0" PropertyData GUID più due terminatori null codificati in UTF-16LE

Windows eseguirà una query sul dispositivo per ottenere queste informazioni solo una volta. Se il dispositivo non risponde con descrittori validi, non chiederà più la prossima volta è connesso. Microsoft ha fornito un elenco di registri dei dispositivi USB Voci che descrivono le voci del registro create durante l'enumerazione di un dispositivo. Quando test elimina le voci create per un dispositivo per forzare Windows a provare a leggere di nuovo i descrittori.

Per ulteriori informazioni, leggi il post del blog di Microsoft su come utilizzare questi descrittori.

Esempi

Codice di esempio che implementa dispositivi WebUSB che includono entrambi WebUSB descrittori e descrittori di Microsoft OS sono disponibili in questi progetti: