我一直在尝试使用this BTStack implemented by Bluekitchen通过经典的蓝牙将ESP-32微控制器连接到XBox One S无线控制器。我设法连接了两个设备(以ESP-32作为主机),并且可以从ESP-32上的控制器读取所有值。我现在正在尝试找出如何将有效报告发送到控制器。控制器在连接时报告的描述符是这样的:
05 01 09 05 A1 01 85 01 09 01 A1 00 09 30 09 31 15 00 27 FF FF 00 00 95 02 75 10 81 02 C0 09 01 A1 00 09 33 09 34 15 00 27 FF FF 00 00 95 02 75 10 81 02 C0 05 01 09 32 15 00 26 FF 03 95 01 75 0A 81 02 15 00 25 00 75 06 95 01 81 03 05 01 09 35 15 00 26 FF 03 95 01 75 0A 81 02 15 00 25 00 75 06 95 01 81 03 05 01 09 39 15 01 25 08 35 00 46 3B 01 66 14 00 75 04 95 01 81 42 75 04 95 01 15 00 25 00 35 00 45 00 65 00 81 03 05 09 19 01 29 0A 15 00 25 01 75 01 95 0A 81 02 15 00 25 00 75 06 95 01 81 03 05 01 09 80 85 02 A1 00 09 85 15 00 25 01 95 01 75 01 81 02 15 00 25 00 75 07 95 01 81 03 C0 05 0F 09 21 85 03 A1 02 09 97 15 00 25 01 75 04 95 01 91 02 15 00 25 00 75 04 95 01 91 03 09 70 15 00 25 64 75 08 95 04 91 02 09 50 66 01 10 55 0E 15 00 26 FF 00 75 08 95 01 91 02 09 A7 15 00 26 FF 00 75 08 95 01 91 02 65 00 55 00 09 7C 15 00 26 FF 00 75 08 95 01 91 02 C0 85 04 05 06 09 20 15 00 26 FF 00 75 08 95 01 81 02 C0
当我通过this translator运行此转储时,由于该问题很长,因此我在问题末尾得到了可读的输出。这里只列出了HID描述符的输出报告格式:
0x05, 0x0F, // Usage Page (PID Page)
0x09, 0x21, // Usage (0x21)
0x85, 0x03, // Report ID (3)
0xA1, 0x02, // Collection (Logical)
0x09, 0x97, // Usage (0x97)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x70, // Usage (0x70)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x64, // Logical Maximum (100)
0x75, 0x08, // Report Size (8)
0x95, 0x04, // Report Count (4)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x50, // Usage (0x50)
0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: Seconds)
0x55, 0x0E, // Unit Exponent (-2)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0xA7, // Usage (0xA7)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x65, 0x00, // Unit (None)
0x55, 0x00, // Unit Exponent (0)
0x09, 0x7C, // Usage (0x7C)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
我对HID标准的理解将表明描述符的这一部分是无效的,因为Usage (0x70)
后跟Report Count (4)
,这是我用来调试为什么它不起作用的btstack解析器然后必须尝试将4个字节匹配为单个用法,据我所知无法做到这一点。当前,我要发送给控制器(和调试时解析器)的报告是0x03, 0xF0, 0x64, 0x64, 0x64, 0x64, 0xFF, 0x10, 0x05
,其中0x03
表示报告ID,以下值表示我要发送的参数控制隆隆声马达。 4个0x64
值是应该映射为4种用法的4个字节,但是根据HID描述符,仅对应于1种用法0x70
。目前,解析器在找到第一个0x64
之后停止并声称已完成。
我认为这个HID描述符无效是我错了吗?如果是,是否有人知道我应该发送什么报告来匹配此HID描述符模板。很抱歉这个问题的冗长。
预先感谢, 理查德
完全可读的HID描述符输出:
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x05, // Usage (Game Pad)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
0x95, 0x02, // Report Count (2)
0x75, 0x10, // Report Size (16)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x33, // Usage (Rx)
0x09, 0x34, // Usage (Ry)
0x15, 0x00, // Logical Minimum (0)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
0x95, 0x02, // Report Count (2)
0x75, 0x10, // Report Size (16)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x32, // Usage (Z)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x95, 0x01, // Report Count (1)
0x75, 0x0A, // Report Size (10)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x06, // Report Size (6)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x35, // Usage (Rz)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x95, 0x01, // Report Count (1)
0x75, 0x0A, // Report Size (10)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x06, // Report Size (6)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x39, // Usage (Hat switch)
0x15, 0x01, // Logical Minimum (1)
0x25, 0x08, // Logical Maximum (8)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x66, 0x14, 0x00, // Unit (System: English Rotation, Length: Centimeter)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x35, 0x00, // Physical Minimum (0)
0x45, 0x00, // Physical Maximum (0)
0x65, 0x00, // Unit (None)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (0x01)
0x29, 0x0A, // Usage Maximum (0x0A)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x0A, // Report Count (10)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x06, // Report Size (6)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x80, // Usage (Sys Control)
0x85, 0x02, // Report ID (2)
0xA1, 0x00, // Collection (Physical)
0x09, 0x85, // Usage (Sys Main Menu)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x01, // Report Count (1)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x07, // Report Size (7)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x05, 0x0F, // Usage Page (PID Page)
0x09, 0x21, // Usage (0x21)
0x85, 0x03, // Report ID (3)
0xA1, 0x02, // Collection (Logical)
0x09, 0x97, // Usage (0x97)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x00, // Logical Maximum (0)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x70, // Usage (0x70)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x64, // Logical Maximum (100)
0x75, 0x08, // Report Size (8)
0x95, 0x04, // Report Count (4)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x50, // Usage (0x50)
0x66, 0x01, 0x10, // Unit (System: SI Linear, Time: Seconds)
0x55, 0x0E, // Unit Exponent (-2)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0xA7, // Usage (0xA7)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x65, 0x00, // Unit (None)
0x55, 0x00, // Unit Exponent (0)
0x09, 0x7C, // Usage (0x7C)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
0x85, 0x04, // Report ID (4)
0x05, 0x06, // Usage Page (Generic Dev Ctrls)
0x09, 0x20, // Usage (Battery Strength)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
答案 0 :(得分:0)
事实证明,由于电池“电量不足”,控制器已禁用了振动电机,并且将问题中描述的报告(开始时带有0xA2)发送给了我更换电池后的预期效果。我仍然不确定HID描述符实际上在语法上是否有效,但是控制器至少要执行我现在想要的操作!
答案 1 :(得分:0)
我知道您已经找到了问题,但是其他人可能对此很感兴趣。我用hidrdd解码了HID描述符(指出错误并提出改进建议)。结果如下:
//--------------------------------------------------------------------------------
// Report descriptor data in hex (length 306 bytes)
//--------------------------------------------------------------------------------
// 05010905 A1018501 0901A100 09300931 150027FF FF000095 02751081 02C00901
// A1000933 09341500 27FFFF00 00950275 108102C0 05010932 150026FF 03950175
// 0A810215 00250075 06950181 03050109 35150026 FF039501 750A8102 15002500
// 75069501 81030501 09391501 25083500 463B0166 14007504 95018142 75049501
// 15002500 35004500 65008103 05091901 290A1500 25017501 950A8102 15002500
// 75069501 81030501 09808502 A1000985 15002501 95017501 81021500 25007507
// 95018103 C0050F09 218503A1 02099715 00250175 04950191 02150025 00750495
// 01910309 70150025 64750895 04910209 50660110 550E1500 26FF0075 08950191
// 0209A715 0026FF00 75089501 91026500 5500097C 150026FF 00750895 019102C0
// 85040506 09201500 26FF0075 08950181 02C0
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 05 (LOCAL) USAGE 0x00010005 Game Pad (Application Collection)
A1 01 (MAIN) COLLECTION 0x01 Application (Usage=0x00010005: Page=Generic Desktop Page, Usage=Game Pad, Type=Application Collection)
85 01 (GLOBAL) REPORT_ID 0x01 (1)
09 01 (LOCAL) USAGE 0x00010001 Pointer (Physical Collection)
A1 00 (MAIN) COLLECTION 0x00 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=Physical Collection)
09 30 (LOCAL) USAGE 0x00010030 X (Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
27 FFFF0000 (GLOBAL) LOGICAL_MAXIMUM 0x0000FFFF (65535)
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (2 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 01 (LOCAL) USAGE 0x00010001 Pointer (Physical Collection)
A1 00 (MAIN) COLLECTION 0x00 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=Physical Collection)
09 33 (LOCAL) USAGE 0x00010033 Rx (Dynamic Value)
09 34 (LOCAL) USAGE 0x00010034 Ry (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
27 FFFF0000 (GLOBAL) LOGICAL_MAXIMUM 0x0000FFFF (65535) <-- Redundant: LOGICAL_MAXIMUM is already 65535
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields <-- Redundant: REPORT_COUNT is already 2
75 10 (GLOBAL) REPORT_SIZE 0x10 (16) Number of bits per field <-- Redundant: REPORT_SIZE is already 16
81 02 (MAIN) INPUT 0x00000002 (2 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
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page <-- Redundant: USAGE_PAGE is already 0x0001
09 32 (LOCAL) USAGE 0x00010032 Z (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF03 (GLOBAL) LOGICAL_MAXIMUM 0x03FF (1023)
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
75 0A (GLOBAL) REPORT_SIZE 0x0A (10) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (1 field x 10 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
75 06 (GLOBAL) REPORT_SIZE 0x06 (6) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
81 03 (MAIN) INPUT 0x00000003 (1 field x 6 bits) 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 <-- Redundant: USAGE_PAGE is already 0x0001
09 35 (LOCAL) USAGE 0x00010035 Rz (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF03 (GLOBAL) LOGICAL_MAXIMUM 0x03FF (1023)
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
75 0A (GLOBAL) REPORT_SIZE 0x0A (10) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (1 field x 10 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
75 06 (GLOBAL) REPORT_SIZE 0x06 (6) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
81 03 (MAIN) INPUT 0x00000003 (1 field x 6 bits) 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 <-- Redundant: USAGE_PAGE is already 0x0001
09 39 (LOCAL) USAGE 0x00010039 Hat switch (Dynamic Value)
15 01 (GLOBAL) LOGICAL_MINIMUM 0x01 (1)
25 08 (GLOBAL) LOGICAL_MAXIMUM 0x08 (8)
35 00 (GLOBAL) PHYSICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 35 00 with 34
46 3B01 (GLOBAL) PHYSICAL_MAXIMUM 0x013B (315)
66 1400 (GLOBAL) UNIT 0x0014 Rotation in degrees [1° units] (4=System=English Rotation, 1=Rotation=Degrees) <-- Info: Consider replacing 66 1400 with 65 14
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
81 42 (MAIN) INPUT 0x00000042 (1 field x 4 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 1=Null 0=NonVolatile 0=Bitmap
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field <-- Redundant: REPORT_SIZE is already 4
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
35 00 (GLOBAL) PHYSICAL_MINIMUM 0x00 (0) <-- Redundant: PHYSICAL_MINIMUM is already 0 <-- Info: Consider replacing 35 00 with 34
45 00 (GLOBAL) PHYSICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 45 00 with 44
65 00 (GLOBAL) UNIT 0x00 No unit (0=None) <-- Info: Consider replacing 65 00 with 64
81 03 (MAIN) INPUT 0x00000003 (1 field x 4 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
05 09 (GLOBAL) USAGE_PAGE 0x0009 Button Page
19 01 (LOCAL) USAGE_MINIMUM 0x00090001 Button 1 Primary/trigger (Selector, On/Off Control, Momentary Control, or One Shot Control)
29 0A (LOCAL) USAGE_MAXIMUM 0x0009000A Button 10 (Selector, On/Off Control, Momentary Control, or One Shot Control)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
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
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
75 06 (GLOBAL) REPORT_SIZE 0x06 (6) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
81 03 (MAIN) INPUT 0x00000003 (1 field x 6 bits) 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 80 (LOCAL) USAGE 0x00010080 System Control (Application Collection)
85 02 (GLOBAL) REPORT_ID 0x02 (2)
A1 00 (MAIN) COLLECTION 0x00 Physical (Usage=0x00010080: Page=Generic Desktop Page, Usage=System Control, Type=Application Collection) <-- Warning: USAGE type should be CP (Physical Collection)
09 85 (LOCAL) USAGE 0x00010085 System Main Menu (One Shot Control)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (1 field x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
75 07 (GLOBAL) REPORT_SIZE 0x07 (7) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
81 03 (MAIN) INPUT 0x00000003 (1 field x 7 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Physical
05 0F (GLOBAL) USAGE_PAGE 0x000F Physical Interface Device Page
09 21 (LOCAL) USAGE 0x000F0021 Set Effect Report (Logical Collection)
85 03 (GLOBAL) REPORT_ID 0x03 (3)
A1 02 (MAIN) COLLECTION 0x02 Logical (Usage=0x000F0021: Page=Physical Interface Device Page, Usage=Set Effect Report, Type=Logical Collection)
09 97 (LOCAL) USAGE 0x000F0097 DC Enable Actuators (Selector)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
91 02 (MAIN) OUTPUT 0x00000002 (1 field x 4 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 00 (GLOBAL) LOGICAL_MAXIMUM 0x00 (0) <-- Info: Consider replacing 25 00 with 24
75 04 (GLOBAL) REPORT_SIZE 0x04 (4) Number of bits per field <-- Redundant: REPORT_SIZE is already 4
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
91 03 (MAIN) OUTPUT 0x00000003 (1 field x 4 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 70 (LOCAL) USAGE 0x000F0070 Magnitude (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 64 (GLOBAL) LOGICAL_MAXIMUM 0x64 (100)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
91 02 (MAIN) OUTPUT 0x00000002 (4 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 50 (LOCAL) USAGE 0x000F0050 Duration (Dynamic Value)
66 0110 (GLOBAL) UNIT 0x1001 Time in seconds [1 s units] (1=System=SI Linear, 1=Time=Seconds)
55 0E (GLOBAL) UNIT_EXPONENT 0x0E (Unit Value x 10⁻²)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
91 02 (MAIN) OUTPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
09 A7 (LOCAL) USAGE 0x000F00A7 Start Delay (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255) <-- Redundant: LOGICAL_MAXIMUM is already 255
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
91 02 (MAIN) OUTPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
65 00 (GLOBAL) UNIT 0x00 No unit (0=None) <-- Info: Consider replacing 65 00 with 64
55 00 (GLOBAL) UNIT_EXPONENT 0x00 (Unit Value x 10⁰) <-- Info: Consider replacing 55 00 with 54
09 7C (LOCAL) USAGE 0x000F007C Loop Count (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255) <-- Redundant: LOGICAL_MAXIMUM is already 255
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
91 02 (MAIN) OUTPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Logical
85 04 (GLOBAL) REPORT_ID 0x04 (4)
05 06 (GLOBAL) USAGE_PAGE 0x0006 Generic Device Controls Page
09 20 (LOCAL) USAGE 0x00060020 Battery Strength (Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
26 FF00 (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255) <-- Redundant: LOGICAL_MAXIMUM is already 255
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields <-- Redundant: REPORT_COUNT is already 1
81 02 (MAIN) INPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport 01 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x01 (1)
// Collection: CA:GamePad CP:Pointer
uint16_t GD_GamePadPointerX; // Usage 0x00010030: X, Value = 0 to 65535
uint16_t GD_GamePadPointerY; // Usage 0x00010031: Y, Value = 0 to 65535
uint16_t GD_GamePadPointerRx; // Usage 0x00010033: Rx, Value = 0 to 65535
uint16_t GD_GamePadPointerRy; // Usage 0x00010034: Ry, Value = 0 to 65535
// Collection: CA:GamePad
uint16_t GD_GamePadZ : 10; // Usage 0x00010032: Z, Value = 0 to 1023
uint8_t : 6; // Pad
uint16_t GD_GamePadRz : 10; // Usage 0x00010035: Rz, Value = 0 to 1023
uint8_t : 6; // Pad
uint8_t GD_GamePadHatSwitch : 4; // Usage 0x00010039: Hat switch, Value = 1 to 8, Physical = (Value - 1) x 45 in degrees
uint8_t : 4; // Pad
uint8_t BTN_GamePadButton1 : 1; // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
uint8_t BTN_GamePadButton2 : 1; // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
uint8_t BTN_GamePadButton3 : 1; // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
uint8_t BTN_GamePadButton4 : 1; // Usage 0x00090004: Button 4, Value = 0 to 1
uint8_t BTN_GamePadButton5 : 1; // Usage 0x00090005: Button 5, Value = 0 to 1
uint8_t BTN_GamePadButton6 : 1; // Usage 0x00090006: Button 6, Value = 0 to 1
uint8_t BTN_GamePadButton7 : 1; // Usage 0x00090007: Button 7, Value = 0 to 1
uint8_t BTN_GamePadButton8 : 1; // Usage 0x00090008: Button 8, Value = 0 to 1
uint8_t BTN_GamePadButton9 : 1; // Usage 0x00090009: Button 9, Value = 0 to 1
uint8_t BTN_GamePadButton10 : 1; // Usage 0x0009000A: Button 10, Value = 0 to 1
uint8_t : 6; // Pad
} inputReport01_t;
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport 02 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x02 (2)
// Collection: CA:GamePad CP:SystemControl
uint8_t GD_GamePadSystemControlSystemMainMenu : 1; // Usage 0x00010085: System Main Menu, Value = 0 to 1
uint8_t : 7; // Pad
} inputReport02_t;
//--------------------------------------------------------------------------------
// Generic Device Controls Page inputReport 04 (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x04 (4)
// Collection: CA:GamePad
uint8_t GEN_GamePadBatteryStrength; // Usage 0x00060020: Battery Strength, Value = 0 to 255
} inputReport04_t;
//--------------------------------------------------------------------------------
// Physical Interface Device Page outputReport 03 (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x03 (3)
// Collection: CA:GamePad CL:SetEffectReport
uint8_t PID_GamePadSetEffectReportDcEnableActuators : 4; // Usage 0x000F0097: DC Enable Actuators, Value = 0 to 1
uint8_t : 4; // Pad
uint8_t PID_GamePadSetEffectReportMagnitude[4]; // Usage 0x000F0070: Magnitude, Value = 0 to 100
uint8_t PID_GamePadSetEffectReportDuration; // Usage 0x000F0050: Duration, Value = 0 to 255, Physical = Value in 10⁻² s units
uint8_t PID_GamePadSetEffectReportStartDelay; // Usage 0x000F00A7: Start Delay, Value = 0 to 255, Physical = Value in 10⁻² s units
uint8_t PID_GamePadSetEffectReportLoopCount; // Usage 0x000F007C: Loop Count, Value = 0 to 255
} outputReport03_t;
报告描述符似乎一般都可以。我可以将其从306个字节优化到仅191个字节-表示完全相同的数据流(见下文)。
至于0x70的使用情况,在我看来,可以使用4位DcEnableActuators用法(0x97)启用4个执行器。所以我想您应该发送:
0x03, 0x0F, 0x64, 0x64, 0x64, 0x64, 0xFF, 0x10, 0x05
以启用全部四个,而不是:
0x03, 0xF0, 0x64, 0x64, 0x64, 0x64, 0xFF, 0x10, 0x05
只是为了好玩,这是他们可以改用的报告描述符的优化版本:
//--------------------------------------------------------------------------------
// Report descriptor data in hex (length 191 bytes)
//--------------------------------------------------------------------------------
// 05010905 A1018501 0901A100 09300931 09330934 1427FFFF 00009504 75108102
// C0093226 FF039501 750A8102 24750681 03093526 FF03750A 81022475 06810309
// 39150125 0834463B 01651475 04814214 24446481 03050919 01290A25 01750195
// 0A810224 75069501 81030501 09808502 A1000985 25017501 81022475 078103C0
// 050F0921 8503A102 09972501 75049102 24910309 70256475 08950491 02095066
// 0110550E 26FF0095 01910209 A7910264 54097C91 02C08504 05060920 8102C0