人機介面裝置的維護與使用¶
介紹¶
除了普通的輸入型別 HID 裝置之外,USB 還使用人機介面協議來處理一些實際上並非人機介面,但具有類似通訊需求的事物。 這兩個主要的例子是電源裝置(尤其是不間斷電源)和高階監視器上的監視器控制。
為了支援這些不同的需求,Linux USB 系統為 HID 事件提供了兩個獨立的介面:* input 子系統,它將 HID 事件轉換為普通的輸入裝置介面(例如鍵盤、滑鼠和操縱桿)以及標準化的事件介面 - 請參閱 介紹 * hiddev 介面,它提供相當原始的 HID 事件
由裝置生成的 HID 事件的資料流如下所示
usb.c ---> hid-core.c ----> hid-input.c ----> [keyboard/mouse/joystick/event]
|
|
--> hiddev.c ----> POWER / MONITOR CONTROL
此外,其他子系統(除了 USB)也可能將事件饋送到 input 子系統中,但這不會對 HID 裝置介面產生影響。
使用 HID 裝置介面¶
hiddev 介面是一個字元介面,使用普通的 USB 主裝置號,次裝置號從 96 開始到 111 結束。 因此,您需要以下命令
mknod /dev/usb/hiddev0 c 180 96
mknod /dev/usb/hiddev1 c 180 97
mknod /dev/usb/hiddev2 c 180 98
mknod /dev/usb/hiddev3 c 180 99
mknod /dev/usb/hiddev4 c 180 100
mknod /dev/usb/hiddev5 c 180 101
mknod /dev/usb/hiddev6 c 180 102
mknod /dev/usb/hiddev7 c 180 103
mknod /dev/usb/hiddev8 c 180 104
mknod /dev/usb/hiddev9 c 180 105
mknod /dev/usb/hiddev10 c 180 106
mknod /dev/usb/hiddev11 c 180 107
mknod /dev/usb/hiddev12 c 180 108
mknod /dev/usb/hiddev13 c 180 109
mknod /dev/usb/hiddev14 c 180 110
mknod /dev/usb/hiddev15 c 180 111
因此,您將您的 hiddev 相容使用者空間程式指向裝置的正確介面,它就可以正常工作了。
當然,前提是您有一個 hiddev 相容的使用者空間程式。 如果您需要編寫一個,請繼續閱讀。
HIDDEV API¶
此描述應與 HID 規範結合閱讀,該規範可從 https://www.usb.org 免費獲得,並方便地連結到 http://www.linux-usb.org。
hiddev API 使用 read() 介面和一組 ioctl() 呼叫。
HID 裝置使用稱為“報告”的資料包與主機計算機交換資料。 每個報告分為“欄位”,每個欄位可以有一個或多個“用法”。 在 hid-core 中,這些用法中的每一個都有一個帶符號的 32 位值。
read():¶
這是事件介面。 當 HID 裝置的狀態發生變化時,它會執行中斷傳輸,其中包含一個報告,其中包含已更改的值。 hid-core.c 模組解析報告,並將報告中已更改的各個用法返回給 hiddev.c。 在其基本模式下,hiddev 將使用 struct hiddev_event 向讀者提供這些單獨的用法更改
struct hiddev_event {
unsigned hid;
signed int value;
};
其中包含已更改狀態的 HID 用法識別符號以及更改為的值。 請注意,該結構是在 <linux/hiddev.h> 中定義的,以及其他一些有用的 #defines 和結構。 HID 用法識別符號是移位到 16 個高位,並與用法程式碼進行 OR 運算的 HID 用法頁面的組合。 可以使用下面描述的 HIDIOCSFLAG ioctl() 修改 read() 函式的行為。
ioctl():¶
這是控制介面。 有許多控制元件
- HIDIOCGVERSION
int (讀取)
從 hiddev 驅動程式中獲取版本程式碼。
- HIDIOCAPPLICATION
(無)
此 ioctl 呼叫返回與 HID 裝置關聯的 HID 應用程式用法。 ioctl() 的第三個引數指定要獲取的應用程式索引。 當裝置有多個應用程式集合時,這很有用。 如果索引無效(大於或等於此裝置擁有的應用程式集合的數量),則 ioctl 返回 -1。 您可以從 hiddev_devinfo 結構的 num_applications 欄位預先了解裝置有多少個應用程式集合。
- HIDIOCGCOLLECTIONINFO
struct hiddev_collection_info (讀/寫)
這返回上述資訊的超集,不僅提供應用程式集合,還提供裝置擁有的所有集合。 它還返回集合在層次結構中存在的級別。 使用者傳入一個 hiddev_collection_info 結構,並將 index 欄位設定為應返回的索引。 ioctl 填充其他欄位。 如果索引大於最後一個集合索引,則 ioctl 返回 -1 並將 errno 設定為 -EINVAL。
- HIDIOCGDEVINFO
struct hiddev_devinfo (讀取)
獲取描述裝置的 hiddev_devinfo 結構。
- HIDIOCGSTRING
struct hiddev_string_descriptor (讀/寫)
從裝置獲取字串描述符。 呼叫者必須填寫“index”欄位以指示應返回哪個描述符。
- HIDIOCINITREPORT
(無)
指示核心從裝置檢索所有輸入和特徵報告值。 此時,所有用法結構都將包含裝置的當前值,並在裝置更改時保持該值。 請注意,通常不需要使用此 ioctl,因為後來的核心會在連線時自動從裝置初始化報告。
- HIDIOCGNAME
字串 (可變長度)
獲取裝置名稱
- HIDIOCGREPORT
struct hiddev_report_info (寫入)
指示核心從裝置獲取特徵或輸入報告,以便選擇性地更新用法結構(與 INITREPORT 相比)。
- HIDIOCSREPORT
struct hiddev_report_info (寫入)
指示核心將報告發送到裝置。 使用者可以透過 HIDIOCSUSAGE 呼叫(如下所示)填充此報告,以在將整個報告發送到裝置之前填充報告中的各個用法值。
- HIDIOCGREPORTINFO
struct hiddev_report_info (讀/寫)
為使用者填寫 hiddev_report_info 結構。 按型別(輸入、輸出或特徵)和 ID 查詢報告,因此使用者必須填寫這些欄位。 ID 可以是絕對的 - 裝置報告的實際報告 ID - 或相對的 - HID_REPORT_ID_FIRST 表示第一個報告,(HID_REPORT_ID_NEXT | report_id) 表示 report_id 之後的下一個報告。 如果沒有關於報告 ID 的先驗資訊,使用此 ioctl 的正確方法是使用上面的相對 ID 來列舉有效 ID。 當沒有更多下一個 ID 時,ioctl 返回非零值。 真正的報告 ID 填充到返回的 hiddev_report_info 結構中。
- HIDIOCGFIELDINFO
struct hiddev_field_info (讀/寫)
以 hiddev_field_info 結構返回與報告關聯的欄位資訊。 使用者必須像上面一樣在此結構中填寫 report_id 和 report_type。 還應填寫 field_index,它應該是一個從 0 到 maxfield-1 的數字,如先前 HIDIOCGREPORTINFO 呼叫返回的。
- HIDIOCGUCODE
struct hiddev_usage_ref (讀/寫)
給定其報告型別、報告 ID、欄位索引以及欄位內的索引已填寫到結構中,則在 hiddev_usage_ref 結構中返回 usage_code。
- HIDIOCGUSAGE
struct hiddev_usage_ref (讀/寫)
返回 hiddev_usage_ref 結構中用法的價值。 要檢索的用法可以如上所述指定,或者使用者可以選擇填寫 report_type 欄位並將 report_id 指定為 HID_REPORT_ID_UNKNOWN。 在這種情況下,如果找到該用法,hiddev_usage_ref 將填充與此用法關聯的報告和欄位資訊。
- HIDIOCSUSAGE
struct hiddev_usage_ref (寫入)
設定輸出報告中用法的價值。 使用者如上所述填寫 hiddev_usage_ref 結構,但另外填寫 value 欄位。
- HIDIOGCOLLECTIONINDEX
struct hiddev_usage_ref (寫入)
返回與此用法關聯的集合索引。 這表示此用法在集合層次結構中的位置。
- HIDIOCGFLAG
int (讀取)
- HIDIOCSFLAG
int (寫入)
這些操作分別檢查和替換影響上面 read() 呼叫的模式標誌。 標誌如下
- HIDDEV_FLAG_UREF
read() 呼叫現在將返回 struct hiddev_usage_ref 而不是 struct hiddev_event。 這是一個更大的結構,但在裝置在其報告中使用具有相同用法程式碼的多個用法的情況下,此模式有助於解決此類歧義。
- HIDDEV_FLAG_REPORT
此標誌只能與 HIDDEV_FLAG_UREF 結合使用。 設定此標誌後,當裝置傳送報告時,將向 read() 返回一個 struct hiddev_usage_ref,其中填充了 report_type 和 report_id,但 field_index 設定為 FIELD_INDEX_NONE。 當裝置已傳送報告時,這可用作額外的通知。