USB HID

文章目录

目录

一、USB简介

二、USB(HID)协议及描述符

1.USB描述符简介

2.USB描述符

  

一、USB简介

USB根据速度可分为:

  1. 低速USB  Low Speed Device (LS)  
  2. 全速USB Full Speed Device (FS)  
  3. 高速USB设备 Hight Speed Device (HS)

具体应用以及特性如下:

一般USB接口有4根线,分别是VCC DM DP GND。DM,DP是数据线。

USB的检测:

每一个主机USB的DM, DP都有内部15K下拉到GND,没有外设插入情况下是低电平。在USB从设备中,如果设备是高速USB则在DP上加有1.5K上拉到VCC,如果是低速设备则在DM上加1.5K上拉到VCC。当DP或者DM被拉高就可以检测USB插入,并且可以区分是高速还是低速USB。

二、USB(HID)协议及描述符

1.USB描述符简介

USB的硬件端口是统一的,但是USB设备却是多种多样的,USB主机根据USB设备的描述符来区分不同的USB设备。每一个USB设备都有自己的描述符,当插入USB设备之后,主机会向从机发送命令,从机收到命令之后,会返回特定的描述符信息。主机通过解析收到的描述符,来识别从机设备的相关信息,这个过程,就是设备枚举(enumeration)过程。

USB有5种标准设备描述符,分别是:设备描述符、配置描述符、字符串描述符、接口描述符、端点描述符。

另外还有:HID描述符、报告描述符等各个类特有的描述符。见下表:

要注意的是,设备描述符有且只有一个。其包含关系如下图所示。

2.USB描述符

         2.1 USB设备描述符

设备描述符有且仅有一个!

描述符使用到的宏定义如下:

#define USB_DEVICE_DESCRIPTOR_TYPE              0x01

#define USB_CONFIGURATION_DESCRIPTOR_TYPE       0x02

#define USB_STRING_DESCRIPTOR_TYPE              0x03

#define USB_INTERFACE_DESCRIPTOR_TYPE           0x04

#define USB_ENDPOINT_DESCRIPTOR_TYPE            0x05

#define HID_DESCRIPTOR_TYPE                     0x21


设备描述符类型定义固定为0x01

USB HID设备的设备描述符代码例子(STM32 USB HID)如下:

/* USB Standard Device Descriptor */
const uint8_t CustomHID_DeviceDescriptor[CUSTOMHID_SIZ_DEVICE_DESC] =
 {
    0x12,                       /*bLength */
    USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
    0x00,                       /*bcdUSB */
    0x02,
    0x00,                       /*bDeviceClass*/
    0x00,                       /*bDeviceSubClass*/
    0x00,                       /*bDeviceProtocol*/
    0x40,                       /*bMaxPacketSize40*/
    0x83,                       /*idVendor (0x0483)*/
    0x04,
    0x50,                       /*idProduct = 0x5750*/
    0x57,
    0x00,                       /*bcdDevice rel. 2.00*/
    0x02,
    1,                          /*Index of string descriptor describing
                                              manufacturer */
    2,                          /*Index of string descriptor describing
                                             product*/
    3,                          /*Index of string descriptor describing the
                                             device serial number */
    0x01                        /*bNumConfigurations*/
 }; /* CustomHID_DeviceDescriptor */

其结构成员意义如下:

(1)bLength

描述符长度(18字节,十六进制为0x12),就是标志描述符数据结构的长度。

(2)bDescriptorType

bDescriptorType代表了本描述符的类型,设备描述符为0x01 (设备描述符固定为0x01)

(3)bcdUSB

    USB协议版本,表示形式0xJJMN版本JJ.M.N(JJ  - 主要版本号,M  - 次要版本号,N  - 次要版本)

    例子:如果是USB2.0,写成:0200H;如果是USB1.1,写成:0110H 如果是USB3.11,写成:0311H

(4)bDeviceClass、bDeviceSubClass、bDeviceProtocol

    bDeviceClass、bDeviceSubClass、bDeviceProtocol分别代表设备类型,子类型,设备使用的协议,USB-IF区分设备类分了三个等级(类-子类-协议码)其中,类包含人机交互类、图像类、无线类、音频类等等,子类比如音频类的音频控制、音频流等等,协议比如人机接口类中的鼠标、键盘、触摸屏等,为何会有这么多USB的Class分类,子分类,设备协议。我们要知道,USB协议设计的目的,就是为实现通用,用单一的USB接口取代之前种类繁多的各种其他接口。而为了取代其他各种接口,那意味着就要实现各种设备所对应的各种功能。如下图显示USB设备的各种类别,USB设备类信息更详细内容可进入https://www.usb.org/defined-class-codes查看。

(5)bMaxPackeSize0

就是端点一次最大传多少个字节。USB协议里有规定,端点0最低8字节,端点的最大传输大小和USB速度等级以及传输类型有关,控制传输一般使用端点0,低速最大8字节,全速和高速最大传输64字节,如下图:

(6)idVender

    厂商ID,就是个2字节的编号,由USB协议分配,厂商申请时需要交费。自己随便写的话,仅限于学习、测试的情况下,不能用做产品。

(7)idProduct

    产品ID,厂家自己随便定义。

(8)bcdDevice

    产品版本号,厂家自己随便定义。

(9)iManufacturer

    描述厂商的字符串的索引,为0则表示没有。

(10)iProduct

    描述产品的字符串的索引,为0则表示没有。

(11)iSerialNumber

    产品序列号字符串的索引,为0则表示没有。

(12)bNumConfigurations

指示设备由多少个配置,前面提到过,一个USB可能有多个配置,一般USB产品都是1个配置。

        2.2 配置描述符

配置描述符至少有一个,可以有多个,一般一个设备只设置一个配置描述符。

配置描述符类型定义固定为0x02

USB HID设备的配置描述符代码例子(STM32 USB HID)如下:(注意其中除了配置描述符还包括其他如接口描述符和端点描述符)

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t CustomHID_ConfigDescriptor[CUSTOMHID_SIZ_CONFIG_DESC] =
{
    0x09, /* bLength: Configuration Descriptor size */
    USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
    CUSTOMHID_SIZ_CONFIG_DESC,/* wTotalLength: Bytes returned */
    0x00,
    0x01,         /* bNumInterfaces: 1 interface */
    0x01,         /* bConfigurationValue: Configuration value */
    0x00,         /* iConfiguration: Index of string descriptor describing
                                 the configuration*/
    0xC0,         /* bmAttributes: Self powered */
    0x32,         /* MaxPower 100 mA: this current is used for detecting Vbus */

    /************** Descriptor of Custom HID interface ****************/
    /* 09 */
    0x09,         /* bLength: Interface Descriptor size */
    USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
    0x00,         /* 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 */
    0,            /* iInterface: Index of string descriptor */
    /******************** Descriptor of Custom HID HID ********************/
    /* 18 */
    0x09,         /* bLength: HID Descriptor size */
    HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
    0x10,         /* bcdHID: HID Class Spec release number */
    0x01,
    0x00,         /* bCountryCode: Hardware target country */
    0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
    0x22,         /* bDescriptorType */
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */
    0x00,
    /******************** Descriptor of Custom HID endpoints ******************/
    /* 27 */
    0x07,          /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */
    0x81,          /* bEndpointAddress: Endpoint Address (IN) */
    0x03,          /* bmAttributes: Interrupt endpoint */
    0x02,          /* wMaxPacketSize: 2 Bytes max */
    0x00,
    0x20,          /* bInterval: Polling Interval (32 ms) */
    /* 34 */
    	
    0x07,	/* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE,	/* bDescriptorType: */
			/*	Endpoint descriptor type */
    0x01,	/* bEndpointAddress: */
			/*	Endpoint Address (OUT) */
    0x03,	/* bmAttributes: Interrupt endpoint */
    0x02,	/* wMaxPacketSize: 2 Bytes max  */
    0x00,
    0x20,	/* bInterval: Polling Interval (20 ms) */
    /* 41 */
  }; /* CustomHID_ConfigDescriptor */

其中配置描述符代码段:

    0x09, /* bLength: Configuration Descriptor size */
    USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
    CUSTOMHID_SIZ_CONFIG_DESC,/* wTotalLength: Bytes returned */
    0x00,
    0x01,         /* bNumInterfaces: 1 interface */
    0x01,         /* bConfigurationValue: Configuration value */
    0x00,         /* iConfiguration: Index of string descriptor describing
                                 the configuration*/
    0xC0,         /* bmAttributes: Self powered */
    0x32,         /* MaxPower 100 mA: this current is used for detecting Vbus */

配置描述符的各个域的意义如下:

bLength:大小为1字节,表示该描述符的长度。标准的USB配置描述符的长度为9字节。

bDescriptorType:配置描述符的类型。

wTotalLength:表示整个配置描述符集合的总长度,包括配置描述符、接口描述符、端点描述符和类特殊描述符(HID类)。注意低字节在前。

bNumInterfaces:该配置描述符所支持的接口数量(接口编号数量而不是接口描述符数量,不同的接口描述符可能使用同一个编号接口)。功能单一设备只有一个,而复合设备则具有多个接口。

bConfigurationValue:表示该配置的值。通常一个USB设备可以支持多个配置,bConfigurationValue就是每个配置的标识。

iConfiguration:描述该配置的字符串的索引值。如果该值为0,则表示没有字符串。

bmAttributes:用来描设备的一些特性。其中,D7是保留的,必须要设置为1。D6表示供电方式,D6=1时,表示设备自供电;D6=0时,表示设备时总线供电。D5表示是否支持远程唤醒,D5=1时,支持远程唤醒。D4~D0保留,设置为0

bMaxPower:表示设备需要从总线获取的最大电流量,单位为2mA。如需要200mA的最大电流,则该字节的值为100

        2.3 接口描述符

如上面代码中

 /************** Descriptor of Custom HID interface ****************/
    /* 09 */
    0x09,         /* bLength: Interface Descriptor size */
    USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType: Interface descriptor type */
    0x00,         /* 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 */
    0,            /* iInterface: Index of string descriptor */

该段代码定义的是HID的接口描述符。


USB_INTERFACE_DESCRIPTOR_TYPE为固定值表示该配置是接口描述符。

bNumEndpoints,该接口使用的端点个数。注意一点,这个端点个数不包括0端点。

bInterfaceClass的定义如下表:

bInterfaceSubClass 除带有由接口定义的类的设备外,此字段于设备描述符中的bDeviceSubClass 相同。若 bInterfaceClass 等于00h,bInterfaceSubClass 也必须等于 00h。若 bInterfaceClass 取从 01h到FEh的值,bInterfaceSubClass则等于00h或等于一个为接口的类定义的值。FFh表明为厂商定义的子类。

    bInterfaceProtocol 除了带有接口定义的类的设备外,此字段于设备描述符中的bDeviceProtocol相同。此字段可为所选bInterfaceClass和bInterfaceSubClass 所规定的协议。若bInterfaceClass取从01h到FEh的值,bInterfaceProtocol必须等于00h,或等于为接口的类定义的值。FFh表明为厂商定义的协议。

    iInterface 是指向描述接口的字符串的索引。若没有字符串描述符,该值为0.

        2.4HID描述符

上面在接口描述符中定义了设备类型为0x03的HID设备,那么需要定义HID描述符,上面代码中HID描述符代码如下:

    /* 18 */
    0x09,         /* bLength: HID Descriptor size */
    HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID */
    0x10,         /* bcdHID: HID Class Spec release number */
    0x01,
    0x00,         /* bCountryCode: Hardware target country */
    0x01,         /* bNumDescriptors: Number of HID class descriptors to follow */
    0x22,         /* bDescriptorType */
    CUSTOMHID_SIZ_REPORT_DESC,/* wItemLength: Total length of Report descriptor */
    0x00,

bcdHID为0x0110,表面该HID协议为1.1版本

bCountryCode: 设备所适用的国家。如果使用的键盘是美式键盘,代码为33,即0x21

bNumDescriptors:下级描述符的数量。这个值至少为1,也就是HID类设备至少要有一个报告描述符。下级描述符可以是报告描述符或者物理描述符。

wItemLength: 报告描述符的总长度。

  2.5 端点描述符

上面HID的端点描述符代码:

    /******************** Descriptor of Custom HID endpoints ******************/
    /* 27 */
    0x07,          /* bLength: Endpoint Descriptor size */
    USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: */

    0x81,          /* bEndpointAddress: Endpoint Address (IN) */
    0x03,          /* bmAttributes: Interrupt endpoint */
    0x02,          /* wMaxPacketSize: 2 Bytes max */
    0x00,
0x20,          /* bInterval: Polling Interval (32 ms) */

bEndpointAddress: bit7 :方向  1/0 :in/out,对于控制端点可以忽略;bit4~bit6 保留,bit3~bit0:端点号 

bmAttributes,属性。如下

bit1~bit0:

00 = Control-控制传输

01 = Isochronous-等时传输

10 = Bulk-批量传输

11 = Interrupt-中断传输

如果不是一个等时传输端点,第5~2位是保留的,必须设置为0。如果它是等时的,则定义如下:

Bits 3..2: Synchronization Type-同步类型

00 = No Synchronization-无同步

01 = Asynchronous-异步

10 = Adaptive-适配

11 = Synchronous-同步

/*Bits 5..4: Usage Type-用途*/

00 = Data endpoint-数据端点

01 = Feedback endpoint-反馈端点

10 = Implicit feedback Data endpoint-暗含反馈的数据端点

11 = Reserved-保留

wMaxPackeSize,端点支持的最大包长。对于等时端点,此值用于在调度中保留总线时间,这是每(微)帧数据有效负载所需的时间。在进行中,管道实际使用的带宽可能比保留的带宽少。如果有必要,设备会报告通过其正常的、非usb定义的机制所使用的实际带宽。

对于所有的端点,bit10~bit0指定最大数据包大小(以字节为单位)。

/*5.对于高速同步和中断端点:bit12~bit11指定每个微帧的额外通信次数:

00 = None (1 transaction per microframe)

01 = 1 additional (2 per microframe)

10 = 2 additional (3 per microframe)

11 = Reserved

bInterval,查询时间,说白了就是主机多久和设备通讯一次。根据设备运行速度以帧或微帧表示。

对于全/高速等时端点,此值必须在1到16之间。bInterval值用作2的指数;例如,bInterval为4,表示周期为8, 2(4 – 1)。

对于全速/低速中断端点,该字段的值可以是1到255。

对于高速中断端点,使用bInterval值作为2的指数;例如,bInterval为4表示周期为8 ,2(4-1)。这个值必须在1到16之间。

对于高速批量/控制输出端点,bInterval必须指定端点的最大NAK速率。值0表示端点永不NAK。其它值表示每个微帧的bInterval数最多1个NAK。这个值的范围必须在0到255之间。

2.6 报告描述符

报告描述符包含多个报告,不同的报告通过报告ID来识别,报告的第一个字节就是报告ID。当报告描述符中没有定义报告ID时,开始就是数据。

报告描述符由条目(item)来组成,一个条目占据一行。HID协议规定了两种条目:短条目和长条目,常用的是短条目。

短条目的构成:一字节的前缀 + 可选的数据字节。可选的数据字节可以是0、1、2、4字节。实际中所使用的条目,大部分是1字节的可选数据

一个条目前缀如下

bSize:bit1~bit0后面紧跟的字节数

03-15
### USB HID协议概述 USB HID(Human Interface Device)协议是一种用于连接计算机和其他电子设备的标准通信协议,主要用于支持人机交互的外设,如键盘、鼠标、游戏控制器等。该协议通过标准化的数据结构和通信流程简化了这些设备的设计与实现过程[^1]。 #### 主要特点 HID协议的核心目标是为输入/输出设备提供一种高效、灵活且易于扩展的通信框架。其主要特点是能够处理多种类型的设备,并允许开发者创建自定义功能的硬件产品。典型的应用场景包括但不限于: - 键盘 (Keyboard)[^2] - 鼠标 (Mouse) - 游戏手柄 (Joystick)[^2] 此外,HID协议还提供了详细的报文描述符解析文档,帮助开发者深入了解数据包的具体格式及其含义[^3]。 --- ### 报文描述符详解 为了便于开发者理解HID设备的工作原理以及如何构建有效的数据流,官方资料中包含了关于报文描述符的详尽解释。以下是几个关键概念: - **报告描述符**:这是HID协议中最核心的部分之一,用来定义设备发送给主机或者接收来自主机的信息格式。例如,在一个简单的按键事件中,“按下键A”的操作会被编码成特定字节序列并通过此路径传递到操作系统层面进行进一步处理。 - **字段布局**:每种类型都有自己的属性集合来表示不同的物理量或逻辑状态变化情况;比如位置坐标轴上的移动距离可以用相对位移值表达出来,而按钮则可能只需要布尔标志表明当前是否处于激活状态之中等等。 --- ### 实现步骤 当实际部署基于HID规范的产品时,通常遵循如下四个阶段完成初始化配置工作: 1. 请求获取完整的设备描述信息以便确认基本参数设定; 示例命令字符串形式化展示如下所示: ```plaintext 52.0 CTL 80 06 00 01 00 00 12 00 GET DESCRIPTOR ``` 2. 接收返回的结果集并验证有效性; 响应消息样例片段列举在此处供参考学习之用: ```plaintext 372.1.0 device 52.0 IN 12 01 10 01 00 00 00 08 9b 0b 12 40 01 00 01 ff ... ``` 上述两部分内容共同构成了整个握手协商过程中不可或缺的重要环节[^4]。 --- ### 开发者资源推荐 针对希望更全面掌握这项技术的人群而言,《USB_HID协议中文版.pdf》无疑是一份极为宝贵的参考资料。它不仅涵盖了基础理论知识介绍,而且深入探讨了一些高级主题领域内的细节问题解决方案建议等内容^[]^3]。 ```python # Python示例代码演示如何读取HID设备数据 import hid def read_hid_data(vendor_id, product_id): try: devices = hid.enumerate() for d in devices: if d['vendor_id'] == vendor_id and d['product_id'] == product_id: dev = hid.device() dev.open_path(d['path']) while True: data = dev.read(64) # 尝试从设备读取最多64字节的数据 if data: print(f"Received Data: {data}") except Exception as e: print(e) if __name__ == "__main__": VENDOR_ID = 0xXXXX # 替换为目标设备的实际Vendor ID PRODUCT_ID = 0xYYYY # 替换为目标设备的实际Product ID read_hid_data(VENDOR_ID, PRODUCT_ID) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值