device descriptor
+ configuration descriptor
| + interface descriptor
| | + endpoint descriptor
| | + (more) endpoint descriptor
| | + hid descriptor
| | + physical descriptor
| | + report descriptor
| + (more) interface descriptor
+ (more) configuration descriptor
驅動程式取得 descriptor 的順序為:
- device descriptor
- configuration descriptor #1 (+ interface descriptor #1 + endpoint descriptor (#1~#N) + hid descriptor (不包括 physical descriptor 及 report descriptor) + interface descriptor #2 + endpoint descriptor (#1~#N) + hid descriptor (不包括 physical descriptor 及 report descriptor) + ... + interface descriptor #N ... )
- 各別 interface descriptor 中的 HID report descriptor.
- 讀取 configuration descriptor #2~N (重複 2~3 步驟)
+--- bit field: 7654 32 10 | tag type size | | | | | | | +--- 0, 1, 2, 4 bytes | | +--- main item, global item, local item | +--- item | | +--- data byte 1 (LSB) | | | | +--- data byte 2 (data byte 為 32 bits, 因此 byte 2~4 沒指定的話, 都為 0) | | | | | | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (1) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x03, // USAGE_MAXIMUM (Button 3) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x02, // INPUT (Data,Var,Abs) Input 是單向的(host 接收) 0x75, 0x05, // REPORT_SIZE (5) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x09, 0x38, // USAGE (Wheel) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page) 0x0A, 0x01, 0x88, // USAGE (Vendor Usage) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x04, // REPORT_ID (4) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0xff, // LOGICAL_MAXIMUM (255) 0x09, 0x00, // USAGE (Undefined) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x10, // REPORT_COUNT (16) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x00, // USAGE (Undefined) 0x95, 0x08, // REPORT_COUNT (8) 0xb1, 0x02, // FEATURE (Data,Var,Abs) Feature 是雙向的 0xc0 // END_COLLECTION
在以上 report descriptor 中, 每一行都是一個 item, 從 item type 及 item tag 就可以區分出所有的 item 了:
- Main item: Input, Output, Feature, Collection, End Collection.
- Global item: Usage Page, Logical Minimum, Logical Maximum, Physical Minimum, Physical Maximum, Unit Exponent, Unit Report Size, Report ID, Report Count, Push, Pop.
- Local item: Usage, Usage Minimum, Usage Maximum, Designator Index, Designator Minimum, Designator Maximum, String Index, String Minimum, String Maximum, Delimiter.
一個 HID 裝置可以有多種應用, 譬如一個觸控板裝置的應用為滑鼠, 但也有可能附加其它應用, 如鍵盤(以在判斷出手勢時, 送出按鍵). 每一個應用, 在 report descriptor 中是以 COLLECTION (Application) item 為開端, 舉前文中 report descriptor 為例, 在作業系統中會由 HID class 驅動程式列舉出兩個裝置: 滑鼠及特殊應用裝置(廠商自定義), 另外, 特別要注意的是 Report ID, 如果 report descriptor 中有多種應用集合, 則在應用集合中要指定不同的 Report ID.
HID 裝置上電後是以 report protocol 傳送資料, 即所送出的資料是完全依照 report descriptor 中之描述, 此外, HID 裝置還可以支援 boot protocol, 以固定格式傳送資料(且不含 Report ID), 如此一來, 可於 BIOS 或是空間有限的嵌入式系統中省下解譯 report descriptor 的程式碼. 目前 boot protocol 所支援的 HID 裝置有鍵盤及滑鼠.
更多資訊:
- USB in a NutShell - USB Descriptors
- USB Protocol
- USnooBie's USB HID Report Descriptor Tutorial 1
- USB DIY -- 自學計畫
- USB 官方網頁 - HID Information
- Wiki - Human Interface Device (boot protocol)
應用程式開發:
- The HID Page
- READING INPUT REPORTS FROM A HID DEVICE
應用程式開發的連結都失效囉
回覆刪除