在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,
配置描述符,接口描述符,端点描述符,字符串描述符,报告描述符等等。
USB报告描述符(Report Descriptor)是HID设备中的一个描述符,它是比较
复杂的一个描述符。

USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告。
输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等
信息返回给电脑,键盘将按键数据数据返回给电脑等;输出报告是主机发送
给USB设备的,例如键盘上的数字键盘锁定灯和大写字母锁定灯等。报告是
一个数据包,里面包含的是所要传送的数据。输入报告是通过中断输入端点
输入的,而输出报告有点区别,当没有中断输出端点时,可以通过控制输出
端点0发送,当有中断输出端点时,通过中断输出端点发出。

而报告描述符,是描述一个报告以及报告里面的数据是用来干什么用的。
通过它,USB HOST可以分析出报告里面的数据所表示的意思。它通过控制输入
端点0返回,主机使用获取报告描述符命令来获取报告描述符,注意这个请求
是发送到接口的,而不是到设备。一个报告描述符可以描述多个报告,不同的
报告通过报告ID来识别,报告ID在报告最前面,即第一个字节。当报告描述符中
没有规定报告ID时,报告中就没有ID字段,开始就是数据。

keyboard键值对应ID如下.

Keyboard上报格式固定为8个byte,如果有Report ID,那就是9byte.

byte0,byte1,byte2,byte3,byte4,byte5,byte6,byte7,byte8.

//----------------------------------------------------------------------------------------------------------------------

byte0:Report ID.

byte1:功能键(参考上面第一张图,每一个bit分别表示不同的功能键按下)

byte2:reserve.

byte3 ~ byte8:共6个byte,也就是说同时只能六个键按下,如果超过6个,状态是未知,还是只上报前6个键(这个待验证)

//---------------------------------------------------------------------------------------------------------------------

For example:

根据上面表格可以得知.

当Alt + Tab同时按下,keyboard会透过中断IN断点送出report ID(如果描述符里面有设定Report ID,上报时需要填写之前预先设定好的 ID,没设定,则不需要写),0x04,0x00(Reserve),0x2b,0x00,0x00,0x00,0x00,0x00

1,2,3同时按下.

Report ID,0x00,0x00(reserve),0x1E,0x1F,0x20,0x00,0x00,0x00.

1,2,3,4,5,6六个键同时按下.

Report ID,0x00,0x00(reserve),0x1E,0x1F,0x20,0x21,0x22,0x23.

仅仅只抬起1跟2两个键.

Report ID,0x00,0x00(reserve),0x20,0x21,0x22,0x23,0x00,0x00.

1,2,3,4,5,6六个键同时抬起.

Report ID,0x00,0x00(reserve),0x00,0x00,0x00,0x00,0x00,0x00.

左Alt按下.

Report ID,0x04,0x00(reserve),0x00,0x00,0x00,0x00,0x00,0x00.

左Window按下.

Report ID,0x08,0x00(reserve),0x00,0x00,0x00,0x00,0x00,0x00.

右Alt按下

Report ID,0x40,0x00(reserve),0x00,0x00,0x00,0x00,0x00,0x00.

右Window按下.

Report ID,0x80,0x00(reserve),0x00,0x00,0x00,0x00,0x00,0x00.

//---------------------------------------------------------------------------------------------------------------------------

下面通过由HID Descriptor tool生成的USB鼠标和USB键盘来说明一下报告
描述符和报告

  1. code char KeyBoardReportDescriptor[63] = {
  2. //表示用途页为通用桌面设备
  3. 0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
  4. //表示用途为键盘
  5. 0x09, 0x06,                    // USAGE (Keyboard)
  6. //表示应用集合,必须要以END_COLLECTION来结束它,见最后的END_COLLECTION
  7. 0xa1, 0x01,                    // COLLECTION (Application)
  8. //表示用途页为按键
  9. 0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
  10. //用途最小值,这里为左ctrl键
  11. 0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
  12. //用途最大值,这里为右GUI键,即window键
  13. 0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
  14. //逻辑最小值为0
  15. 0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
  16. //逻辑最大值为1
  17. 0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
  18. //报告大小(即这个字段的宽度)为1bit,所以前面的逻辑最小值为0,逻辑最大值为1
  19. 0x75, 0x01,                    //   REPORT_SIZE (1)
  20. //报告的个数为8,即总共有8个bits
  21. 0x95, 0x08,                    //   REPORT_COUNT (8)
  22. //输入用,变量,值,绝对值。像键盘这类一般报告绝对值,
  23. //而鼠标移动这样的则报告相对值,表示鼠标移动多少
  24. 0x81, 0x02,                    //   INPUT (Data,Var,Abs)
  25. //上面这这几项描述了一个输入用的字段,总共为8个bits,每个bit表示一个按键
  26. //分别从左ctrl键到右GUI键。这8个bits刚好构成一个字节,它位于报告的第一个字节。
  27. //它的最低位,即bit-0对应着左ctrl键,如果返回的数据该位为1,则表示左ctrl键被按下,
  28. //否则,左ctrl键没有按下。最高位,即bit-7表示右GUI键的按下情况。中间的几个位,
  29. //需要根据HID协议中规定的用途页表(HID Usage Tables)来确定。这里通常用来表示
  30. //特殊键,例如ctrl,shift,del键等
  31. //这样的数据段个数为1
  32. 0x95, 0x01,                    //   REPORT_COUNT (1)
  33. //每个段长度为8bits
  34. 0x75, 0x08,                    //   REPORT_SIZE (8)
  35. //输入用,常量,值,绝对值
  36. 0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
  37. //上面这8个bit是常量,设备必须返回0
  38. //这样的数据段个数为5
  39. 0x95, 0x05,                    //   REPORT_COUNT (5)
  40. //每个段大小为1bit
  41. 0x75, 0x01,                    //   REPORT_SIZE (1)
  42. //用途是LED,即用来控制键盘上的LED用的,因此下面会说明它是输出用
  43. 0x05, 0x08,                    //   USAGE_PAGE (LEDs)
  44. //用途最小值是Num Lock,即数字键锁定灯
  45. 0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
  46. //用途最大值是Kana,这个是什么灯我也不清楚^_^
  47. 0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
  48. //如前面所说,这个字段是输出用的,用来控制LED。变量,值,绝对值。
  49. //1表示灯亮,0表示灯灭
  50. 0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
  51. //这样的数据段个数为1
  52. 0x95, 0x01,                    //   REPORT_COUNT (1)
  53. //每个段大小为3bits
  54. 0x75, 0x03,                    //   REPORT_SIZE (3)
  55. //输出用,常量,值,绝对
  56. 0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
  57. //由于要按字节对齐,而前面控制LED的只用了5个bit,
  58. //所以后面需要附加3个不用bit,设置为常量。
  59. //报告个数为6
  60. 0x95, 0x06,                    //   REPORT_COUNT (6)
  61. //每个段大小为8bits
  62. 0x75, 0x08,                    //   REPORT_SIZE (8)
  63. //逻辑最小值0
  64. 0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
  65. //逻辑最大值255
  66. 0x25, 0xFF,                    //   LOGICAL_MAXIMUM (255)
  67. //用途页为按键
  68. 0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
  69. //使用最小值为0
  70. 0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
  71. //使用最大值为0x65
  72. 0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
  73. //输入用,变量,数组,绝对值
  74. 0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
  75. //以上定义了6个8bit宽的数组,每个8bit(即一个字节)用来表示一个按键,所以可以同时
  76. //有6个按键按下。没有按键按下时,全部返回0。如果按下的键太多,导致键盘扫描系统
  77. //无法区分按键时,则全部返回0x01,即6个0x01。如果有一个键按下,则这6个字节中的第一
  78. //个字节为相应的键值(具体的值参看HID Usage Tables),如果两个键按下,则第1、2两个
  79. //字节分别为相应的键值,以次类推。
  80. //关集合,跟上面的对应
  81. 0xc0                           // END_COLLECTION
  82. };

通过上面的分析,我们知道这个报告中只有一个报告,所以没有报告ID,
因此返回的都是实际使用的数据。总共有8字节输入,1字节输出。其中输入的
第一字节用来表示特殊按键,第二字节保留,后面的六字节为普通按键。如果
只有左ctrl键按下,则返回01 00 00 00 00 00 00 00(十六进制),如果
只有数字键1 按下,则返回00 00 0x1E 00 00 00 00 00,如果数字
键1 和2 同时按下,则返回00 00 0x1E 0x1F 00 00 00 00,如果
再按下左shift 键,则返回02 00 0x1E 0x1F 00 00 00 00,
然后再释放1   键,则返回02 00 0x1F 00 00 00 00 00,
然后全部按键释放,则返回00 00 00 00 00 00 00 00。

这些数据(即报告)都是通过中断端点返回的。当按下Num Lock键时,PC会发送
输出报告,从报告描述符中我们知道,Num Lock的LED对应着输出报告的最低位,
当数字小键盘打开时,输出xxxxxxx1(二进制,打x的由其它的LED状态决定);
当数字小键盘关闭时,输出xxxxxxx0(同前)。取出最低位就可以控制数字键锁定LED了。

下面这个报告描述符是USB鼠标报告描述符,比起键盘的来说要简单些。
它描述了4个字节,第一个字节表示按键,第二个字节表示x轴(即鼠标左右移动,
0表示不动,正值表示往右移,负值表示往左移),第三个字节表示y轴(即鼠标
上下移动,0表示不动,正值表示往下移动,负值表示往上移动),第四个字节
表示鼠标滚轮(正值为往上滚动,负值为往下滚动)。

  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. };

通过对上面的报告分析,我们知道报告返回4个字节,没有报告ID。如果鼠标左键按下,
则返回01 00 00 00(十六进制值),如果右键按下,则返回02 00 00 00,如果中键按下,
则返回04 00 00 00,如果三个键同时按下,则返回07 00 00 00。如果鼠标往右移动则
第二字节返回正值,值越大移动速度越快。其它的类推。

HID Keyboard & Mouse descriptor.的更多相关文章

  1. Share Keyboard, Mouse and Clipboard between Multiple Computers

    Synergy version: 1.4.12 Server Download and install synergy-1.4.12-Linux-i686.deb on Mint 14; Run it ...

  2. USB Keyboard Recorder

    catalogue . 引言 . Device Class Definition for Human Interface Devices (HID) . USB HID Report Descript ...

  3. Sparrow 开发板化身电脑音量调节器

    前言 原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正. 之前的新浪不能用啦,这次部分图片用的sm.ms的图床,加载慢,请耐心,准备换图床. 1.开箱简介 来填坑了!这次是 Sparrow ...

  4. (USB HID) Configuration Descriptor

    最近完成了HID的基本收發,使用的配置用了2個Endpoint,把一些特別重要要的地方紀錄下來 整個Configuration 分成4大部分 : 1. Configuration 2. Interfa ...

  5. 2--STM32+USB移植+HID 与AUDIO类MIDI设备组成的复合设备(原创)

      前期准备: 一.硬件资源:STM32F103,USB-FS固件库. 链接: STM32 之 标准外设版USB驱动库详解(架构+文件+函数+使用说明+示例程序) https://blog.csdn. ...

  6. DM816X 实现 USB HID Gadget 鼠标键盘功能【转】

    转自:https://my.oschina.net/renyongke/blog/410695 开发环境: 平台: DM8168 内核 :linux 2.6.32 RDK:DVRRDK_04.00.0 ...

  7. USB组合设备 Interface Association Descriptor (IAD)

    Communication Device Class,简称CDCUSB Compound Device,USB复合设备USB Composite Device,USB组合设备 摘要USB复合设备 Co ...

  8. imx6 matrix keyboard

    imx6需要添加4x4的矩阵键盘.本文记录添加方法. 参考链接 http://processors.wiki.ti.com/index.php/TI-Android-JB-PortingGuide h ...

  9. 技巧.【转】在虚拟机Vmware中使用HID设备(如USB免驱键盘)

    ZC:我的环境:Win7x64.VMware10 ZC:我的处理: ZC: (1).usb.generic.allowHID = "TRUE" (本来就有,将它的位置提前) ZC: ...

随机推荐

  1. Android开发手记(7) 按钮类控件的使用

    1.点击Button改变页面背景色 通过Button改变页面背景色,首先新建相应的对象,让后绑定到Layout上的元素. final RelativeLayout layout = (Relative ...

  2. 自定义圆形imageview

    import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader ...

  3. 方形布局SquareLayout

    public class SquareLayout extends RelativeLayout { public SquareLayout(Context context, AttributeSet ...

  4. ASP.NET 页面间数据传递的方法

    在做WEB开发时,很多地方会涉及到页面间的数据传递.这几天在完善教务基础系统,遇到了这个问题,上网查了一些资料,现总结如下: 说到页面间数据传递,很多人都会想到通过像Session这样的全局变量,但是 ...

  5. 将图片转换为Base64

    string Imagefilename   硬盘路径 protected string ImgToBase64String(string Imagefilename) { try { Bitmap ...

  6. 单点登录CAS使用记(七):关于服务器超时以及客户端超时的分析

    我的预想情况 一般情况下,当用户登录一个站点后,如果长时间没有发生任何动作,当用户再次点击时,会被强制登出并且跳转到登录页面, 提醒用户重新登录.现在我已经为站点整合了CAS,并且已经实现了单点登录以 ...

  7. 学OpenGL的一些好的网站

    好的资源太多,自己懂的太少,而今迈步从头越!!fighting...... 一些OpenGL资源链接 这是前几天自己简单整理的几个链接,希望对大家有用 顺便问一下http://www.spacesim ...

  8. 利用libpcap抓取QQ号码信息

    最近想在QQ登录时把QQ号码信息记录下来,百度了很多都没有找到具体方式,最近用Wireshark分析报文+libpcap库嗅探实现了这个小功能. 通讯背景: QQ客户端在通讯时使用UDP协议,其中数据 ...

  9. 避免Block的循环引用

    避免Block的循环引用 什么是循环引用,什么时候发生循环引用 1 循环引用就是当self 拥有一个block的时候,在block 又调用self的方法.形成你中有我,我中有你,谁都无法将谁释放的困局 ...

  10. 一次awk脚本的重构

    # 脚本功能说明: # . 检查URL中的域名是否是指定版本的域名 # . 对访问bid,authorid的游客身份排重,并累加其pv # 全局变量说明 # DOMIAN_LIST 是数组,key是要 ...