HIDRAW - 原始訪問 USB 和藍牙人機介面裝置¶
hidraw 驅動程式提供了一個到 USB 和藍牙人機介面裝置 (HID) 的原始介面。它與 hiddev 的不同之處在於,傳送和接收的報告不會被 HID 解析器解析,而是以未修改的形式傳送到裝置並從裝置接收。
如果使用者空間應用程式確切地知道如何與硬體裝置通訊,並且能夠手動構建 HID 報告,則應使用 Hidraw。對於為自定義 HID 裝置製作使用者空間驅動程式時,通常是這種情況。
Hidraw 對於與不符合規範的 HID 裝置通訊也很有用,這些裝置以與其報告描述符不一致的方式傳送和接收資料。由於 hiddev 會解析透過它傳送和接收的報告,並根據裝置的報告描述符檢查它們,因此使用 hiddev 無法與這些不符合規範的裝置進行此類通訊。 對於這些不符合規範的裝置,Hidraw 是唯一的替代方案,除非編寫自定義核心驅動程式。
hidraw 的一個優點是使用者空間應用程式對其的使用獨立於底層硬體型別。 目前,hidraw 已經為 USB 和藍牙實現。 未來,隨著開發使用 HID 規範的新硬體匯流排型別,hidraw 將擴充套件以新增對這些新匯流排型別的支援。
Hidraw 使用動態主裝置號,這意味著應該依靠 udev 來建立 hidraw 裝置節點。 Udev 通常會在 /dev 下直接建立裝置節點(例如:/dev/hidraw0)。 由於此位置依賴於發行版和 udev 規則,因此應用程式應使用 libudev 來定位連線到系統的 hidraw 裝置。 libudev 上有一個包含工作示例的教程,網址為
http://www.signal11.us/oss/udev/
https://web.archive.org/web/2019*/www.signal11.us
HIDRAW API¶
read()¶
read() 將讀取從 HID 裝置接收的排隊報告。 在 USB 裝置上,使用 read() 讀取的報告是從裝置在 INTERRUPT IN 端點上傳送的報告。 預設情況下,read() 將阻塞,直到有報告可供讀取。 可以透過將 O_NONBLOCK 標誌傳遞給 open() 或使用 fcntl() 設定 O_NONBLOCK 標誌來使 read() 變為非阻塞。
在使用編號報告的裝置上,返回資料的第一個位元組將是報告編號;報告資料緊隨其後,從第二個位元組開始。 對於不使用編號報告的裝置,報告資料將從第一個位元組開始。
write()¶
write() 函式會將報告寫入裝置。 對於 USB 裝置,如果裝置具有 INTERRUPT OUT 端點,則將在該端點上傳送報告。 如果沒有,將使用 SET_REPORT 傳輸透過控制端點發送報告。
傳遞給 write() 的緩衝區的第一個位元組應設定為報告編號。 如果裝置不使用編號報告,則第一個位元組應設定為 0。 報告資料本身應從第二個位元組開始。
ioctl()¶
Hidraw 支援以下 ioctl
- HIDIOCGRDESCSIZE
獲取報告描述符大小
此 ioctl 將獲取裝置報告描述符的大小。
- HIDIOCGRDESC
獲取報告描述符
此 ioctl 使用 hidraw_report_descriptor 結構返回裝置的報告描述符。 請確保將 hidraw_report_descriptor 結構的 size 欄位設定為從 HIDIOCGRDESCSIZE 返回的大小。
- HIDIOCGRAWINFO
獲取原始資訊
此 ioctl 將返回一個 hidraw_devinfo 結構,其中包含裝置的匯流排型別、供應商 ID (VID) 和產品 ID (PID)。 匯流排型別可以是以下之一
- BUS_USB
- BUS_HIL
- BUS_BLUETOOTH
- BUS_VIRTUAL
這些定義在 uapi/linux/input.h 中。
- HIDIOCGRAWNAME(len)
獲取原始名稱
此 ioctl 返回一個字串,其中包含裝置的供應商和產品字串。 返回的字串是 Unicode,UTF-8 編碼。
- HIDIOCGRAWPHYS(len)
獲取物理地址
此 ioctl 返回一個字串,表示裝置的物理地址。 對於 USB 裝置,該字串包含裝置的物理路徑(USB 控制器、集線器、埠等)。 對於藍牙裝置,該字串包含裝置的硬體 (MAC) 地址。
- HIDIOCSFEATURE(len)
傳送特性報告
此 ioctl 將向裝置傳送特性報告。 按照 HID 規範,特性報告始終使用控制端點發送。 將提供的緩衝區的第一個位元組設定為報告編號。 對於不使用編號報告的裝置,將第一個位元組設定為 0。 報告資料從第二個位元組開始。 請確保相應地設定 len,比報告的長度多一個(以說明報告編號)。
- HIDIOCGFEATURE(len)
獲取特性報告
此 ioctl 將使用控制端點從裝置請求特性報告。 提供的緩衝區的第一個位元組應設定為請求報告的報告編號。 對於不使用編號報告的裝置,將第一個位元組設定為 0。 返回的報告緩衝區將包含第一個位元組中的報告編號,後跟從裝置讀取的報告資料。 對於不使用編號報告的裝置,報告資料將從返回緩衝區的第一個位元組開始。
- HIDIOCSINPUT(len)
傳送輸入報告
此 ioctl 將使用控制端點向裝置傳送輸入報告。 在大多數情況下,在裝置上設定輸入 HID 報告是沒有意義且沒有效果的,但某些裝置可能會選擇使用它來設定或重置報告的初始狀態。 使用此報告發出的緩衝區的格式與 HIDIOCSFEATURE 的格式相同。
- HIDIOCGINPUT(len)
獲取輸入報告
此 ioctl 將使用控制端點從裝置請求輸入報告。 在大多數裝置上,對於存在用於常規輸入報告的專用 In 端點,這會比較慢,但它允許主機請求特定報告編號的值。 通常,這用於請求裝置的輸入報告的初始狀態,然後應用程式透過常規裝置 read() 介面偵聽正常報告。 使用此報告發出的緩衝區的格式與 HIDIOCGFEATURE 的格式相同。
- HIDIOCSOUTPUT(len)
傳送輸出報告
此 ioctl 將使用控制端點向裝置傳送輸出報告。 在大多數裝置上,對於存在用於常規輸出報告的專用 Out 端點,這會比較慢,但為了完整性而添加了它。 通常,這用於設定裝置的輸出報告的初始狀態,然後應用程式透過 HIDIOCSOUTPUT 請求或常規裝置 write() 介面傳送更新。 使用此報告發出的緩衝區的格式與 HIDIOCSFEATURE 的格式相同。
- HIDIOCGOUTPUT(len)
獲取輸出報告
此 ioctl 將使用控制端點從裝置請求輸出報告。 通常,這用於檢索裝置的輸出報告的初始狀態,然後應用程式根據需要透過 HIDIOCSOUTPUT 請求或常規裝置 write() 介面對其進行更新。 使用此報告發出的緩衝區的格式與 HIDIOCGFEATURE 的格式相同。
示例¶
在 samples/ 中,找到 hid-example.c,其中顯示了 read()、write() 和 hidraw 的所有 ioctl 的示例。 任何人都可以將該程式碼用於任何目的,並且可以作為使用 hidraw 開發應用程式的起點。
文件作者
Alan Ott <alan@signal11.us>, Signal 11 Software