# HID Report Descriptor Inspector

> 用 WebHID 在 Chrome 直接讀取 USB HID 裝置的 report descriptor：縮排列出每個項目、逐欄位標出位元位置與範圍，並即時串流輸入報告，全程資料不上傳。

- URL: https://bytescope.dev/zh-Hant/hid-inspector/
- Locale: zh-Hant · Also: [en](https://bytescope.dev/en/hid-inspector.md) · [ja](https://bytescope.dev/ja/hid-inspector.md)
- Runs: 在瀏覽器本機讀取 HID 裝置 — 完全不會上傳。
- Requires: Chrome, Edge or Opera on desktop (WebHID). Not Firefox, Safari or mobile.
- Updated: 2026-09-08

## What it does

這個工具透過 WebHID API 連上 USB HID 裝置：按下連線，從瀏覽器的裝置選擇器挑出你的鍵盤、遊戲手把、條碼掃描器或自製韌體的板子，頁面就會列出它的 Collection 與報告，並把 report descriptor 解碼成經典桌面工具那種縮排列表 —— Usage Page、Usage、Collection、Logical Minimum/Maximum、`Report Size`、`Report Count`，還有 Input/Output/Feature 旗標，一個項目一行，直接可讀。一切都在你的瀏覽器本機執行，什麼都不會上傳；而且這個版本是純唯讀的，連一個位元組都不會送給裝置。

### 把 descriptor 拆到每一個欄位

Report descriptor 是每個 HID 裝置交給主機的一段位元組，用來宣告它接下來會送什麼資料 —— 鍵盤不用裝驅動就能動，靠的就是它；自製裝置動不了的時候，第一個該查的也是它。在原始列表下方，一張表把每一個 input、output、feature 報告攤開來：報告 ID、位元組大小，以及每個欄位的位元偏移、位元寬度、usage 名稱（`Generic Desktop / X`、`Keyboard LeftControl`、`Button 3`）、邏輯範圍與旗標 —— 這張對照表，以前你得拿著 HID Usage Tables 和記事本自己一格一格拼出來。

### 即時看著位元在跳

打開裝置後，輸入報告一到就即時串進來：一邊是原始十六進位位元組，旁邊是逐欄位解碼後的數值。按一個鍵、推一下搖桿、刷一張條碼 —— 你會直接看到是哪幾個位元在變，通常光是這樣就能揪出差一位的位元偏移，或是韌體實際打包方式跟 descriptor 宣告不一致的欄位。要注意 WebHID 是 Chromium 專屬的 API（桌面版 Chrome、Edge、Opera；Android 版 Chrome 照理也能用，但我們沒有實測過；Firefox 和 Safari 都沒有實作），而且有些裝置在瀏覽器開到之前就被作業系統接管了 —— 哪些裝置、為什麼，下面的 FAQ 會講清楚。

## Limits

Does not write feature reports or remap devices; it decodes report descriptors and shows live input reports.

## FAQ

### 為什麼我的鍵盤或滑鼠沒出現在選擇器裡？

在 Windows 上，Chromium 直接封鎖鍵盤和滑鼠 —— 一個能讀原始鍵盤報告的網頁，等於能側錄你打給其他程式的按鍵，所以它們根本不會出現在選擇器裡。macOS 上瀏覽器通常開得起來。另外，WebHID 在任何作業系統上都會封鎖某些受保護的 Usage Page（例如 FIDO 安全金鑰），而被驅動程式獨占接管的裝置，瀏覽器則完全開不了。

### Report descriptor 到底是什麼？

它是 HID 裝置在列舉時交給主機的一段精簡位元組，宣告它會送出或接受的每一種報告的結構：每個欄位屬於哪個 Usage Page 和 Usage、占幾個位元、邏輯範圍多大、是 Input、Output 還是 Feature。主機解析一次之後，就知道怎麼解讀之後的每一筆報告 —— HID 裝置不需要專屬驅動就是這個原因，而你在除錯的時候，這份 descriptor 就是唯一可信的依據。

### 裝置的資料會被上傳到哪裡嗎？

不會。WebHID 是瀏覽器和裝置之間的直接對話 —— descriptor、報告表格，還有你盯著看的每一筆輸入報告，全都留在你的電腦上。網站的分析只會記錄你用過這個工具，絕不會碰任何裝置資料。

### 它能寫入裝置嗎？可以送 output 或 feature 報告嗎？

不能，而且是刻意的。這個版本完全不會呼叫 `sendReport()` 或 `sendFeatureReport()`：它只讀 descriptor、只聽輸入報告，所以拿來對付你還在逆向工程的硬體也很安全。Feature 報告的寫入功能規劃在之後的版本。

### 解碼出來的欄位跟我的韌體程式碼對不上，為什麼？

這個工具解碼的就是裝置實際送出的位元組，所以對不上的時候，通常代表 descriptor 講的跟你以為的不一樣。常見兇手有三個：裝置用了報告 ID 時，線路上的第一個位元組是 ID，所有偏移都會往後移 8 個位元；填充項目（有 `Report Size` × `Report Count` 但沒有 Usage）占掉的位元，你的程式碼可能默默跳過了；欄位的位元組順序跟的是 descriptor 的位元配置，不是你 struct 的定義。把縮排列表和你自己寫的 descriptor 對一遍，出入幾乎一定就在裡面。
