usb鼠标_HID报告描述符的实现(11)

开发环境:win7
开发板    :51单片机 + pdiusbd12 芯片


前言:
    在上一节的末尾,设备接收到的数据:0x81 0x06 0x00 0x22 0x00 0x00 0x74 0x00
        0x81 表示:数据传输方向为 设备到主机,该命令请求是发送到接口中的。
                详情请看: usb鼠标_USB标准请求之设备描述符(5) 

        0x06 表示:表示是标准的设备请求:Get Descriptor,获取描述符。
        0x22 表示:HID 设备的 Report Desc,报告描述符。
        0x74 表示:报告描述符的长度。


1,报告描述符概述
     1.1) 报表描述符
        报表描述符和USB的其他描述符是不一样的,它不是一个简单的表格,报表描述符是USB所有描述符中最复杂的。报表描述符非常复杂而有弹性,因为它需要处理各种用途的设备。
报表的数据必须以简洁的格式来储存,这样才不会浪费设备内的储存空间以及数据传输时的总线时间。实际上可以这样理解,报表内容的简洁,是通过报表描述符全面的、复杂的数据描述实现的。
报表描述符必须先描述数据的大小与内容。报表描述符的内容与大小因设备的不同而不同,在进行报表传输之前,主机必须先请求设备的报表描述符,只有得到了报表描述符才可正确解析报表的数据。
报表描述符是报表描述项目(Item)的集合 ,每一个描述项目都有相对统一的数据结构,项目很多,通过编码实现。

      1.2) 项目(Item)
          HID的项目有 短项目 长项 两种。
          其中  :项目的第一个字节(项目前缀)由三部分构成,即项目类型(item type)、项目标志(item tag)和项目长度(item size)。
其中项目类型说明项目的数据类型,项目标签说明项目的功能,项目长度说明项目的数据部分的长度。
           usb鼠标_HID报告描述符的实现(11)_第1张图片
        短项目的数据字节数由bSize的值定义,bSize为0、1、2、3时Data部分的字节数分别为0、1、2、4个字节。短项目的项目类型由bType定义,bType为0、1、2时分别为 Main Global Local 类型。

          长项目:
           usb鼠标_HID报告描述符的实现(11)_第2张图片
          项目中的第一个字节为上图中的特定值时表明该项目是一个长项目。长项目中的bDataSize说明Data部分的字节数,bLongItemTag在HID规范中没有定义。


       1.3) 项目(Item) 类型
        报表的项目有Main、Global和Local三大类,每一类都有多个不同的项目,实现不同的描述。
         Main 类项目用于 定义报表描述符中的数据项 。也可以组合其中的若干数据项成为一个集合。Main项目可以分为带数据的Main项目和不带数据的Main项目。带数据项的Main用于生成报表中的数据项,包括Input、Output和Feature项目。不带数据的Main项目不生成报表中的数据项,包括Collection和End Collection项目。
         Global 类项目 实现对数据的描述 ,用来识别报表并且描述报表内的数据,包括数据的功能、最大与最小允许值以及数据项的大小与数目等。改变由Main类项目生成的项目状态表。Global类项目描述对后续的所有项目有效,除非遇到有新的Global类项目。
         Local 类项目 定义控制的特征 ,这一类项目的作用域不超过下一个Main项目,所以在每一Main项目之前可能有多个Local项目。Local项目用于描述后面的Input、Output和Feature项目。
         usb鼠标_HID报告描述符的实现(11)_第3张图片
         usb鼠标_HID报告描述符的实现(11)_第4张图片
        在这些项目中, Usage Page用来指定设备的功能 ,而 Usage项目用来指定个别报表的功能 。Usage Page项目相当于是HID的子集合,Usage相当于是Usage Page的子集合。



         1.4) 鼠标的报告描述符的实现
            Usage Page (Generic Desktop), 
            Usage (Mouse), 
            Collection (Application), 
                Usage (Pointer), 
                Collection (Physical), 
                    Report Count (3), 
                    Report Size (1), 
                    Usage Page (Buttons), 
                    Usage Minimum (1), 
                    Usage Maximum (3), 
                    Logical Minimum (0), 
                    Logical Maximum (1),  
                    Input (Data, Variable, Absolute), 
                    Report Count (1), 
                    Report Size (5), 
                    Input (Constant), 
                    Report Size (8), 
                    Report Count (2), 
                    Usage Page (Generic Desktop), 
                    Usage (X), 
                    Usage (Y), 
                    Logical Minimum (-127), 
                    Logical Maximum (127), 
                    Input (Data, Variable, Relative), 
                End Collection, 
            End Collection
             usb鼠标_HID报告描述符的实现(11)_第5张图片

             (1)Input、Outpot和Feature项目
                    这3个项目用来定义 报告(Report 中的 数据字段
                     Input 项目可以应用到任何控制、计数器读数或其他设备传给主机的信息。一个输入报告(Report)包含一个或多个Input项目,主机使用中断输入传输来请求输入 报告(Report
                     Ouput 项目用来定义主机传送给设备的信息。一个输出 报告(Report 包含一个或多个Outpot项目。输出 报告(Report 包含控制状态的数据。如果有中断输出管道,HID1.1兼容主机使用中断输出传输来传送输出 报告(Report ,否则使用Set_Report控制请求。
                     Feature 项目应用到主机传送给设备的信息,或是主机从设备读取Feature项目。一个特征 报告(Report 包含一个或多个Feature项目,Feature项目通常是包合影响设备与其组件整体行为的配置。特征 报告(Report 通常是控制可以使用实际的控制面板调整的设置,例如主机可以使用虚拟控制面板来让用户选择控制特征。主机使用Set_Report与Get_Report请求来传送与接收特征 报告(Report
                    在每一个Input、Output和Feature项目的前缀字之后是32位描述数据,目前最多定义了9个位,余的位则是保留。位0~8的定义中只有位7不能应用于Input项目,除此之外其他的位定义都适应于Input、Output和Feature项目。
                     usb鼠标_HID报告描述符的实现(11)_第6张图片
                     usb鼠标_HID报告描述符的实现(11)_第7张图片
                     usb鼠标_HID报告描述符的实现(11)_第8张图片
                    注:①:该位不能应用到数组。
                            ②:只应用于Output和Feature项目,对于Input项目该位保留。

                 (2)Collection和End Collection项目
                        所有的报表类型都可以使用Collection与End Collection项目来将相关的Main类型项目组成群组。 这两个项目分别用于打开和关闭集合 。所有在Collection与End Collection项目之间的Main类型项目都是Collection的一部分。
                        Collection有 3 种类型: Application Physical Logical ,其项目的数据项的值分别为1、0和2。厂商也可以自己定义Collection类型,数据项的值为80h~FFh保留给厂商定义。End Collection项目无数据项。
                         Application  Collection包含有共同用途的项目或执行单一功能的项目。例如键盘的开机描述符将键盘的按键与LED指示灯数据集合成一个Application Collection。所有的报表必须在一个Application Collection内。
                         Physical  Collection包含在一个单一几何点上的数据项目,可以将每个位置的数据集合成一个Physical Collection。在设备报告多个传感器的位置的时候,使用Physical Collection指明不同的数据来自不同的传感器。
                         Logical  Collection形成一个数据结构,包含由Collection所连结的不同类型的项目。例如数据缓冲区的内容以及缓冲区内字节数目的计数。

                 (3)Usage Page和Usage项目
                         Usage page 项目的数据部分为1~2个字节,目前的定义全部都是一个字节。Usage Page定义了常用的设备功能,关于Usage Page(以及其他项目)的具体定义内容,可以查阅HID Usage tables(http://www.usb.org/developers/hidpage/#Class_Definition),下表是来自HID Usage tables的Usage Page定义。
                         usb鼠标_HID报告描述符的实现(11)_第9张图片
                         usb鼠标_HID报告描述符的实现(11)_第10张图片

                        关于Usage Page的每一个有效定义项,都有一个相应的下一级定义,如Usage Page的数据项数值为1,则设备定义为Generic Desktop Controls,关于该类设备的具体功能可以在HID Usage Tables中查到具体的定义。下表是HID Usage Tables中对 Generic Desktop Controls 设备的功能定义。
                                                          
                        
                        


                    (4)Report ID项目
                         Report ID 放在信息包中报表数据之前,设备可以支持多个相同类型的报表,每一个报表包含不同的数据与其特有的ID。
                        在报表描述符中,Report ID项目作用于其后续所有的项目,直到遇到下一个Report ID为止。如果报表描述符中没有Report ID项目,默认的ID值是0,描述符不能定义一个为0的Report ID,输入报表、输出报表与特征报表可以分享同一个Report ID。
                        在Set_Report和Get_Report请求传输中,主机在设置事务的wValue字段的低字节中指定一个Report ID。在中断传输中如果接口支持一个以上的Report ID,Report ID必须是传送报表中的第一个字节。如果接口只支持数值为0的默认Report ID,此Report ID不应该在中断传输中随着报表一起传送。


                    (5)Report Size和Report Count项目
                         Report Size 项目指定Input、Output与Feature项目字段的大小,以位为单位。
                         Report Count 项目指定Input、Output与Feature项目包含的字段数目。
                        例如两个8位的字段,Report Size等于8,而Report Count等于2。8个1位的字段,Report Size等于1,而Report Count等于8。
                        Input、Output与Feature项目报表可以有多个项目,每一个项目可以有自己的Report Size和Report Count项目。


                    (6)Logical Minimum和Logical Maximum项目
                        Logical Minimum与Logical Maximum项目定义报表的变量(Variable)或阵列(Array)数据的限制范围,此限制范围以逻辑单位来表示。例如设备报表的一个电流值读数是500mA,而一个单位是2mA,则Logical Maximum值等于250。
                        负数值以2的补码来表示。如果Logical Minimum与Logical Maximum都是正数,就不需要有正负号位。不管Logical Minimum与Logical Maximum是以有正负号或是无正负号的数值来表示,设备都可以正确地传输数据。数据的接收者必须知道数据是否可以是负值。


                    (7)Physical Minimum和Physical Maximum项目
                        Physical Minimum和Physical Maximum项目定义数值的限制范围,该限制范围使用Unit项目定义的单位来表示。上例中设备报表的一个电流值读数是500mA,单位是2mA,Logical Maximum值等于250,而Physical Maximum值是500。
                        Logical Minimum与Logical Maximum值说明了设备返回数值的边界,可以根据Physical Minimum和Physical Maximum值对数据进行偏移和比例变换。


                    (8)Usage、Usage Minimum和Usage Maximum项目
                        这3个项目输入Local类型项目。
                        Usage项目和Global类型的Usage Page项目协同描述项目或集合的功能。一个报表可以指定一个Usage给许多个控制,或是指定不同的Usage给每一个控制。如果一个报表项目之前有一个Usage,此Usage应用到该项目的所有控制。如果一个报表项目之前有一个以上的Usage,每一个Usage应用到一个控制,Usage与控制是按顺序结合的。

                         例如下面报表描述符的一个局部,报表含有2个输入字节,第一个字节的用法是x,第2个字节是y。
                         usb鼠标_HID报告描述符的实现(11)_第11张图片

                        如果一个报表项目之前有一个以上的Usage,而且控制的数目多于Usage的数目,每一个Usage与一个控制对应,最后一个Usage则应用到所有剩余的控制。例如在下面报表包含16个字节输入数据,第一个字节对应用法x,第2个字节对应用法y,剩余的14个字节对应厂商定义的用法。
                         usb鼠标_HID报告描述符的实现(11)_第12张图片

                        Usage Minimum和Usage Maximum可以指定一个Usage给多个控制或是数组项目。将从Usage Minimum到Usgae Maximun定义的用法顺序对应到多个控制中。例如在一个键盘描述符中定义的标准键盘的左、右修饰键的输入项目中,使用一个字节的8位分别输入键盘的左、右Ctrl键、Shift键、Alt键和GUI键,从HID Usage tables文档中的第10节可以查到关于键盘用法的定义,其中上述8个修饰键的用法定义值为224到231。以下是报表描述符的修饰键部分描述。
                         usb鼠标_HID报告描述符的实现(11)_第13张图片


2,报告描述符的实现

点击(此处)折叠或打开

  1. code char MouseReportDescriptor[52] = {
  2.     //通用桌面设备
  3.     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  4.     //鼠标
  5.     0x09, 0x02, // USAGE (Mouse)
  6.     //集合
  7.     0xa1, 0x01, // COLLECTION (Application)
  8.     //指针设备
  9.     0x09, 0x01, // USAGE (Pointer)
  10.     //集合
  11.     0xa1, 0x00, // COLLECTION (Physical)
  12.     //按键
  13.     0x05, 0x09, // USAGE_PAGE (Button)
  14.     //使用最小值1
  15.     0x19, 0x01, // USAGE_MINIMUM (Button 1)
  16.     //使用最大值3。1表示左键,2表示右键,3表示中键
  17.     0x29, 0x03, // USAGE_MAXIMUM (Button 3)
  18.     //逻辑最小值0
  19.     0x15, 0x00, // LOGICAL_MINIMUM (0)
  20.     //逻辑最大值1
  21.     0x25, 0x01, // LOGICAL_MAXIMUM (1)
  22.     //数量为3
  23.     0x95, 0x03, // REPORT_COUNT (3)
  24.     //大小为1bit
  25.     0x75, 0x01, // REPORT_SIZE (1)
  26.     //输入,变量,数值,绝对值
  27.     //以上3个bit分别表示鼠标的三个按键情况,最低位(bit-0)为左键
  28.     //bit-1为右键,bit-2为中键,按下时对应的位值为1,释放时对应的值为0
  29.     0x81, 0x02, // INPUT (Data,Var,Abs)
  30.     //填充5个bit,补足一个字节
  31.     0x95, 0x01, // REPORT_COUNT (1)
  32.     0x75, 0x05, // REPORT_SIZE (5)
  33.     0x81, 0x03, // INPUT (Cnst,Var,Abs)
  34.     //用途页为通用桌面
  35.     0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  36.     //用途为X
  37.     0x09, 0x30, // USAGE (X)
  38.     //用途为Y
  39.     0x09, 0x31, // USAGE (Y)
  40.     //用途为滚轮
  41.     0x09, 0x38, // USAGE (Wheel)
  42.     //逻辑最小值为-127
  43.     0x15, 0x81, // LOGICAL_MINIMUM (-127)
  44.     //逻辑最大值为+127
  45.     0x25, 0x7f, // LOGICAL_MAXIMUM (127)
  46.     //大小为8个bits
  47.     0x75, 0x08, // REPORT_SIZE (8)
  48.     //数量为3个,即分别代表x,y,滚轮
  49.     0x95, 0x03, // REPORT_COUNT (3)
  50.     //输入,变量,值,相对值
  51.     0x81, 0x06, // INPUT (Data,Var,Rel)
  52.     //关集合
  53.     0xc0, // END_COLLECTION
  54.     0xc0 // END_COLLECTION
  55. };

3,运行结果
        对于HID设备而言,主机成功获取到 报告描述符,则设备的枚举过程就算是完成了的,
         usb鼠标_HID报告描述符的实现(11)_第14张图片
         usb鼠标_HID报告描述符的实现(11)_第15张图片
        设备已成功加载。

4,源码
         mouse.zip

5,问题遗留
        设备已成功加载,剩下的就是鼠标的左右键,滑轮等的功能实现了


6,参考文件
        1,HID Usage Tables  HID_Usage_Tables .pdf
        2,HID1.1协议  HID1_11.pdf



欲知 鼠标的功能的实现,敬请留意下集精彩。

你可能感兴趣的:(USB开发,USB开发)