使用USB HID进行数据交互

原创
2017/06/27 13:59
阅读数 2.3K

最近看到一款与我们同类型的USB Audio  Chip的SPEC: CM108AH(http://www.hardwaresecrets.com/datasheets/CM108AH.pdf), 其中通过HID协议对芯片内部寄存器进行读写操作的feature觉得很有意思。 考虑到客户应用场景下通过USB进行寄存器调整的简便性,觉得增加这个功能还是很有必要。

由于之前已经使用USB HID来进行音量的控制,所以相对修改就小的多,基本上只需要进行描述符的改动即可。

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 */

端点描述符


  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区分下。

HID 描述符

    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**,其他对应的格式如下:

我是通过Linux下对/dev/hidrawX这个设备节点进行read、write操作来进行功能的验证。

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进行传输。

 

展开阅读全文
USB
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部