承上篇,這篇將摘要說明 V-USB hid-custom-rq 範例程式。
hid-customer-rq 分成兩個部份:韌體和 PC 端的指令列工具 (commandline)。
hid-custom-rq 的功能跟 custom-class 範例一樣,因此底下的內容大部份都跟 custom-class 雷同。hid-custom-rq 跟 custom-class 不一樣的地方,在於 hid-custom-rq 是宣告成 HID device。
韌體
usbconfig.h
底下是 hid-custom-rq 對 usbconfig.h 所做的調整:
- USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 與 USB_CFG_DPLUS_BIT
這些設定 USB bus D+ 和 D- 所用的接腳。預設是:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 4
#define USB_CFG_DPLUS_BIT 2
- #define USB_CFG_HAVE_INTRIN_ENDPOINT 1
這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。
- #define USB_CFG_INTR_POLL_INTERVAL 100
這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。
- USB_CFG_VENDOR_ID 與 USB_CFG_DEVICE_ID
這些設定 VID 和 PID。預設是:
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_DEVICE_ID 0xdf, 0x05資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05df 是 obdev 提供的共享 VID/PID。
- USB_CFG_DEVICE_NAME and USB_CFG_DEVICE_NAME_LEN
這些設定 Device Name 和資料長度,hid-custom-rq 把 Device Name 設成 "LEDCtlHID",資料長度是 9:
#define USB_CFG_DEVICE_NAME 'L', 'E', 'D', 'C', 't', 'l', 'H', 'I', 'D'
#define USB_CFG_DEVICE_NAME_LEN 9
- USB_CFG_DEVICE_CLASS 與 USB_CFG_INTERFACE_CLASS
這些設定 Device Class 和 Interface Class。hid-custom-rq 的設定為:
#define USB_CFG_DEVICE_CLASS 0
#define USB_CFG_INTERFACE_CLASS 3USB 有定義一些常用的 device class,可在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義 3 代表這個是 HID Class。
- #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 22
這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 22 bytes 才行。
request.h
這個檔案定義 host 和 device 的通訊 request number,它由 host software 和 device firmware 共享。
hid-custom-rq 共定義了 2 個 request numbers:
- #define CUSTOM_RQ_SET_STATUS 1
設定 LED 狀態 (Control-OUT)。要求的 LED 狀態會放在 control transfer 的 wValue 欄位中,wValue 低位元組 Bit 0 用來控制 LED 的開關 (1: 開, 0: 關)。control transfer 的 data stage 實際上沒有送出 OUT data (zero length data)。
- #define CUSTOM_RQ_GET_STATUS 2
取得 LED 目前的狀態 (Control-IN)。這個 control transfer 在 data stage 中 device 會送 1 個 byte 的資料給 host,LED 的狀態會儲存在 data byte 的 BIT 0。
main.c
主程式分成 main() 和 usbFunctionSetup() 兩個函式。關於 main() 和 usbFunctionSetup() 兩個函式的說明,請參考「V-USB custom-class 範例解說」一文。
在這個範例程式中,main loop 的工作很單純,只是不斷呼叫 usbPoll() 讓 driver 處理工作。根據 V-USB 的說明,usbPoll() 至少每 50 ms 要跑一次。
底下是 custom-data 的 usbFunctionSetup():
跟 custom-class 範例一樣,程式邏輯只是透過 bRequest 判斷是哪一個 request number,然後再依 request number 執行對應的動作,很單純。關於 request number,請參考前面 request.h 的說明。
雖然 hid-custom-rq 定義成 HID class,但程式並沒有實作 HID 相關的 request function,因為 PC 端指令列工具不會呼叫,作業系統也不會,所以 hid-customr-rq 把 report 定義成 "undefined":
上列只是一個 dummy desciptor,它的描述是說 report 是 1 byte 的 undefined data。 這個資料結構可以利用 HID Descriptor Tool 產生:
指令列工具 (commandline)
hid-custom-rq 的指令列工具跟 custom-class 一樣,請參考「V-USB custom-class 範例解說」這篇。
0 意見:
張貼留言