HID USB 控制传输 (Windows)
HID USB control transfer (Windows)
最近,我开始学习如何在 Windows 10 上与 HID 设备通信。
但我有几个问题。
根据 Window 的文档,HidD_SetOutputReport
必须将 ReportBuffer
参数的第一个字节设置为报告 ID 或 0x00
.
因为我的设备的 HID 报告描述符已经声明了一些报告 ID,所以当我使用 HidD_setoutputreport
而不是 0x00
时我必须设置报告 ID?
当我使用报告 ID 0x80 作为 buf[0]
时,例如:0x80 0x02 0x00 ...... 0x00(我的 Capabilities.OutputReportByteLength
是 64)
我的密码是ret = HidD_SetOutputReport(handle->device_handle, buf2, 65)
但我总是这样发送数据(在Bus Hound):
64 OUT 80 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................ 4.1.0
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 ................ 4.1.16
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
4.1.32
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
4.1.48
我认为它应该发送 buf[1] to buf[64]
而不是 buf[0] to buf[63]
,所以我尝试了 ret = HidD_SetOutputReport(handle->device_handle, buf2, 64)
,但结果是一样的。
这是我的输入和输出的 HID 报告描述符:
Usage Page (Generic Desktop) 05 01
Logical Minimum (0) 15 00
Usage (Joystick) 09 04
Collection (Application) A1 01
Report ID (48) 85 30
Usage Page (Generic Desktop) 05 01
Usage Page (Button) 05 09
Usage Minimum (Button 1) 19 01
Usage Maximum (Button 10) 29 0A
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (10) 95 0A
Unit Exponent (0) 55 00
Unit (None) 65 00
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Button) 05 09
Usage Minimum (Button 11) 19 0B
Usage Maximum (Button 14) 29 0E
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (4) 95 04
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Size (1) 75 01
Report Count (2) 95 02
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Usage (Generic Desktop:Pointer) 0B 01 00 01 00
Collection (Physical) A1 00
Usage (Generic Desktop:X) 0B 30 00 01 00
Usage (Generic Desktop:Y) 0B 31 00 01 00
Usage (Generic Desktop:Z) 0B 32 00 01 00
Usage (Generic Desktop:Rz) 0B 35 00 01 00
Logical Minimum (0) 15 00
Logical Maximum (65535) 27 FF FF 00 00
Report Size (16) 75 10
Report Count (4) 95 04
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
End Collection C0
Usage (Generic Desktop:Hat Switch) 0B 39 00 01 00
Logical Minimum (0) 15 00
Logical Maximum (7) 25 07
Physical Minimum (0) 35 00
Physical Maximum (315) 46 3B 01
Unit (Eng Rot: Degree) 65 14
Report Size (4) 75 04
Report Count (1) 95 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Button) 05 09
Usage Minimum (Button 15) 19 0F
Usage Maximum (Button 18) 29 12
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (4) 95 04
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Size (8) 75 08
Report Count (52) 95 34
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Usage Page (Vendor-Defined 1) 06 00 FF
Report ID (33) 85 21
Usage (Vendor-Defined 1) 09 01
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Report ID (129) 85 81
Usage (Vendor-Defined 2) 09 02
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Report ID (1) 85 01
Usage (Vendor-Defined 3) 09 03
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (16) 85 10
Usage (Vendor-Defined 4) 09 04
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (128) 85 80
Usage (Vendor-Defined 5) 09 05
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (130) 85 82
Usage (Vendor-Defined 6) 09 06
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
End Collection C0
I can't really comment on the Windows API (I've never used it), but I
know that if you specify a report id in your HID report descriptor
then the report id occupies the first byte of your packet and the rest
of the packet is your payload otherwise your packet is all payload and
no REPORT_ID is sent. In your case, your RD specifies a REPORT_ID and
63 byte payload, so I would specify a length of 64, and put the
REPORT_ID in the first byte.
The report id is transmitted to the end point so that it can know how
to interpret each report
我已经检查了你的报告描述符,我可以提出一些调整建议,以减少未来悲伤的可能性。
- 从输入报告中删除 52 字节的 pad。它只会被主机忽略,因此无需从您的设备发送它。
- 使用较短的使用代码来减小报告描述符的大小。如果您的设备内存不足,这可能很重要。
- 不需要时重置物理单位。如果您不这样做,那么物理单位将应用于所有后续项目 - 这可能不合适(例如,长度以英寸为单位的 on/off 开关)。我已通过使用 PUSH 保存全局变量并使用 POP 稍后在方便的时候恢复它们来完成此操作。
- 在您的输出报告中指定数据(不是常数)。我真的不确定这是否有任何区别,但你永远不知道,某些未来的 USB 驱动程序可能会选择在发送数据包之前将任何 CONSTANT 字段设置为空,这会导致痛苦。
执行上述操作后,报告描述符大小从 203 字节减少到仅 133 字节:
//--------------------------------------------------------------------------------
// Report descriptor data in hex (length 133 bytes)
//--------------------------------------------------------------------------------
// 05011409 04A10185 30050925 017501A4 1901290A 950A8102 190B290E 95048102
// 95028103 05010901 A0093009 31093209 3527FFFF 00007510 95048102 C0093925
// 0734463B 01651475 04950181 02B4190F 29129504 810226FF 00750895 3F0600FF
// 85210901 81028581 09028102 85010903 91828510 09049182 85800905 91828582
// 09069182 C0
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
14 (GLOBAL) LOGICAL_MINIMUM (0) <-- Redundant: LOGICAL_MINIMUM is already 0
09 04 (LOCAL) USAGE 0x00010004 Joystick (CA=Application Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x00010004: Page=Generic Desktop Page, Usage=Joystick, Type=CA)
85 30 (GLOBAL) REPORT_ID 0x30 (48) '0'
05 09 (GLOBAL) USAGE_PAGE 0x0009 Button Page
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
A4 (GLOBAL) PUSH USAGE_PAGE=0x0009 LOGICAL(MIN=0,MAX=1) PHYSICAL(MIN=0,MAX=0) UNIT(0x0,EXP=0) REPORT(ID=0x30,SIZE=1,COUNT=0)
19 01 (LOCAL) USAGE_MINIMUM 0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot)
29 0A (LOCAL) USAGE_MAXIMUM 0x0009000A Button 10 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 0A (GLOBAL) REPORT_COUNT 0x0A (10) Number of fields
81 02 (MAIN) INPUT 0x00000002 (10 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
19 0B (LOCAL) USAGE_MINIMUM 0x0009000B Button 11 (MULTI=Selector, On/Off, Momentary, or One Shot)
29 0E (LOCAL) USAGE_MAXIMUM 0x0009000E Button 14 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 03 (MAIN) INPUT 0x00000003 (2 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 01 (LOCAL) USAGE 0x00010001 Pointer (CP=Physical Collection)
A0 (MAIN) COLLECTION 0x00000000 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=CP)
09 30 (LOCAL) USAGE 0x00010030 X (DV=Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (DV=Dynamic Value)
09 32 (LOCAL) USAGE 0x00010032 Z (DV=Dynamic Value)
09 35 (LOCAL) USAGE 0x00010035 Rz (DV=Dynamic Value)
27 FFFF0000 (GLOBAL) LOGICAL_MAXIMUM 0x0000FFFF (65535)
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 16 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Physical
09 39 (LOCAL) USAGE 0x00010039 Hat switch (DV=Dynamic Value)
25 07 (GLOBAL) LOGICAL_MAXIMUM 0x07 (7)
34 (GLOBAL) PHYSICAL_MINIMUM (0) <-- Redundant: PHYSICAL_MINIMUM is already 0
46 3B01 (GLOBAL) PHYSICAL_MAXIMUM 0x013B (315)
65 14 (GLOBAL) UNIT 0x00000014 Rotation in degrees [1° units] (4=System=English Rotation, 1=Rotation=Degrees)
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 02 (MAIN) INPUT 0x00000002 (1 field x 4 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
B4 (GLOBAL) POP USAGE_PAGE=0x0009 LOGICAL(MIN=0,MAX=1) PHYSICAL(MIN=0,MAX=0) UNIT(0x0,EXP=0) REPORT(ID=0x30,SIZE=1,COUNT=0)
19 0F (LOCAL) USAGE_MINIMUM 0x0009000F Button 15 (MULTI=Selector, On/Off, Momentary, or One Shot)
29 12 (LOCAL) USAGE_MAXIMUM 0x00090012 Button 18 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 3F (GLOBAL) REPORT_COUNT 0x3F (63) Number of fields
06 00FF (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
85 21 (GLOBAL) REPORT_ID 0x21 (33)
09 01 (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
81 02 (MAIN) INPUT 0x00000002 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
85 81 (GLOBAL) REPORT_ID 0x81 (129)
09 02 (LOCAL) USAGE 0xFF000002 <-- Warning: Undocumented usage
81 02 (MAIN) INPUT 0x00000002 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
85 01 (GLOBAL) REPORT_ID 0x01 (1)
09 03 (LOCAL) USAGE 0xFF000003 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 10 (GLOBAL) REPORT_ID 0x10 (16)
09 04 (LOCAL) USAGE 0xFF000004 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 80 (GLOBAL) REPORT_ID 0x80 (128)
09 05 (LOCAL) USAGE 0xFF000005 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 82 (GLOBAL) REPORT_ID 0x82 (130)
09 06 (LOCAL) USAGE 0xFF000006 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Button Page inputReport 30 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x30 (48) '0'
// Collection: Joystick
uint8_t BTN_JoystickButton1 : 1; // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
uint8_t BTN_JoystickButton2 : 1; // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
uint8_t BTN_JoystickButton3 : 1; // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
uint8_t BTN_JoystickButton4 : 1; // Usage 0x00090004: Button 4, Value = 0 to 1
uint8_t BTN_JoystickButton5 : 1; // Usage 0x00090005: Button 5, Value = 0 to 1
uint8_t BTN_JoystickButton6 : 1; // Usage 0x00090006: Button 6, Value = 0 to 1
uint8_t BTN_JoystickButton7 : 1; // Usage 0x00090007: Button 7, Value = 0 to 1
uint8_t BTN_JoystickButton8 : 1; // Usage 0x00090008: Button 8, Value = 0 to 1
uint8_t BTN_JoystickButton9 : 1; // Usage 0x00090009: Button 9, Value = 0 to 1
uint8_t BTN_JoystickButton10 : 1; // Usage 0x0009000A: Button 10, Value = 0 to 1
uint8_t BTN_JoystickButton11 : 1; // Usage 0x0009000B: Button 11, Value = 0 to 1
uint8_t BTN_JoystickButton12 : 1; // Usage 0x0009000C: Button 12, Value = 0 to 1
uint8_t BTN_JoystickButton13 : 1; // Usage 0x0009000D: Button 13, Value = 0 to 1
uint8_t BTN_JoystickButton14 : 1; // Usage 0x0009000E: Button 14, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
// Collection: Joystick Pointer
uint16_t GD_JoystickPointerX; // Usage 0x00010030: X, Value = 0 to 65535
uint16_t GD_JoystickPointerY; // Usage 0x00010031: Y, Value = 0 to 65535
uint16_t GD_JoystickPointerZ; // Usage 0x00010032: Z, Value = 0 to 65535
uint16_t GD_JoystickPointerRz; // Usage 0x00010035: Rz, Value = 0 to 65535
// Collection: Joystick
uint8_t GD_JoystickHatSwitch : 4; // Usage 0x00010039: Hat switch, Value = 0 to 7, Physical = Value x 45 in degrees
uint8_t BTN_JoystickButton15 : 1; // Usage 0x0009000F: Button 15, Value = 0 to 1
uint8_t BTN_JoystickButton16 : 1; // Usage 0x00090010: Button 16, Value = 0 to 1
uint8_t BTN_JoystickButton17 : 1; // Usage 0x00090011: Button 17, Value = 0 to 1
uint8_t BTN_JoystickButton18 : 1; // Usage 0x00090012: Button 18, Value = 0 to 1
} inputReport30_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 21 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x21 (33)
uint8_t VEN_Joystick0001[63]; // Usage 0xFF000001: , Value = 0 to 255
} inputReport21_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 81 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x81 (129)
uint8_t VEN_Joystick0002[63]; // Usage 0xFF000002: , Value = 0 to 255
} inputReport81_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 01 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: Joystick
uint8_t VEN_Joystick0003[63]; // Usage 0xFF000003: , Value = 0 to 255
} outputReport01_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 10 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x10 (16)
uint8_t VEN_Joystick0004[63]; // Usage 0xFF000004: , Value = 0 to 255
} outputReport10_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 80 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x80 (128)
uint8_t VEN_Joystick0005[63]; // Usage 0xFF000005: , Value = 0 to 255
} outputReport80_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 82 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x82 (130)
uint8_t VEN_Joystick0006[63]; // Usage 0xFF000006: , Value = 0 to 255
} outputReport82_t;
最近,我开始学习如何在 Windows 10 上与 HID 设备通信。
但我有几个问题。
根据 Window 的文档,HidD_SetOutputReport
必须将 ReportBuffer
参数的第一个字节设置为报告 ID 或 0x00
.
因为我的设备的 HID 报告描述符已经声明了一些报告 ID,所以当我使用 HidD_setoutputreport
而不是 0x00
时我必须设置报告 ID?
当我使用报告 ID 0x80 作为 buf[0]
时,例如:0x80 0x02 0x00 ...... 0x00(我的 Capabilities.OutputReportByteLength
是 64)
我的密码是ret = HidD_SetOutputReport(handle->device_handle, buf2, 65)
但我总是这样发送数据(在Bus Hound):
64 OUT 80 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4.1.0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4.1.16
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4.1.32
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 4.1.48
我认为它应该发送 buf[1] to buf[64]
而不是 buf[0] to buf[63]
,所以我尝试了 ret = HidD_SetOutputReport(handle->device_handle, buf2, 64)
,但结果是一样的。
这是我的输入和输出的 HID 报告描述符:
Usage Page (Generic Desktop) 05 01
Logical Minimum (0) 15 00
Usage (Joystick) 09 04
Collection (Application) A1 01
Report ID (48) 85 30
Usage Page (Generic Desktop) 05 01
Usage Page (Button) 05 09
Usage Minimum (Button 1) 19 01
Usage Maximum (Button 10) 29 0A
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (10) 95 0A
Unit Exponent (0) 55 00
Unit (None) 65 00
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Button) 05 09
Usage Minimum (Button 11) 19 0B
Usage Maximum (Button 14) 29 0E
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (4) 95 04
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Size (1) 75 01
Report Count (2) 95 02
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Usage (Generic Desktop:Pointer) 0B 01 00 01 00
Collection (Physical) A1 00
Usage (Generic Desktop:X) 0B 30 00 01 00 Usage (Generic Desktop:Y) 0B 31 00 01 00 Usage (Generic Desktop:Z) 0B 32 00 01 00 Usage (Generic Desktop:Rz) 0B 35 00 01 00 Logical Minimum (0) 15 00 Logical Maximum (65535) 27 FF FF 00 00 Report Size (16) 75 10 Report Count (4) 95 04 Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
End Collection C0
Usage (Generic Desktop:Hat Switch) 0B 39 00 01 00
Logical Minimum (0) 15 00
Logical Maximum (7) 25 07
Physical Minimum (0) 35 00
Physical Maximum (315) 46 3B 01
Unit (Eng Rot: Degree) 65 14
Report Size (4) 75 04
Report Count (1) 95 01
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Usage Page (Button) 05 09
Usage Minimum (Button 15) 19 0F
Usage Maximum (Button 18) 29 12
Logical Minimum (0) 15 00
Logical Maximum (1) 25 01
Report Size (1) 75 01
Report Count (4) 95 04
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Size (8) 75 08
Report Count (52) 95 34
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Usage Page (Vendor-Defined 1) 06 00 FF
Report ID (33) 85 21
Usage (Vendor-Defined 1) 09 01
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Report ID (129) 85 81
Usage (Vendor-Defined 2) 09 02
Report Size (8) 75 08
Report Count (63) 95 3F
Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03
Report ID (1) 85 01
Usage (Vendor-Defined 3) 09 03
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (16) 85 10
Usage (Vendor-Defined 4) 09 04
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (128) 85 80
Usage (Vendor-Defined 5) 09 05
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
Report ID (130) 85 82
Usage (Vendor-Defined 6) 09 06
Report Size (8) 75 08
Report Count (63) 95 3F
Output (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) 91 83
End Collection C0
I can't really comment on the Windows API (I've never used it), but I know that if you specify a report id in your HID report descriptor then the report id occupies the first byte of your packet and the rest of the packet is your payload otherwise your packet is all payload and no REPORT_ID is sent. In your case, your RD specifies a REPORT_ID and 63 byte payload, so I would specify a length of 64, and put the REPORT_ID in the first byte.
The report id is transmitted to the end point so that it can know how to interpret each report
我已经检查了你的报告描述符,我可以提出一些调整建议,以减少未来悲伤的可能性。
- 从输入报告中删除 52 字节的 pad。它只会被主机忽略,因此无需从您的设备发送它。
- 使用较短的使用代码来减小报告描述符的大小。如果您的设备内存不足,这可能很重要。
- 不需要时重置物理单位。如果您不这样做,那么物理单位将应用于所有后续项目 - 这可能不合适(例如,长度以英寸为单位的 on/off 开关)。我已通过使用 PUSH 保存全局变量并使用 POP 稍后在方便的时候恢复它们来完成此操作。
- 在您的输出报告中指定数据(不是常数)。我真的不确定这是否有任何区别,但你永远不知道,某些未来的 USB 驱动程序可能会选择在发送数据包之前将任何 CONSTANT 字段设置为空,这会导致痛苦。
执行上述操作后,报告描述符大小从 203 字节减少到仅 133 字节:
//--------------------------------------------------------------------------------
// Report descriptor data in hex (length 133 bytes)
//--------------------------------------------------------------------------------
// 05011409 04A10185 30050925 017501A4 1901290A 950A8102 190B290E 95048102
// 95028103 05010901 A0093009 31093209 3527FFFF 00007510 95048102 C0093925
// 0734463B 01651475 04950181 02B4190F 29129504 810226FF 00750895 3F0600FF
// 85210901 81028581 09028102 85010903 91828510 09049182 85800905 91828582
// 09069182 C0
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
14 (GLOBAL) LOGICAL_MINIMUM (0) <-- Redundant: LOGICAL_MINIMUM is already 0
09 04 (LOCAL) USAGE 0x00010004 Joystick (CA=Application Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x00010004: Page=Generic Desktop Page, Usage=Joystick, Type=CA)
85 30 (GLOBAL) REPORT_ID 0x30 (48) '0'
05 09 (GLOBAL) USAGE_PAGE 0x0009 Button Page
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
A4 (GLOBAL) PUSH USAGE_PAGE=0x0009 LOGICAL(MIN=0,MAX=1) PHYSICAL(MIN=0,MAX=0) UNIT(0x0,EXP=0) REPORT(ID=0x30,SIZE=1,COUNT=0)
19 01 (LOCAL) USAGE_MINIMUM 0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot)
29 0A (LOCAL) USAGE_MAXIMUM 0x0009000A Button 10 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 0A (GLOBAL) REPORT_COUNT 0x0A (10) Number of fields
81 02 (MAIN) INPUT 0x00000002 (10 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
19 0B (LOCAL) USAGE_MINIMUM 0x0009000B Button 11 (MULTI=Selector, On/Off, Momentary, or One Shot)
29 0E (LOCAL) USAGE_MAXIMUM 0x0009000E Button 14 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 03 (MAIN) INPUT 0x00000003 (2 fields x 1 bit) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 01 (LOCAL) USAGE 0x00010001 Pointer (CP=Physical Collection)
A0 (MAIN) COLLECTION 0x00000000 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=CP)
09 30 (LOCAL) USAGE 0x00010030 X (DV=Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (DV=Dynamic Value)
09 32 (LOCAL) USAGE 0x00010032 Z (DV=Dynamic Value)
09 35 (LOCAL) USAGE 0x00010035 Rz (DV=Dynamic Value)
27 FFFF0000 (GLOBAL) LOGICAL_MAXIMUM 0x0000FFFF (65535)
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 16 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Physical
09 39 (LOCAL) USAGE 0x00010039 Hat switch (DV=Dynamic Value)
25 07 (GLOBAL) LOGICAL_MAXIMUM 0x07 (7)
34 (GLOBAL) PHYSICAL_MINIMUM (0) <-- Redundant: PHYSICAL_MINIMUM is already 0
46 3B01 (GLOBAL) PHYSICAL_MAXIMUM 0x013B (315)
65 14 (GLOBAL) UNIT 0x00000014 Rotation in degrees [1° units] (4=System=English Rotation, 1=Rotation=Degrees)
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 02 (MAIN) INPUT 0x00000002 (1 field x 4 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
B4 (GLOBAL) POP USAGE_PAGE=0x0009 LOGICAL(MIN=0,MAX=1) PHYSICAL(MIN=0,MAX=0) UNIT(0x0,EXP=0) REPORT(ID=0x30,SIZE=1,COUNT=0)
19 0F (LOCAL) USAGE_MINIMUM 0x0009000F Button 15 (MULTI=Selector, On/Off, Momentary, or One Shot)
29 12 (LOCAL) USAGE_MAXIMUM 0x00090012 Button 18 (MULTI=Selector, On/Off, Momentary, or One Shot)
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 3F (GLOBAL) REPORT_COUNT 0x3F (63) Number of fields
06 00FF (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined
85 21 (GLOBAL) REPORT_ID 0x21 (33)
09 01 (LOCAL) USAGE 0xFF000001 <-- Warning: Undocumented usage
81 02 (MAIN) INPUT 0x00000002 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
85 81 (GLOBAL) REPORT_ID 0x81 (129)
09 02 (LOCAL) USAGE 0xFF000002 <-- Warning: Undocumented usage
81 02 (MAIN) INPUT 0x00000002 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
85 01 (GLOBAL) REPORT_ID 0x01 (1)
09 03 (LOCAL) USAGE 0xFF000003 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 10 (GLOBAL) REPORT_ID 0x10 (16)
09 04 (LOCAL) USAGE 0xFF000004 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 80 (GLOBAL) REPORT_ID 0x80 (128)
09 05 (LOCAL) USAGE 0xFF000005 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
85 82 (GLOBAL) REPORT_ID 0x82 (130)
09 06 (LOCAL) USAGE 0xFF000006 <-- Warning: Undocumented usage
91 82 (MAIN) OUTPUT 0x00000082 (63 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 1=Volatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Button Page inputReport 30 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x30 (48) '0'
// Collection: Joystick
uint8_t BTN_JoystickButton1 : 1; // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
uint8_t BTN_JoystickButton2 : 1; // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
uint8_t BTN_JoystickButton3 : 1; // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
uint8_t BTN_JoystickButton4 : 1; // Usage 0x00090004: Button 4, Value = 0 to 1
uint8_t BTN_JoystickButton5 : 1; // Usage 0x00090005: Button 5, Value = 0 to 1
uint8_t BTN_JoystickButton6 : 1; // Usage 0x00090006: Button 6, Value = 0 to 1
uint8_t BTN_JoystickButton7 : 1; // Usage 0x00090007: Button 7, Value = 0 to 1
uint8_t BTN_JoystickButton8 : 1; // Usage 0x00090008: Button 8, Value = 0 to 1
uint8_t BTN_JoystickButton9 : 1; // Usage 0x00090009: Button 9, Value = 0 to 1
uint8_t BTN_JoystickButton10 : 1; // Usage 0x0009000A: Button 10, Value = 0 to 1
uint8_t BTN_JoystickButton11 : 1; // Usage 0x0009000B: Button 11, Value = 0 to 1
uint8_t BTN_JoystickButton12 : 1; // Usage 0x0009000C: Button 12, Value = 0 to 1
uint8_t BTN_JoystickButton13 : 1; // Usage 0x0009000D: Button 13, Value = 0 to 1
uint8_t BTN_JoystickButton14 : 1; // Usage 0x0009000E: Button 14, Value = 0 to 1
uint8_t : 1; // Pad
uint8_t : 1; // Pad
// Collection: Joystick Pointer
uint16_t GD_JoystickPointerX; // Usage 0x00010030: X, Value = 0 to 65535
uint16_t GD_JoystickPointerY; // Usage 0x00010031: Y, Value = 0 to 65535
uint16_t GD_JoystickPointerZ; // Usage 0x00010032: Z, Value = 0 to 65535
uint16_t GD_JoystickPointerRz; // Usage 0x00010035: Rz, Value = 0 to 65535
// Collection: Joystick
uint8_t GD_JoystickHatSwitch : 4; // Usage 0x00010039: Hat switch, Value = 0 to 7, Physical = Value x 45 in degrees
uint8_t BTN_JoystickButton15 : 1; // Usage 0x0009000F: Button 15, Value = 0 to 1
uint8_t BTN_JoystickButton16 : 1; // Usage 0x00090010: Button 16, Value = 0 to 1
uint8_t BTN_JoystickButton17 : 1; // Usage 0x00090011: Button 17, Value = 0 to 1
uint8_t BTN_JoystickButton18 : 1; // Usage 0x00090012: Button 18, Value = 0 to 1
} inputReport30_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 21 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x21 (33)
uint8_t VEN_Joystick0001[63]; // Usage 0xFF000001: , Value = 0 to 255
} inputReport21_t;
//--------------------------------------------------------------------------------
// Vendor-defined inputReport 81 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x81 (129)
uint8_t VEN_Joystick0002[63]; // Usage 0xFF000002: , Value = 0 to 255
} inputReport81_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 01 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: Joystick
uint8_t VEN_Joystick0003[63]; // Usage 0xFF000003: , Value = 0 to 255
} outputReport01_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 10 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x10 (16)
uint8_t VEN_Joystick0004[63]; // Usage 0xFF000004: , Value = 0 to 255
} outputReport10_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 80 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x80 (128)
uint8_t VEN_Joystick0005[63]; // Usage 0xFF000005: , Value = 0 to 255
} outputReport80_t;
//--------------------------------------------------------------------------------
// Vendor-defined outputReport 82 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x82 (130)
uint8_t VEN_Joystick0006[63]; // Usage 0xFF000006: , Value = 0 to 255
} outputReport82_t;