一.测试中断或者Bulk传输:

  首先要使用Libusb打印出HID设备的Endpoint查看是否支持中断或者Bulk传输模式;如果支持的话才可以进一步测试;

  因为HID设备在插入的时候无需安装,并且一般会被OS直接占用,所以如果直接使用Interrupt传输(通常只有一个断点)会发生超时

  所以建议使用zadig给对应的HID设备安装WinUSB来防止直接被占用,然后就可以收到数据了:

  对于收到的数据该如何解析(以及如果想要修改Device来发送不同的字母)可以查看:HID键盘对照表   和  字母的ASCII码表

  这是我的一部分解析数据的代码(传入参数就是接收缓冲区的首地址指针)

 1 void parse_mouse_data(char* data)
 2 {
 3     char c1 = *data;
 4     char c2 = *(data + 1);
 5     char c3 = *(data + 2);
 6     char c4 = *(data + 3);
 7     if (c1 & LEFT_PRESS)
 8         printf("Left key press\n");
 9     if (c1 & RIGHT_PRESS)
10         printf("Right Key Press\n");
11     if (c1 & MIDLE_PRESS)
12         printf("Middle Key Press\n");
13     if (c2 & LEFT_SIDE)
14         printf("Go Left : %d\n", (c2 & 0x7f));
15     else 
16         printf("Go Right : %d\n", (c2 & 0x7f));
17     if (c3 & DOWN_SIDE)
18         printf("Go Down : %d\n", (c3 & 0x7f));
19     else 
20         printf("Go Up : %d\n", (c3 & 0x7f));
21 }
22 void parse_keyboard_data(char* data) 
23 {
24     char temp1 = *data;
25     if (temp1 & (0x1 << 0))
26         printf("Left Control Presed");
27     if (temp1 & (0x1 << 1))
28         printf("Left Shift Pressed\n");
29     if (temp1 & (0x1 << 2))
30         printf("Left Alt Pressed\n");
31     if (temp1 & (0x1 << 4))
32         printf("Right Control Pressed\n");
33     if (temp1 & (0x1 << 5))
34         printf("Right Shift Pressed\n");
35     if (temp1 & (0x1 << 6))
36         printf("Right Alt Pressed\n");
37     char alpha = data + 3;
38     printf("input: %c\n", (char)((int)alpha + ASCII_LOWERCASE_SUB));
39 }

二.如果失败了之后之后测试就会一直失败的问题:

  查找资料:如果不是EP0端点传输时,Device收到了不支持或者无效的请求,对应的EP将会在data或者status阶段返回STALL故障 —— 需要Host的EP0发送clear Halt指令才能重新启用这个EP( 也就是需要使用Libusb提供的clear_halt函数)

三. HID report

  这是标志一个设备是HID的重要方式:report数组:

  注意要区分:报告和报告描述符:前者是用来传输数据(在get report和set report命令,控制EP中传输)后者是对数据用途的说明,是一个数组;

  可以根据 HID设备描述符的官方文档 来写自己的HID report array;当然更方便的是结合使用官方提供的 Dt工具 生成更保险;

  是我对device,interface,endpoint的修改:

 1 /*
 2  * for maxPakcetSize0 for device descriptor
 3  * it means the mas packet size for endpoint 0 
 4  * for low: 8; for full: 8 or 16, 32, 65; for high : only can be 64
 5  */
 6 device_descriptor{
 7         .bcdUSB = 0x0210,                 //表示这个是HID设备
 8     .bDeviceClass = 0x00,            
 9     .bDeviceSubClass = 0x00,
10     .bDeviceProtocol = 0x00,
11 }
12 
13 /*
14  * bConfiguration Value must >= 0x01
15  * if == 0x00, after set configuration, enter not configured state
16  * bmAttributes in Config desc
17  * for usb2.0 bit7 reserved must 1
18  * bit6 = 1:means self-powered
19  * bit5 = 1:means Remote Wakeup
20  * rest must be 0
21  */
22 config_descriptor{
23         .bmAttributes = 0xA0,
24      .bMaxPower = 0x32,
25 }
26 
27 /*
28  * interfaceClass: class code : delivered by USB-IF; == bDeviceClass
29  * 0x03 means HID
30  * iInterface == 0 means there is no string descriptor
31  */
32 interface_descriptor{
33         .bInterfaceClass = 0x03,
34     .bInterfaceSubClass = 0x00,
35     .bInterfaceProtocol = 0x00,
36     .iInterface = 0x00,
37 }
38 
39 /*
40  * for hid descriptor type == 0x21
41  * bDesccriptorType: 0x21 means HID;
42  * bDescriptorType0 :  Lower level desciptor : 0x22 means report
43  */
44 hid_descriptor{
45         .bDescriptorType = 0x21,
46     .bDescriptorType0 = 0x22,
47     .wDescriptorLength0 = REPORT_DESC_SIZE,
48 }
49 
50 // 下面是使用的HID report结构:
51 0x05, 0x0c,          // USAGE PAGE 使用 Consumer Devices 这样就不会被OS直接占用,可以进行bulk等传输
52 0x09, 0x01,             // USAGE 使用 Consumer Control
53 0xa1, 0x01,             // Collection 选择 Application;
54         0x09, 0x00,     // USAGE 使用 Unassigned定义自己的report;
55 0xc0                        // End of Collection

四. Get. Set report 指令的使用:

  这一部分才是使用的精髓:之前使用多个都是中断传输;但是HID设备更常用或者说更应该使用控制节点传输的report命令:

  因为前者中断传输算是异步:需要另外开辟一个线程来等待监听;但是控制节点的类似于同步,对于Host来说更方便:

  参考:

  

  

 

  所以两者分别是 0xa1 0x01 和 0x21 0x09

  然后通过控制节点传输的方法就可以传输了

  并且注意:如果是对于HID设备传输时候(在Windows中)一定要将buffer的第一个Byte写为在report 数组中龟腚的ReportID(默认是0x00)才能被传输

       使用libusb中的interrupt_transfer如果判断device是hid设备将会转给hid_transfer函数,所以将ReportID设置为第一个字符非常重要。

五. hidapi踩坑:

  相比起Libusb:Hidapi并没有caim interface;以及判断是否被占用和clear_halt等命令;对于mouse之类的无能为力;

  并且提供的set report函数功能也很有限;不建议使用;但是比较简单。

 

 

 

 

  

 

原文地址:http://www.cnblogs.com/celesial-dancers/p/16876206.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性