網站可透過 WebHID API 存取替代輔助鍵盤和特殊控制器。
人機介面裝置 (HID) 種類繁多,例如替代鍵盤或特殊遊戲手把,這些裝置可能太新、太舊或太罕見,系統的裝置驅動程式無法存取。WebHID API 解決了這個問題,提供在 JavaScript 中實作裝置專屬邏輯的方法。
建議用途
HID 裝置會接收或提供人為輸入/輸出內容。裝置範例包括鍵盤、指標裝置 (滑鼠、觸控螢幕等) 和遊戲手把。透過HID 通訊協定,您可以使用作業系統驅動程式,在桌上型電腦上存取這些裝置。網路平台會依賴這些驅動程式,支援 HID 裝置。
如果無法存取非標準 HID 裝置,對於替代輔助鍵盤 (例如 Elgato Stream Deck、Jabra 耳機、X-keys) 和特殊遊戲手把支援來說,特別令人困擾。專為桌機設計的遊戲手把通常會使用 HID 處理遊戲手把的輸入內容 (按鈕、搖桿、觸發鍵) 和輸出內容 (LED 燈、震動)。很抱歉,遊戲手把的輸入和輸出並未標準化,網頁瀏覽器通常需要針對特定裝置採用自訂邏輯。這無法長期維持,且會導致舊型和不常見裝置的支援服務品質不佳。也會導致瀏覽器依賴特定裝置行為中的怪異之處。
術語
HID 包含兩個基本概念:報告和報告描述元。 報表是裝置與軟體用戶端之間交換的資料。報表描述元會說明裝置支援的資料格式和意義。
人機介面裝置 (HID) 是一種裝置,可接收或提供人為輸入/輸出內容。這類通訊協定是主機與裝置間的雙向通訊標準,旨在簡化安裝程序。HID 協定最初是為 USB 裝置開發,但後來已透過許多其他協定實作,包括藍牙。
應用程式和 HID 裝置會透過三種報表類型交換二進位資料:
報告類型 | 說明 |
---|---|
輸入報表 | 從裝置傳送至應用程式的資料 (例如按下按鈕)。 |
輸出報表 | 從應用程式傳送至裝置的資料 (例如開啟鍵盤背光的請求)。 |
功能報表 | 資料可能會朝任一方向傳送。格式會因裝置而異。 |
報表描述元會說明裝置支援的報表二進位格式。結構為階層式,可將報表分組為頂層集合中的不同集合。描述元的格式是由 HID 規格定義。
HID 用法是指標準化輸入或輸出的數值。 裝置可透過使用情況值說明裝置的預期用途,以及報表中每個欄位的用途。舉例來說,其中一個是為滑鼠左鍵定義。用量也會整理到用量頁面,指出裝置或報表的高層級類別。
使用 WebHID API
特徵偵測
如要檢查是否支援 WebHID API,請使用:
if ("hid" in navigator) {
// The WebHID API is supported.
}
開啟 HID 連線
WebHID API 的設計為非同步,可避免網站 UI 在等待輸入時遭到封鎖。這點很重要,因為系統隨時可能收到 HID 資料,因此需要監聽資料的方式。
如要開啟 HID 連線,請先存取 HIDDevice
物件。為此,您可以呼叫 navigator.hid.requestDevice()
提示使用者選取裝置,或從 navigator.hid.getDevices()
中選取裝置,後者會傳回網站先前獲准存取的裝置清單。
navigator.hid.requestDevice()
函式會採用定義篩選器的必要物件。這些值可用來比對透過 USB 供應商 ID (vendorId
)、USB 產品 ID (productId
)、使用量頁面值 (usagePage
) 和使用量值 (usage
) 連接的任何裝置。您可以從 USB ID 存放區和 HID 使用量表文件取得這些值。
這個函式傳回的多個 HIDDevice
物件,代表同一部實體裝置上的多個 HID 介面。
// 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();

您也可以在 exclusionFilters
中使用選用鍵 navigator.hid.requestDevice()
,從瀏覽器挑選器中排除已知會發生故障的裝置。
// 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 }],
});
HIDDevice
物件包含 USB 供應商和產品 ID,用於識別裝置。其 collections
屬性會以裝置報表格式的階層式說明初始化。
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
}
根據預設,系統會以「關閉」狀態傳回 HIDDevice
裝置,且必須先呼叫 open()
開啟裝置,才能傳送或接收資料。
// Wait for the HID connection to open before sending/receiving data.
await device.open();
接收輸入內容報告
建立 HID 連線後,您就可以監聽裝置的 "inputreport"
事件,處理傳入的輸入報告。這些事件包含 HID 資料 (DataView
物件 (data
))、所屬的 HID 裝置 (device
),以及與輸入報表相關聯的 8 位元報表 ID (reportId
)。

延續上例,以下程式碼說明如何偵測使用者在 Joy-Con Right 裝置上按下的按鈕,希望您可以在家嘗試。
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]}.`);
});
請參閱 Pen webhid-joycon-button 示範。
傳送輸出報告
如要將輸出報告傳送至 HID 裝置,請將與輸出報告相關聯的 8 位元報告 ID (reportId
) 和位元組做為 BufferSource
(data
) 傳遞至 device.sendReport()
。報表傳送完畢後,系統就會處理傳回的 Promise。如果 HID 裝置未使用報告 ID,請將 reportId
設為 0。
以下範例適用於 Joy-Con 裝置,並說明如何使用輸出報表讓裝置震動。
// 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));
請參閱 Pen webhid-joycon-rumble 示範。
傳送及接收功能報表
功能報表是唯一可雙向傳輸的 HID 資料報表類型。可讓 HID 裝置和應用程式交換非標準 HID 資料。與輸入和輸出報表不同,應用程式不會定期接收或傳送功能報表。

如要將功能報告傳送至 HID 裝置,請將與功能報告相關聯的 8 位元報告 ID (reportId
) 和位元組做為 BufferSource
(data
) 傳遞至 device.sendFeatureReport()
。報表傳送完畢後,傳回的 Promise 會解析。如果 HID 裝置未使用報告 ID,請將 reportId
設為 0。
以下範例說明如何使用功能報表,要求 Apple 鍵盤背光裝置、開啟裝置並讓裝置閃爍。
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);
}
請參閱 Pen webhid-apple-keyboard-backlight 示範。
如要接收 HID 裝置的功能報告,請將與功能報告相關聯的 8 位元報告 ID (reportId
) 傳遞至 device.receiveFeatureReport()
。傳回的 Promise 會使用包含功能報表內容的 DataView
物件解析。如果 HID 裝置未使用報表 ID,請將 reportId
設為 0。
// Request feature report.
const dataView = await device.receiveFeatureReport(/* reportId= */ 1);
// Read feature report contents with dataView.getInt8(), getUint8(), etc...
聆聽連線和中斷連線的音效
網站獲得存取 HID 裝置的權限後,即可監聽 "connect"
和 "disconnect"
事件,主動接收連線和中斷連線事件。
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.
});
撤銷 HID 裝置的存取權
網站可以對不再想保留的 HID 裝置存取權進行清理,方法是在 HIDDevice
例項上呼叫 forget()
。舉例來說,如果教育網路應用程式是在多部裝置共用的電腦上使用,累積大量使用者產生的權限會導致使用者體驗不佳。
在單一 HIDDevice
執行個體上呼叫 forget()
,會撤銷對同一實體裝置上所有 HID 介面的存取權。
// Voluntarily revoke access to this HID device.
await device.forget();
forget()
適用於 Chrome 100 以上版本,請按照下列步驟檢查是否支援這項功能:
if ("hid" in navigator && "forget" in HIDDevice.prototype) {
// forget() is supported.
}
開發提示
您可以在內部頁面 about://device-log
輕鬆偵錯 Chrome 中的 HID,並在同一處查看所有 HID 和 USB 裝置相關事件。

如要以使用者可判讀的格式傾印 HID 裝置資訊,請使用 HID 探索工具。它會將每個 HID 用途的值對應至名稱。
在大多數 Linux 系統中,HID 裝置預設會對應唯讀權限。如要允許 Chrome 開啟 HID 裝置,請新增 udev
規則。在 /etc/udev/rules.d/50-yourdevicename.rules
建立檔案,並加入下列內容:
KERNEL=="hidraw*", ATTRS{idVendor}=="[yourdevicevendor]", MODE="0664", GROUP="plugdev"
在上一行中,[yourdevicevendor]
是 057e
,例如 Nintendo Switch Joy-Con。您也可以新增 ATTRS{idProduct}
,制定更具體的規則。確認 user
是 plugdev
群組的成員。然後重新連接裝置即可。
瀏覽器支援
Chrome 89 的 WebHID API 適用於所有電腦平台 (ChromeOS、Linux、macOS 和 Windows)。
示範
如需 WebHID 範例,請前往 web.dev/hid-examples。快來看看吧!
安全性和隱私權
規格作者已根據「控管強大的網頁平台功能存取權」中定義的核心原則 (包括使用者控制、透明度和人體工學),設計及實作 WebHID API。使用這項 API 的權限主要由權限模型控管,一次只能授予單一 HID 裝置的存取權。使用者必須主動選取特定 HID 裝置,才能回應提示。
如要瞭解安全性方面的取捨,請參閱 WebHID 規格的「安全性和隱私權注意事項」一節。
此外,Chrome 會檢查每個頂層集合的使用情形,如果頂層集合的使用情形受到保護 (例如一般鍵盤、滑鼠),網站就無法傳送及接收該集合中定義的任何報表。受保護用途的完整清單公開提供。
請注意,Chrome 也會封鎖安全性敏感的 HID 裝置 (例如用於加強驗證的 FIDO HID 裝置)。請參閱 USB 封鎖清單和 HID 封鎖清單檔案。
意見回饋
Chrome 團隊很想瞭解您對 WebHID API 的想法和使用體驗。
介紹 API 設計
API 是否有任何異常狀況?還是缺少實作構想所需的方法或屬性?
在 WebHID API GitHub 存放區中提出規格問題,或在現有問題中新增想法。
回報導入問題
您是否發現 Chrome 實作方式有錯誤?還是實作方式與規格不同?
請參閱「如何回報 WebHID 錯誤」。請務必盡可能提供詳細資訊,並提供重現錯誤的簡單操作說明,且將「元件」設為 Blink>HID
。
顯示支援
您打算使用 WebHID API 嗎?您的公開支持有助於 Chrome 團隊排定功能優先順序,並向其他瀏覽器供應商展現支援這些功能的重要性。
使用 #WebHID
主題標籤傳送推文給 @ChromiumDev,告訴我們您在何處使用這項功能,以及使用方式。
實用連結
- 規格
- 追蹤錯誤
- ChromeStatus.com 項目
- Blink 元件:
Blink>HID
特別銘謝
感謝 Matt Reynolds 和 Joe Medley 審查本文。 紅色和藍色 Nintendo Switch 相片由 Sara Kurfeß 提供,黑色和銀色筆記型電腦相片由 Athul Cyriac Ajay 在 Unsplash 上提供。