本帖最后由 zn123717885 于 2013-10-18 14:24 编辑
USB报表难点剖析 USB 报表比较难理解,经无数次试验,有了点心得,分享一下。 首先是 用法页、用法、开集合、关集合这4个。 先简化一下: RRR = 报表数组 Upg = 用法页, U = 用法, ( = 开集合, ) = 关集合, 那么:一个RRR必须先整个定义UpgU即:RRR = UpgU(……内容……)。
Upg:是HID协议定义的用途大类,有很多种,其中有个为自定义(undefine), U :是每个用途大类内的具体子分类,大类不同子类定义也不同, 有些子类中有自定义(undefine)。 自定义就是可以按自己的意思来定义数据用途。但HID不处理,得我们自己处理数据,上位机必须要编程支持才行哈。 上面说的很好理解,下面关键的来了哈!注意理解。
当RRR需包含不同UpgU时则需嵌套在总()切换。比如鼠标和键盘的用法切换。 UpgU // 用法1 ( // 开集合 …….. // 这里内容为用法1 U // 用法2 (切换了用途子类) …….. // 这里内容为用法2 UpgU // 用法3(切换了用途大类和子类) …….. // 这里内容为用法3 ) // 关集合
一般来说Upg切换了,U也会变,但特例还是有的,如自定义(undefine)则可不管。建议一起切换为妙。看着也清楚明了对吧。当然你也可以分几个RRR来说明,就是有点麻烦,需要在程序中上传不同RRR。
Upg、U 被称为全局标签,即切换后就有效,直到下个相同全局标签出现或RRR结束。 HID协议还有几个全局标签,用法与Upg、U相同。 如:域位数 REPORT_SIZE 域个数 REPORT_COUNT 等….. 也有不能在总()之外使用的全局标签。 如 报告识别号 REPORT_ID 等…..
开、关集合也可在总UpgU(…..)内嵌套,但好像没啥必要。
下面用个具体简单例子来分析 unsigned char RRR[]= {
0x06, 0x00, 0xff, //总 Upg (自定义) 0x09, 0x00, //总 U (自定义) 0x75, 0x08, //总 REPORT_SIZE (8 bit)域位数 这里定义一个域为一字节 0x95, 10, // REPORT_COUNT域个数 一次传送10域即10字节 //这个报表上面的定义作用区域一直到RRR尾才终止 //因为一直没有用全局标签改变。 0xa1,0x02, // (开集合 开集合也有分类这里使用(Logical类)
//------------------------------------------------------------------------------------- 输入报告0x19, 0x00, // USAGE_MINIMUM (无用途小极限 )局部标签 0x29,0x00, // USAGE_MAXIMUM (无用途大极限 )局部标签0x85,1, // REPORT_ID 报告识别号 = 1全局标签 0x81, 0x02, // INPUT (Data,Var,Abs) 定义输入报告//------------------------------------------------------------------------------------- 输出报告 0x19, 0x00, // USAGE_MINIMUM (无用途小极限)局部标签0x29, 0x00, // USAGE_MAXIMUM (无用途大极限)局部标签 0x91, 0x02, // OUTPUT (Data,Var,Abs) 定义输出报告 //------------------------------------------------------------------------------------- 0xc0 // )关集合} 上面整个报表不知你看懂没,其实就是定义了2个报告,一个输入报告,一个输出报告。都是10字节数据,报告ID 都是 1 。那么传输数据的个数都是11字节,其中头字节为报告ID=1。 当然报告ID也可不要,因为只有一个输入,一个输出,多个输入或多个输出则必须用报告ID区分。如果不要ID则上传数据的个数只需10字节即可(HID协议默认ID=0)。
那两个局部标签在自定义Upg、U是必须的。局部标签作用区只到INPUT 或OUTPUT就结束,所以每个INPUT 或 OUTPUT前都需标注必要的局部标签。
另外HID还有个比较迷惑人的难点,就是HID与USB端点的关系:
HID只与接口相关,每个接口下可定义多个HID描述符和多个端点,但接口下所有报表只使用其中最小端点号(非0 且必须是中断类端点),端点不能区分报表。 如果报表想使用不同端点,则需将其挂在不同接口下,由接口来另外定义端点。但如此有必要吗?我想好像没啥必要吧! 比如:键盘和鼠标都可定义在一个接口下,用报表识别号来区分键盘和鼠标报表。甚至可加入一个调试报表,用于显示调试信息(但上位机要能区分报表识别号才行哈,要不都将键盘鼠标报表都当调试信息显示,那显示就乱了。这样就可不要串口来调试了)。
好了!!上面我说的都是我对HID报表标签的理解,其他具体的报表标签都还是比较好理解的。 总的来说我觉得HID就是一个数据传输平台,USB不过就是它的一个载体(例如也可用蓝牙作HID的载体),并且HID已将一些应用分类打包好,这样我们向支持HID的系统传送数据时就不需开发驱动程序了,只需关心我们的设备开发即可。 |