ByteScope

HID Report Descriptor Inspector

接上 HID 裝置,看它到底跟主機說了什麼 —— 解碼後的 descriptor、逐位元的欄位表與即時輸入報告。

在瀏覽器本機讀取 HID 裝置 — 完全不會上傳。

未連接任何裝置

正在檢查瀏覽器支援狀態…

瀏覽器支援矩陣

WebHID 目前在 Chromium 架構的桌上型瀏覽器中獲得支援。瞭解更多關於 WebHID 支援的資訊

功能ChromeEdgeFirefoxSafari
navigator.hid 裝置選擇器僅支援 Chromium 桌上型瀏覽器。支援支援不支援不支援
即時 Input Report透過 WebHID 接收即時 Input Report。支援支援不支援不支援
在 Android 上連接裝置我們沒有在 Android 上實機測過。Firefox 在任何平台都沒有實作 WebHID,Safari 在 Android 上也不存在。未測試未測試不支援不適用
貼上 descriptor 解碼純運算 — 無需連接裝置,在所有瀏覽器皆可運作。支援支援支援支援
開啟鍵盤或滑鼠Windows 會完全封鎖 WebHID 存取最上層鍵盤與滑鼠 Collection;macOS 和 Linux 通常允許存取。部分支援部分支援不支援不支援

偵測到的瀏覽器功能

  • navigator.hid
  • Secure Context (HTTPS)

關於這個工具

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

把 descriptor 拆到每一個欄位

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

即時看著位元在跳

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