自定义 HID 设备的实现――下位机

最近在做一个投票系统的上位机。虽然是上位机,但还是要弄清楚下位机与自己的接口――HID。

因为windows下已经有一个usb监听程序――USB HOUND。所以,我选择先写好下位机的程序,成功发送数据后,再进行上位机程序的编写。

下位机程序,重点在于HID设备的描述符配置。什么是描述符?

HID 设备,
|– 通过设备描述符来标识自己的设备信息,如设备ID、厂商名称、版本、配置数量等;
|– 通过配置描述符集合来标识自己的配置信息,包括
| |– 配置描述符(总述)、
| `– 接口描述符(接口类型,鼠标,键盘,自定义设备等)、
| |– 端点描述符(端点读写类型,支持的数据包属性等)和
| `– HID描述符(HID版本、下级描述符信息等)。
|– 通过字符串描述符来定义自己的一些字符串,如厂商名称等;
`– 通过报告描述符来标识数据流的格式,如数据用途(鼠标、键盘、自定义等)、长度、大小等。

网上的很多示例和介绍都使用c语言,但是,我遇到的源码,却是汇编编写的,所以我以我的项目为例,用汇编来介绍各个描述符结构,也算是个不一样的体验吧。

具体的描述介绍如下:

设备描述符

deviceDesc:     ; Device descriptor
DB deviceDescEnd - deviceDesc    ; bLength 该描述符长度
DB DESC_TYPE_DEVICE              ; bDescriptorType 类型
DW 0200H                         ; bcdUSB (USB 2.0) USB 版本
DB 00H                           ; bDeviceClass (given by interface) 类代码
DB 00H                           ; bDeviceSubClass 子类代码
DB 00H                           ; bDeviceProtocol 设备协议
DB EP0_PACKET_SIZE   ; 端点0最大包长
DW 0451H                         ; idVendor (Texas Instruments) 厂商ID (VID)
#if (chip==2531)
DW 16A9H                         ; idProduct (CC2531 HID) 产品ID (PID)
#elif (chip==2511)
DW 16A5H                         ; idProduct (CC2511 HID)
#else
DW 16A7H                         ; idProduct (CC1111 HID)
#endif
DW 0100H                         ; bcdDevice (v1.0) 设备版本号
DB 01H                           ; iManufacturer 描述厂商的字符串索引
DB 02H                           ; iProduct 描述产品的字符串索引
DB 00H                           ; iSerialNumber 产品序列号字符串的索引
DB 01H                           ; bNumConfigurations 可能的配置数
deviceDescEnd:

在里面,最重要的是VID和PID,它一般用来标识你的USB设备。VID需要向USB组织申请,PID则是公司内部自己定义。其实,我们还可以通过产品序列号来标识,但目前,我还没有添加这个功能,直接使用VID和PID识别的。

另外我们可以通过这份代码看到一些技巧,就是在填写描述符长度时,让编译器自己计算:deviceDescEnd – deviceDesc

配置描述符

configDesc:     ; Configuration descriptor
DB configDescEnd - configDesc   ; bLength 该描述符长度
DB DESC_TYPE_CONFIG             ; bDescriptorType 类型
DW config1LengthEnd - config1LengthStart ; wTotalLength 所有配置描述符的总长度
; adding a custom interface, so this should be 3! - by tankery.
DB 03H                          ; bNumInterfaces 端点数量
DB 01H                          ; bConfigurationValue 该配置的值?不懂。。。。。。
DB 00H                          ; iConfiguration 该配置的字符串索引值
DB 80H                          ; bmAttributes 该配置属性
DB 25                           ; bMaxPower (max 2 * 25 = 50 mA) 设备所需电流大小。
configDescEnd:

我目前的设备是鼠标、键盘、自定义3种接口。可以支持三种端点同时传输数据,非常high~~

接口描述符

interface2Desc: ; custom device interface descriptor
DB interface2DescEnd - interface2Desc ; bLength 该描述符长度
DB DESC_TYPE_INTERFACE          ; bDescriptorType 类型
; this should be increaced - by tankery.
DB 02H                          ; bInterfaceNumber 该接口的编号
DB 00H                          ; bAlternateSetting (none) 备用编号
DB 01H                          ; bNumEndpoints 端点数
DB 03H                          ; bInterfaceClass (HID) 接口使用的类(HID)
DB 00H                          ; bInterfaceSubClass (custom) 接口使用的子类(00为自定义)
DB 00H                          ; bInterfaceProcotol (custom) 接口使用的协议(00为自定义)
DB 00H                          ; iInterface 该接口的字符串索引值
interface2DescEnd:

我的这个项目中,有3 种接口,原始代码已经实现了鼠标和键盘的接口描述符。感兴趣的读者也可以在网上查阅。有现成的示例代码。

从本文开始的那个介绍看出,接口之下是包含端点的,因此,接口描述符中有一项的端点数,这个端点数标明的是除默认控制端点0之外的数据输入输出端点数量。目前我只实现了一个数据输入(USB中所有的输入、输出的对象都是主设备,在我这里,指的是PC)。
后期我会添加一个数据输出端点。

端点描述符

endpoint2Desc:  ; Custom endpoint descriptor (EP3 IN)
; need endpoint 3 - by tankery.
DB endpoint2DescEnd - endpoint2Desc ; bLength 该描述符长度
DB DESC_TYPE_ENDPOINT           ; bDescriptorType 类型
DB 83H                          ; bEndpointAddress 端点地址(3)
DB EP_ATTR_INT                  ; bmAttributes (INT) 端点类型(中断)
DW 0008H                        ; wMaxPacketSize (8 bit) 最大数据包长度
DB 0AH                          ; bInterval (10 full-speed frames = 10 ms)
endpoint2DescEnd:

端点描述符中的bmAttributes 是个比较重要的字段,标明了该端点的类型,端点有控制(0)、等时(1)、批量(2)、中断(3)四种类型。HID只有控制端点和中断端点两种类型。

HID描述符

hid2Desc:	; Custom HID descriptor
DB hid2DescEnd - hid2Desc       ; bLength
DB DESC_TYPE_HID                ; bDescriptorType
DW 0111H                        ; bcdHID (HID v1.11)
DB 00H                          ; bCountryCode (not localized)
DB 01H                          ; bNumDescriptors
DB DESC_TYPE_HIDREPORT          ; bDescriptorType
DW entity2DescEnd - entity2Desc ; wDescriptorLength
hid2DescEnd:

这个没啥要紧的,我也不清楚,不详述了。

报告描述符

报告描述符相当复杂,但也是HID设备的精髓。它标识了HID设备与主机通讯的报告格式以及数据用途,数据是存放在报告中的。

报告描述符的每个条目都有个条目前缀,是如下格式:

,-----------------------.
|7 6 5 4  3   2   1   0 |
|-----------------------|
| bTag  | bType | bSize |
`-----------------------'

高 4 位bTag标识该条目的功能,具体的可以参看HID协议,第 2, 3 位为条目类型(0――主条目、1――全局条目、2――局部条目、3――保留),第 0, 1 位为条目大小,表示该前缀之后有多少个字节的内容。
比如 09H (00001001B) 表示这是一个局部条目,后跟一个字节。功能为用途页(0)。各种功能的定义可以参看HID协议或者其它示例,下面,我就以我写的自定义设备为例大致介绍一下报告描述符的设计:

entity2Desc:                ; Custom HID device report descriptor
DB 0005H, 0001H     ; Usage Pg (Generic Desktop) 全局,功能为“用途页”。后跟的0001H表示这是通用桌面用途
DB 0009H, 0000H     ; Usage (0) ; custom usage 局部,功能为“用途页”。后跟0000H表示这是自定义用途。
DB 00A1H, 0001H     ; Collection: (Application) 主条目,功能为“开集合”,表示后面的条目都在集合 Application 下。
                    ;
DB 0015H, 0000H     ;   Log Min (0) 全局,功能为“最小值”,表示数据的可以达到的逻辑最小值为0
DB 0025H, 00FFH     ;   Log Max (255) 全局,“最大值”,表示最大为255 (一个字节)。
DB 0019H, 0000H     ;   Usage Min (0) 局部,功能为“最小值”,表示局部用途,即上文定义的自定义用途最小值为0
DB 0029H, 00FFH     ;   Usage Max (255) 局部。。。。
                    ;
                    ;   we will send the remote ID and selection
                    ;       need 2 byte (16 bit) data space.
DB 0095H, 0002H     ;   Report Count (2) 全局,功能为“数据数量”,表示每个报告中数据的数据有2个
DB 0075H, 0008H     ;   Report Size (8) 全局,功能为“数据大小”,表示每个数据大小为 8 个bit。
DB 0081H, 0002H     ;   Input: (Data, Variable, Absolute) 主,功能为“输入”,
                    ;   02H (00000010B) 表示以上的数据定义是变量,独立(非数组),绝对值(无符号)的。
DB 00C0H            ; End Collection 主条目,不跟内容,“关集合”。表示关闭上面打开的Application集合。
entity2DescEnd:

通过这份报告描述符,我们就能知道,这个接口传输的数据是用于自定义用途的,而且是两个字节的数据。
当然,我这还是测试之用,到具体使用时,我会使用两个数据段,一个是 4 个字节的手持端ID数组,一个是1字节的手持端数据内容。
到时就会更复杂一些。

OK,剩下的工作就是编写这些描述符的发送函数了。我使用的是TI公司的代码,所以没有自己编写这些函数,就不误人子弟了。。
并且不同的芯片编写的代码也不一样。要看具体情况。有兴趣的读者就自己去体会吧~~

转载于:https://www.cnblogs.com/tankery/archive/2011/04/16/2018288.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值