我在生成HID描述符时遇到了一些问题。 我想使用ID1作为输入的简单报告,使用ID2作为64字节数据的输出。
我意识到尽管有rtfming和谷歌搜索,我仍然不知道HID描述符中的某些字段。
有人可以给我一个提示或手册,我可以找到所有描述符字段的含义吗?我所能找到的只是HID-mouse / joistick / keyboard的例子。
例如 - REPORT_SIZE - 是以字节还是以位为单位的大小?为什么还有REPORT_COUNT? 如果报告中有64个字节,LOGICAL_MAXIMUM必须是255或255 * 64?
我是否应该为每个报告编写LOGICAL_MAX和MIN?
或许这个(通过猜测生成)就足够了?
char ReportDescriptor[39] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x40, // REPORT_SIZE (64)
0x96, 0x00, 0x02, // REPORT_COUNT (512)
0x81, 0x82, // INPUT (Data,Var,Abs,Vol)
0x85, 0x02, // REPORT_ID (2)
0x09, 0x00, // USAGE (Undefined)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x40, // REPORT_SIZE (64)
0x96, 0x00, 0x02, // REPORT_COUNT (512)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol)
0xc0 // END_COLLECTION
};
答案 0 :(得分:17)
所有官方文档均可在usb.org上找到。要了解HID报告描述符,您需要阅读HID Information页面上的一些文档。特别是,您应该尝试理解:
话虽如此,该文件众所周知地是钝的,需要付出相当大的努力才能消化。
REPORT_SIZE是报告的大小,以位为单位而非字节。将REPORT_SIZE视为字段的宽度(以位为单位),将REPORT_COUNT视为字段数(该宽度)。这在“HID 1.11的设备类定义”文档,第6.2.2.7节“全局项目”中有所阐述,如下所示:
Global Item Tag One-byte Prefix Description
Report Size 0111 01 nn Unsigned integer specifying the size of the report
fields in bits. This allows the parser to build an
item map for the report handler to use. For more
information, see Section 8: Report Protocol.
作为指南,一个合理的(即我没有测试过)报告描述符描述了一个64字节的输入缓冲区(对于REPORT_ID为0x01的主机)和一个64字节的输出缓冲区(来自REPORT_ID为0x02的主机可以如下:
0x06, 0x00, 0xFF, // (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
0xA1, 0x01, // (MAIN) COLLECTION 0x01 Application (Usage=0x0: Page=, Usage=, Type=) <-- Warning: USAGE type should be CA (Application)
0x15, 0x00, // (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
0x26, 0xFF, 0x00, // (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
0x75, 0x08, // (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
0x85, 0x01, // (GLOBAL) REPORT_ID 0x01 (1)
0x95, 0x40, // (GLOBAL) REPORT_COUNT 0x40 (64) Number of fields
0x09, 0x01, // (LOCAL) USAGE 0xFF000001
0x81, 0x02, // (MAIN) INPUT 0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0x85, 0x02, // (GLOBAL) REPORT_ID 0x02 (2)
0x09, 0x01, // (LOCAL) USAGE 0xFF000001
0x91, 0x02, // (MAIN) OUTPUT 0x00000002 (64 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
0xC0, // (MAIN) END_COLLECTION Application
这对应于以下C语言结构定义:
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
uint8_t VEN_VendorDefined0001[64]; // FF00 0001 Value = 0 to 255
} inputReport01_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 02 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
uint8_t VEN_VendorDefined0001[64]; // FF00 0001 Value = 0 to 255
} outputReport02_t;
您是否应为每个报告指定LOGICAL_MINIMUM和LOGICAL_MAXIMUM?没有。
有些项目是GLOBAL(这意味着,由于报告描述符是按顺序解析的,它们的值保持不变,直到它们被另一个GLOBAL项目显式更改)而其他项目是LOCAL(这意味着它们的值在每次MAIN时都会重置为默认值遇到项目)。 LOGICAL_MINIMUM和LOGICAL_MAXIMUM都是GLOBAL项,因此如果希望更改值,则只需重新指定它们的值。在我看来,如果项目的官方名称以GLOBAL_,LOCAL_和MAIN_作为前缀,则规范会更清楚,但遗憾的是我们都必须遵守规范。
以上示例使用SourceForge上的免费工具hidrdd
答案 1 :(得分:6)
正如@aja所述,官方的USB文档相当迟钝。我创建了这个模板(主要是从这个页面的帮助)作为与自定义板通信的简单起点。 HID代码旨在替换虚拟COM端口协议。 HID的一大优势是不需要驱动程序。
uint8_t CUSTOM_HID_ReportDesc[REPORT_DESC_SIZE] =
{
0x06, 0x00, 0xFF, // Global Usage page = 0xFF00 (Vendor-defined pages are in the range 0xFF00 through 0xFFFF)
0x09, 0x01, // Local Usage (vendor usage 1)
0xA1, 0x01, // Main Collection (application) begin
0x15, 0x00, // Global Logical minimum (0) applies to each byte
0x26, 0xFF, 0x00, // Global Logical maximum (255)
0x75, 0x08, // Global Report Size (8 bits)
// 14 bytes | Output message 1 (sent from host to device)
0x85, 1, // Global Report ID (cannot be 0)
0x98, 64, // Global Report Count (number of Report Size fields, in this case 64 bytes)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x91, 0x02, // Main Output (data, array, absolute)
// 24 bytes | Input message 1 (sent from device to host)
0x85, 1, // Global Report ID (cannot be 0)
0x98, 64, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x81, 0x02, // Main Input (data, array, absolute)
// 34 bytes | Output message 2 (sent from host to device)
0x85, 2, // Global Report ID (cannot be 0)
0x98, 12, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x91, 0x02, // Main Output (data, array, absolute)
// 44 bytes | Input message 2 (sent from device to host)
0x85, 2, // Global Report ID (cannot be 0)
0x98, 57, // Global Report Count (number of Report Size fields)
0x19, 0x01, // Local Usage Minimum (each Report Count must be associated with a Usage)
0x19, 0x40, // Local Usage Maximum
0x81, 0x02, // Main Input (data, array, absolute)
// 54 bytes | End (add one byte)
0xC0 // Main Collection (application) end
}
有几点需要注意:
#define REPORT_DESC_SIZE (55)
)。在Windows端,我使用Mike O'Brien's HIDLibrary。 HID报告通常附有报告ID - 在HIDLibrary中,使用HidReport.ReportID
字段设置/获取值。在董事会方面,请记住报告的第一个字节是报告ID。
答案 2 :(得分:2)
我已经通过Win7检测到我的自定义隐藏设备(通过猜测和窃取来自示例):
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x00, // USAGE (Undefined)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x85, 0x01, // REPORT_ID (1)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x00, // USAGE (Undefined)
0x81, 0x82, // INPUT (Data,Var,Abs,Vol) - to the host
0x85, 0x02, // REPORT_ID (2)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
0x09, 0x00, // USAGE (Undefined)
0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol) - from the host
0xc0 // END_COLLECTION
}; /* CustomHID_ReportDescriptor */
我不确定它是否能正常工作。会看到。
答案 3 :(得分:0)
以下是Spec Sheet(或&#34;手册&#34;)的链接,供您阅读。
要回答您的一些问题,REPORT_SIZE
以比特指定,REPORT_COUNT
可用于指定多少&#34; Usages&#34;报告具有指定的属性。例如,您可以设置X
和Y
用法的属性,并将REPORT_COUNT
指定为2(一个用于X,一个用于Y),然后指定{{1将这些用法添加到报表中。然后继续描述其他用法。
另外,不要忘记使用字节对齐。由于INPUT
以位为单位指定,因此很容易忘记使用字节对齐。因此,如果一次使用仅为1位,则需要指定该字节中有7位未被使用,如果需要超过7位,则转移到下一次使用。
答案 4 :(得分:0)
HID报告描述符在键值对中。要理解它们,在这种情况下,请阅读HID规范和第6章。您在哪里找到这些值的来源以及它如何影响描述符?如果我们更改它们。
Key , value
--------------
0x85, 0x02, // REPORT_ID (2)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x40, // REPORT_COUNT (64)
@Trick: 如果您在理解REPORT_COUNT(0x95)和REPORT_SIZE(0x75)时遇到问题 然后,您可以想象为2D阵列。
Array[count][size] = Array[4][8] /* value are in [Bytes][bit] */
Where 4 represent total number of reports to be send and 8 shows size of each report.
即 结构报告 {
uint8_t report_1;
uint8_t report_2;
uint8_t report_3;
uint8_t report_4;
};