android - 16 位 HID 游戏手柄报告描述符提供了类似于 android 中的 8 位描述符的分辨率
问题描述
我正在为我的项目使用 MEMS 传感器。我正在研究 16 位 HID 游戏手柄报告描述符,它有 8 个按钮和 4 个轴(来自 MEMS 传感器的数据)。
首先,我使用了 8 位 HID 游戏手柄报告描述符并通过 BLE 发送数据。它已经通过 windows 和 android HTML5 游戏手柄测试器(http://html5gamepad.com/)进行了检查,并且两个操作系统都在游戏手柄测试器中提供了预期的数据。为了获得更好的分辨率,我更改了报告描述符并制作了 2 个字节的 HID 描述符,附在下面。此报告描述符在 windows 中提供预期的数据和分辨率,但在 android 端没有获得相同的输出。
输出:
Windows 中的 16 位数据分辨率:0.147723、0.148028、0.149737、0.150103、0.152056、0.154070、0.154957、0.156087、0.156146
Android中的16位数据分辨率:0.144566、0.153294、0.165441、0.170080、0.183691、0.191595、0.199957
在这里,我附上了 html5 游戏手柄测试器的屏幕截图(在 chrome 中)。在此处输入图像描述
它表明,我从传感器发送四元数数据,它给出了 4 轴值(X,Y,Z,W),初始状态为(0、0、0、1)。所以数据在游戏手柄测试器中介于 -1 到 1 之间。在 16 位中,我使用逻辑最小值:-32767 到逻辑最大值:32767
所以我怀疑HID报告描述符在android端有什么限制吗?
0x05, 0x01, //USAGE_PAGE (Generic Desktop)
0x09, 0x05, //USAGE (Game Pad)
0xa1, 0x01, //COLLECTION (APPLICATION)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, //USAGE_PAGE (Button)
0x19, 0x01, //USAGE_MINIMUM (Button1)
0x29, 0x08, //USAGE_MAXIMUM (Button 8)
0x15, 0x00, //LOGICAL_MINIMUM (0)
0x25, 0x01, //LOGICAL_MAXIMUM(1)
0x95, 0x08, //REPORT_COUNT (8)
0x75, 0x01, //REPORT_SIZE (1)
0x81, 0x02, //INPUT(Data, Var, Abs)
0x05, 0x01, //USAGE_PAGE (Generic Desktop)
0x09, 0x30, //USAGE (X)
0x09, 0x31, //USAGE (Y)
0x09, 0x32, //USAGE (Z)
0x09, 0x35, //USAGE (Rz)
0x16, 0x01, 0x80 //LOGICAL_MINIMUM(-32767)
0x26, 0xff, 0x7f //LOGICAL_MAXIMUM(32767)
0x75, 0x10, //REPORT_SIZE(16)
0x95, 0x04, //REPORT_COUNT(4)
0x81, 0x02, //INPUT(Data,Var,Abs)
0xc0, //END_Collection
0xc0 //END_Collection
我希望有人能够帮助解决这个问题。
谢谢,
迪维亚。
解决方案
我认为您可能不小心更新了评论而不是实际的报告描述符字节。当我解码您的描述符时,我得到:
//--------------------------------------------------------------------------------
// 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)
A1 00 (MAIN) COLLECTION 0x00 Physical (Usage=0x0: Page=, Usage=, Type=) <-- Error: COLLECTION must be preceded by a USAGE <-- Warning: USAGE type should be CP (Physical Collection)
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 10 (LOCAL) USAGE_MAXIMUM 0x00090010 Button 16 (Selector, On/Off Control, Momentary Control, or One Shot Control)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
95 10 (GLOBAL) REPORT_COUNT 0x10 (16) Number of fields
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (16 fields x 1 bit) 0=Data 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 30 (LOCAL) USAGE 0x00010030 X (Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (Dynamic Value)
09 32 (LOCAL) USAGE 0x00010032 Z (Dynamic Value)
09 33 (LOCAL) USAGE 0x00010033 Rx (Dynamic Value)
15 81 (GLOBAL) LOGICAL_MINIMUM 0x81 (-127)
25 7F (GLOBAL) LOGICAL_MAXIMUM 0x7F (127)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 04 (GLOBAL) REPORT_COUNT 0x04 (4) Number of fields
81 02 (MAIN) INPUT 0x00000002 (4 fields 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 Physical
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Button Page inputReport (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
// No REPORT ID byte
// Collection: GamePad
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 BTN_GamePadButton11 : 1; // Usage 0x0009000B: Button 11, Value = 0 to 1
uint8_t BTN_GamePadButton12 : 1; // Usage 0x0009000C: Button 12, Value = 0 to 1
uint8_t BTN_GamePadButton13 : 1; // Usage 0x0009000D: Button 13, Value = 0 to 1
uint8_t BTN_GamePadButton14 : 1; // Usage 0x0009000E: Button 14, Value = 0 to 1
uint8_t BTN_GamePadButton15 : 1; // Usage 0x0009000F: Button 15, Value = 0 to 1
uint8_t BTN_GamePadButton16 : 1; // Usage 0x00090010: Button 16, Value = 0 to 1
int8_t GD_GamePadX; // Usage 0x00010030: X, Value = -127 to 127
int8_t GD_GamePadY; // Usage 0x00010031: Y, Value = -127 to 127
int8_t GD_GamePadZ; // Usage 0x00010032: Z, Value = -127 to 127
int8_t GD_GamePadRx; // Usage 0x00010033: Rx, Value = -127 to 127
} inputReport_t;
尝试改用这个:
//--------------------------------------------------------------------------------
// 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)
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)
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 08 (LOCAL) USAGE_MAXIMUM 0x00090008 Button 8 (Selector, On/Off Control, Momentary Control, or One Shot Control)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
95 08 (GLOBAL) REPORT_COUNT 0x08 (8) Number of fields
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
81 02 (MAIN) INPUT 0x00000002 (8 fields x 1 bit) 0=Data 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 30 (LOCAL) USAGE 0x00010030 X (Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (Dynamic Value)
09 32 (LOCAL) USAGE 0x00010032 Z (Dynamic Value)
09 33 (LOCAL) USAGE 0x00010033 Rx (Dynamic Value)
16 0180 (GLOBAL) LOGICAL_MINIMUM 0x8001 (-32767)
26 FF7F (GLOBAL) LOGICAL_MAXIMUM 0x7FFF (32767)
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
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Button Page inputReport (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
// No REPORT ID byte
// Collection: GamePad Pointer
uint8_t BTN_GamePadPointerButton1 : 1; // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
uint8_t BTN_GamePadPointerButton2 : 1; // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
uint8_t BTN_GamePadPointerButton3 : 1; // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
uint8_t BTN_GamePadPointerButton4 : 1; // Usage 0x00090004: Button 4, Value = 0 to 1
uint8_t BTN_GamePadPointerButton5 : 1; // Usage 0x00090005: Button 5, Value = 0 to 1
uint8_t BTN_GamePadPointerButton6 : 1; // Usage 0x00090006: Button 6, Value = 0 to 1
uint8_t BTN_GamePadPointerButton7 : 1; // Usage 0x00090007: Button 7, Value = 0 to 1
uint8_t BTN_GamePadPointerButton8 : 1; // Usage 0x00090008: Button 8, Value = 0 to 1
int16_t GD_GamePadPointerX; // Usage 0x00010030: X, Value = -32767 to 32767
int16_t GD_GamePadPointerY; // Usage 0x00010031: Y, Value = -32767 to 32767
int16_t GD_GamePadPointerZ; // Usage 0x00010032: Z, Value = -32767 to 32767
int16_t GD_GamePadPointerRx; // Usage 0x00010033: Rx, Value = -32767 to 32767
} inputReport_t;
编辑:我将按钮数从 16 减少到 8 以匹配您对控制器的描述
推荐阅读
- python - Woocommerce API - 列出按国家/地区过滤的订单
- javascript - 使用 Javascript 在我的项目文件夹中打开一个文件
- python - 根据条件替换多列中的值
- azure-functions - CosmosDBTrigger 中的批处理文档是否具有已定义的顺序?
- azure - SharePoint/Azure - 在租户级别授予应用程序权限
- r - 如何并行化循环以替换 R 中的单元格
- hive - 在执行插入覆盖选择时从 Hive 中的文件中删除垃圾字符 *
- c# - EF Core 3.1 在迁移中没有返回正确的错误
- ocaml - 返回 OCAML 中参数的更改值
- angular - 将 Angular 应用程序的功能分支部署到 GitHub Pages 的正确方法是什么?