打造支援 WebUSB 的裝置

打造可充分運用 WebUSB API 的裝置。

本文說明如何打造可充分運用 WebUSB API。如需 API 本身的簡介,請參閱「存取 USB 裝置」 。

背景

通用串列匯流排 (USB) 已成為 Google Cloud 將週邊裝置連線至電腦和行動運算裝置。除了 定義公車的電動特性 以及一般模型 USB 規格包括一組裝置類別 規格。這些是適用於特定裝置類型的一般模型, 例如儲存空間、音訊、影片和網路等 這些裝置類別規格的優點是 作業系統廠商可以根據 類別實作單一驅動程式 規格 (「類別驅動程式」),以及所有實作該類別的裝置都會 支援。對所有需要編寫程式碼的製造商來說 為開發人員

然而,有些裝置並不屬於任一標準化裝置類別。A 罩杯 製造商可選擇將自家裝置標示為 特定供應商課程在此情況下,作業系統會選擇 根據供應商驅動程式套件中提供的資訊進行載入的驅動程式, 通常也是一組已知會導入 各供應商專用的通訊協定

USB 的另一項功能是,裝置可能會為 保持連線狀態每個介面均可實作 標準化類別或供應商專屬作業系統選擇 不同介面都能聲明各項介面對應的正確驅動程式 驅動程式庫。舉例來說,USB 網路攝影機通常提供兩種介面 實作 USB 影片類別 (適用於攝影機),另一個實作 USB 裝置 音訊類別 (適用於麥克風)。作業系統不會載入一個 "網路攝影機驅動程式"但會載入獨立的影片和語音類別驅動程式 這些程式碼會負責裝置的個別功能這個 介面類別組合提供更高的彈性。

API 基本資訊

許多標準 USB 類別都有對應的網路 API。舉例來說 頁面可以使用 getUserMedia() 從視訊課程裝置擷取影片 或是透過監聽器,從人工介面 (HID) 類別裝置接收輸入事件 適用於 KeyboardEventsPointerEvents,或使用 遊戲手把WebHID API。 並非所有裝置都會實作標準化類別定義 裝置會實作與現有網路平台 API 相對應的功能。時間 在此情況下,WebUSB API 可以藉由提供網站的方式來填補此缺口 聲明供應商專屬介面,並直接從該介面導入相關支援 頁面顯示的內容

透過 WebUSB 存取裝置具體的規定略有不同 因為作業系統管理 USB 的方式不同 不過基本需求是,裝置本身並不會有 驅動程式。可以是 一般類別驅動程式:OS 廠商或 即可。由於 USB 裝置可提供多個介面,且每個介面都可能 有專屬驅動程式,就能打造支援某些介面的裝置 ,而其他人則可透過瀏覽器存取。

舉例來說,高階 USB 鍵盤可提供 HID 類別介面, 作業系統的輸入子系統及供應商特有聲明的所有聲明 WebUSB 仍可供設定工具使用的介面。這個 這個工具可以在製造商網站上提供,讓使用者變更 例如微距鍵和打光效果等裝置行為的控制因素 安裝任何平台專屬軟體。這類裝置的設定描述元 如下所示:

欄位 說明
設定描述元
0x09 bLength 此描述元的大小
0x02 bDescriptorType 設定描述元
0x0039 wTotalLength 這一系列描述元的總長度
0x02 bNumInterfaces 介面數量
0x01 bConfigurationValue Configuration 1
0x00 iConfiguration 設定名稱 (無)
0b1010000 bmAttributes 自主裝置與遠端喚醒
0x32 bMaxPower 最大功率以 2 mA 為單位表示
介面描述元
0x09 bLength 此描述元的大小
0x04 bDescriptorType 介面描述元
0x00 bInterfaceNumber 介面 0
0x00 bAlternateSetting 替代設定 0 (預設)
0x01 bNumEndpoints 1 個端點
0x03 bInterfaceClass HID 介面類別
0x01 bInterfaceSubClass 啟動介面子類別
0x01 bInterfaceProtocol 鍵盤
0x00 iInterface 介面名稱 (無)
HID 描述元
0x09 bLength 此描述元的大小
0x21 bDescriptorType HID 描述元
0x0101 bcdHID HID 1.1 版
0x00 bCountryCode 硬體指定國家/地區
0x01 bNumDescriptors 要追蹤的 HID 類別描述元數量
0x22 bDescriptorType 報表描述元類型
0x003F wDescriptorLength 報表描述元的總長度
端點描述元
0x07 bLength 此描述元的大小
0x05 bDescriptorType 端點描述元
0b10000001 bEndpointAddress 端點 1 (印度)
0b00000011 bmAttributes 中斷
0x0008 wMaxPacketSize 8 位元組封包
0x0A bInterval 間隔 10 毫秒
介面描述元
0x09 bLength 此描述元的大小
0x04 bDescriptorType 介面描述元
0x01 bInterfaceNumber 介面 1
0x00 bAlternateSetting 替代設定 0 (預設)
0x02 bNumEndpoints 2 個端點
0xFF bInterfaceClass 供應商專屬的介面類別
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface 介面名稱 (無)
端點描述元
0x07 bLength 此描述元的大小
0x05 bDescriptorType 端點描述元
0b10000010 bEndpointAddress 端點 1 (印度)
0b00000010 bmAttributes 大量
0x0040 wMaxPacketSize 64 位元組封包
0x00 bInterval 不適用於大量端點
端點描述元
0x07 bLength 此描述元的大小
0x05 bDescriptorType 端點描述元
0b00000011 bEndpointAddress 端點 3 (OUT)
0b00000010 bmAttributes 大量
0x0040 wMaxPacketSize 64 位元組封包
0x00 bInterval 不適用於大量端點

設定描述元包含多個串連的描述元 。每個欄位都以 bLengthbDescriptorType 欄位開頭,方便 。第一個介面是 HID 介面, HID 描述元以及單一端點,用來將輸入事件傳送至 以及作業系統第二個是供應商專屬的介面, 可用來將指令傳送至裝置及接收回應的端點 傳回的結果。

WebUSB 描述元

WebUSB 雖適用於多種裝置,不需手動修改韌體, 標示裝置時, 說明 WebUSB 支援的描述元。舉例來說,您可以指定 到達網頁網址,瀏覽器將使用者導向 已接上電源。

Chrome 中 WebUSB 通知的螢幕截圖
WebUSB 通知

二進位裝置物件存放區 (BOS) 是 USB 3.0 中引進的概念,但 作為 2.1 版本的一部分 也向後移植到 USB 2.0 裝置宣告 WebUSB 支援一開始包含下列平台功能 BOS 描述元中的描述元:

欄位 說明
二進位裝置物件存放區描述元
0x05 bLength 此描述元的大小
0x0F bDescriptorType 二進位裝置物件存放區描述元
0x001D wTotalLength 這一系列描述元的總長度
0x01 bNumDeviceCaps BOS 中的裝置功能描述元數量
WebUSB 平台功能描述元
0x18 bLength 此描述元的大小
0x10 bDescriptorType 裝置功能描述元
0x05 bDevCapabilityType 平台功能描述元
0x00 bReserved
{0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, 0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} PlatformCapablityUUID WebUSB 平台功能描述元 GUID (小端格式)
0x0100 bcdVersion WebUSB 描述元 1.0 版
0x01 bVendorCode WebUSB 的 bRequest 值
0x01 iLandingPage 到達網頁網址

平台功能 UUID 識別為 WebUSB 平台功能 描述元,可提供裝置的基本資訊。瀏覽器專區 針對使用 bVendorCode 值的裝置擷取更多相關資訊, 向裝置發出更多要求。目前所指定的唯一要求是 GET_URL,這會傳回網址描述元。這些字元與字串類似 描述元的情形,主要是在最少位元組中對網址進行編碼。網址 "https://google.com" 的描述元看起來會像這樣:

欄位 說明
網址描述元
0x0D bLength 此描述元的大小
0x03 bDescriptorType 網址描述元
0x01 bScheme https://
"google.com" 網址 UTF-8 編碼網址內容

當裝置首次插入瀏覽器時,系統會讀取 BOS 描述元 ( 發出這個標準 GET_DESCRIPTOR 控制移轉作業:

bmRequestType bRequest wValue wIndex wLength 資料 (回應)
0b10000000 0x06 0x0F00 0x0000 * BOS 描述元

這項要求通常會發出兩次,第一次是大小夠大的 wLength 以便主機找出 wTotalLength 欄位的值 發布至大型傳輸,並在完整的描述元長度為 目前已知

如果 WebUSB 平台功能描述元的 iLandingPage 欄位設為 瀏覽器設為非零的值,然後執行 WebUSB 專屬 GET_URL 要求 透過發出控制移轉作業,並將 bRequest 設為 bVendorCode 值。 從平台功能描述元並將 wValue 設定為 iLandingPage 值。GET_URL (0x02) 的要求代碼來自 wIndex

bmRequestType bRequest wValue wIndex wLength 資料 (回應)
0b11000000 0x01 0x0001 0x0002 * 網址描述元

再次提醒,為了初次探測長度,可能會發出兩次這項要求 所讀取的描述元

特定平台注意事項

WebUSB API 會嘗試提供一致的存取介面 USB 裝置的開發人員仍應留意先前 才能存取裝置。

macOS

macOS 不需要任何特殊設定。使用 WebUSB 的網站可連線至 並聲明任何介面皆未由核心驅動程式聲明擁有權,或 或其他應用程式。

Linux

Linux 與 macOS 類似,但根據預設,大多數發行版並未設定使用者 有權開啟 USB 裝置的帳戶。名為 udev 的系統 Daemon 負責為使用者和群組指派可存取裝置的權限。一項規則 如此一來,系統就會指派與指定廠商相符的裝置擁有權, 產品 ID 加入 plugdev 群組,這是具存取權的使用者通用群組 適用於週邊裝置:

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

XXXX 替換為裝置的十六進位供應商 ID 和產品 ID。 例如:「ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e11"」會與 Nexus One 相符 電話。不得以一般的「0x」寫成前置字元和全部小寫 例如文字如要尋找裝置的 ID,請執行指令列 工具 lsusb

這項規則應置於 /etc/udev/rules.d 目錄中的檔案中,且 會在裝置插上電源後立即生效。因此不需要重新啟動 udev。

Android

Android 平台以 Linux 為基礎,但不需修改 系統設定根據預設,未建構驅動程式的裝置 才能使用瀏覽器。開發人員 但請注意,使用者在連線至網路時 裝置。使用者選取裝置以回應 requestDevice(),Android 會顯示提示,詢問是否允許 使用 Chrome 存取如果使用者返回網站,這個提示也會再次顯示 已具備連線至裝置和網站通話的權限 open()

此外,在 Android 上存取的裝置數量比電腦 Linux 還多 因為預設納入的司機較少明顯的遺漏情形,例如 是 USB CDC-ACM 類別,通常由 USB 對序列轉接器實作 Android SDK 中沒有用於與序列裝置通訊的 API。

ChromeOS

ChromeOS 同樣以 Linux 為建構基礎,因此不需要進行任何修改 轉換至系統設定permissions_broker 服務控制 USB 存取權 並且允許瀏覽器存取這些內容,前提是 一個無人認領的介面

Windows

Windows 驅動程式模型包含一項額外需求。與 使用者應用程式開啟 USB 裝置的能力上, 預設值,即使沒有載入驅動程式也一樣。而是指定 WinUSB 驅動程式,如要提供介面,則需載入 存取裝置所用的應用程式。方法是使用 系統上安裝的驅動程式資訊檔案 (INF),或修改裝置 提供 Microsoft OS 相容性描述元 列舉。

駕駛資訊檔案 (INF)

驅動程式資訊檔案會指示 Windows 遇到裝置時應採取什麼動作 因為我們的遊戲 在 2010 年間脫穎而出由於使用者的系統已包含 WinUSB 驅動程式 只要設定所有必要的步驟,INF 檔案就能連結供應商和產品 ID 套用這項新的安裝規則以下檔案為基本範例。儲存到 使用 .inf 副檔名,來變更標有「X」的區段,然後對著 然後按一下「安裝」我們要使用相關內容選單

[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"

[Dev_AddReg] 區段會設定裝置的 DeviceInterfaceGUID 組合 裝置。每個裝置介面都必須有一個 GUID,應用程式才能 可透過 Windows API 找到裝置並進行連線。使用 New-Guid PowerShell cmdlet 或線上工具來產生隨機 GUID。

基於開發目的,Zadig 工具提供了一個簡單的介面 以 WinUSB 驅動程式取代為 USB 介面載入的驅動程式。

Microsoft OS 相容性描述元

上述的 INF 檔案方法非常麻煩,因為必須設定 讀取及寫入機器Windows 8.1 以上版本提供替代選項 使用自訂的 USB 描述元這些描述元 更新至 Windows 作業系統 通常包含在 INF 檔案中

設定 WebUSB 描述元後,即可輕鬆新增 Microsoft 的 OS 相容性描述元首先,請使用這個程式碼擴充 BOS 描述元 額外的平台功能描述元請務必更新 wTotalLength 以及 bNumDeviceCaps

欄位 說明
Microsoft OS 2.0 平台功能描述元
0x1C bLength 此描述元的大小
0x10 bDescriptorType 裝置功能描述元
0x05 bDevCapabilityType 平台功能描述元
0x00 bReserved
{0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} PlatformCapablityUUID Microsoft OS 2.0 平台相容性描述元 GUID,採用 Little-Endian 格式
0x06030000 dwWindowsVersion 最低相容 Windows 版本 (Windows 8.1)
0x00B2 wMSOSDescriptorSetTotalLength 描述元集的總長度
0x02 bMS_VendorCode bRequest 值,用於擷取進一步的 Microsoft 描述元
0x00 bAltEnumCode 裝置不支援替代列舉

與 WebUSB 描述元一樣,您必須挑選要使用的 bRequest 值 控制與這些描述元相關的移轉作業。在這個範例中 0x020x07,位於 wIndex 中是擷取 Microsoft OS 的指令 2.0 在裝置上進行描述元集。

bmRequestType bRequest wValue wIndex wLength 資料 (回應)
0b11000000 0x02 0x0000 0x0007 * MS OS 2.0 描述元集

USB 裝置可以有多個功能,因此描述元的第一個部分 組會說明下方與屬性相關聯的函式。 下方範例會設定複合裝置的介面 1。描述元 作業系統有兩項關於此介面的資訊相容的 ID 描述元可告知 Windows 此裝置與 WinUSB 相容 驅動程式庫。註冊資料庫屬性描述元的功能類似 上述 INF 範例的 [Dev_AddReg] 部分,將登錄屬性設為 為這個函式指派裝置介面 GUID。

欄位 說明
Microsoft OS 2.0 描述元集標頭
0x000A wLength 此描述元的大小
0x0000 wDescriptorType 描述元集標頭描述元
0x06030000 dwWindowsVersion 最低相容 Windows 版本 (Windows 8.1)
0x00B2 wTotalLength 描述元集的總長度
Microsoft OS 2.0 設定子集標頭
0x0008 wLength 此描述元的大小
0x0001 wDescriptorType 設定子集標頭說明
0x00 bConfigurationValue 套用至設定 1 (儘管設定已從 0 編入索引 從 1 開始建立索引)
0x00 bReserved 必須設為 0
0x00A8 wTotalLength 部分內容總長度 (包含這個標題)
Microsoft OS 2.0 函式子集標頭
0x0008 wLength 此描述元的大小
0x0002 wDescriptorType 函式子集標頭描述元
0x01 bFirstInterface 函式的第一個介面
0x00 bReserved 必須設為 0
0x00A0 wSubsetLength 部分內容總長度 (包含這個標題)
與 Microsoft OS 2.0 相容的 ID 描述元
0x0014 wLength 此描述元的大小
0x0003 wDescriptorType 相容 ID 描述元
"WINUSB\0\0" CompatibileID 填補至 8 個位元組的 ASCII 字串
"\0\0\0\0\0\0\0\0" SubCompatibleID 填補至 8 個位元組的 ASCII 字串
Microsoft OS 2.0 登錄屬性描述元
0x0084 wLength 此描述元的大小
0x0004 wDescriptorType 登錄屬性描述元
0x0007 wPropertyDataType REG_MULTI_SZ
0x002A wPropertyNameLength 房源名稱的長度
"DeviceInterfaceGUIDs\0" PropertyName 以 UTF-16LE 編碼的屬性名稱含空值結束字元
0x0050 wPropertyDataLength 屬性值的長度
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\0\0" PropertyData GUID 加上兩個以 UTF-16LE 編碼的空值結束字元

Windows 只會向裝置查詢這項資訊一次。如果裝置使用 未以有效的描述元回應,系統下次擷取 裝置已連線。Microsoft 已提供 USB 裝置登錄清單 項目,用於說明列舉裝置時建立的登錄檔項目。時間 測試 刪除為裝置建立的項目,強制 Windows 嘗試讀取 來覆寫描述元

詳情請參閱 Microsoft 的網誌文章,瞭解這些方法的使用方式 描述元

範例

實作包含 WebUSB 的 WebUSB 感知裝置程式碼範例 您可在下列專案中找到描述元與 Microsoft OS 描述元: