2011年10月20日 星期四

V-USB hid-custom-rq 範例解說

承上篇,這篇將摘要說明 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     3

USB 有定義一些常用的 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 產生:

2011063018h57_26_thumb2

指令列工具 (commandline)

hid-custom-rq 的指令列工具跟 custom-class 一樣,請參考「V-USB custom-class 範例解說」這篇。

延伸閱讀

0 意見: