使用USB HID進行數據交互

最近看到一款與咱們同類型的USB Audio  Chip的SPEC: CM108AH(http://www.hardwaresecrets.com/datasheets/CM108AH.pdf), 其中經過HID協議對芯片內部寄存器進行讀寫操做的feature以爲頗有意思。 考慮到客戶應用場景下經過USB進行寄存器調整的簡便性,以爲增長這個功能仍是頗有必要。ubuntu

因爲以前已經使用USB HID來進行音量的控制,因此相對修改就小的多,基本上只須要進行描述符的改動便可。api

HID接口描述符測試

0x09,         /* bLength: Interface Descriptor size */
  0x04,         /* bDescriptorType: Interface descriptor type */
  0x03,         /* bInterfaceNumber: Number of Interface */
  0x00,         /* bAlternateSetting: Alternate setting */
  0x02,         /* bNumEndpoints */
  0x03,         /* bInterfaceClass: HID */
  0x00,         /* bInterfaceSubClass : 1=BOOT, 0=no boot */
  0x00,         /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
  0x00,         /* iInterface: Index of string descriptor */

端點描述符code

0x07,          /* bLength: Endpoint Descriptor size */
  0x05,          /* bDescriptorType: */
  0x81,          /* bEndpointAddress: Endpoint Address (IN) */
  0x03,          /* bmAttributes: Interrupt endpoint */
  0x08, 0x00,    /* wMaxPacketSize: 8 Bytes max */
  0x20,          /* bInterval: Polling Interval (32 ms) */

  0x07,          /* bLength: Endpoint Descriptor size */
  0x05,          /* bDescriptorType: */
  0x09,          /* bEndpointAddress: Endpoint Address (OUT) */
  0x03,          /* bmAttributes: Interrupt endpoint */
  0x08, 0x00,    /* wMaxPacketSize: 8 Bytes max */
  0x20,          /* bInterval: Polling Interval (32 ms) */

這裏使用了2個端點,IN端點1做爲媒體控制信息和私有數據的輸入端點,OUT端點做爲私有數據的輸出端點。接口

因爲IN端點1裏面承載的2種不一樣用途的payload,就必需要用report id區分下。ip

HID 描述符get

0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
    0x09, 0x01,                    // USAGE (Consumer Control)
    0xa1, 0x01,                    // COLLECTION (Application)
    
    0x85, 0x01,                    //   Report ID1
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x09, 0xe9,                    //   USAGE (Volume Up)
    0x09, 0xea,                    //   USAGE (Volume Down)
    0x09, 0xe2,                    //   USAGE (Mute)
    0x09, 0xCD,                    //   USAGE (Play/Pause)
    0x09, 0xb5,                    //   USAGE (Scan Next Track)
    0x09, 0xb6,                    //   USAGE (Scan Previous Track)
    0x09, 0xb3,                    //   USAGE (Fast Forward)
    0x09, 0xb7,                    //   USAGE (Stop)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x42,                    //   INPUT (Data,Var,Abs,Null)

    0x85, 0x02,                    //   Report ID2 Data Input(2 bytes)
    0x26, 0xFF, 0x00,
    0x09, 0x00,
    0x75, 0x08,
    0x95, 0x02,
    0x81, 0x02,
    
    0x85, 0x03,                    //   Report ID3 Data Output (2 bytes)
    0x26, 0xFF, 0x00,
    0x09, 0x00,
    0x75, 0x08,
    0x95, 0x02,
    0x91, 0x02,
    
    0xc0,                           // END_COLLECTION

注意在進行數據傳輸時,須要先發送report id,而後再加上playload。虛擬機

按上面的描述信息,report ID1的payload是1個字節,因此傳輸數據格式應該爲: 0x01,,0x**,其餘對應的格式以下:string

我是經過Linux下對/dev/hidrawX這個設備節點進行read、write操做來進行功能的驗證。it

USB分析儀抓包數據以下:

能夠看到幀號45096是report1的輸入數據,幀號45105是report3的輸出數據。

BTW:

  1. 你們能夠觀察下,HID採用USB中斷傳輸類型,其本質也是輪詢方式,若是過多使用的話也會很佔用USB帶寬(從超多的NAK就能夠看出來)。
  2. 我本人是在vmware虛擬機裏裝ubuntu進行對hidrawX節點的操做,結果問題不少hidapi(http://www.signal11.us/oss/hidapi/)也用不起來。若是隻能在虛擬機下測試,最好每次測試完後拔插下USB設備。
  3. 關於OUT端點9能夠不用,這樣的話HID默認採用端點0進行傳輸。
相關文章
相關標籤/搜索