如何在 Android 的 HID 游戏手柄中实现左右模拟触发器
How to implement Left and Right Analog Triggers in a HID Gamepad for Android
我正在开发具有 4 轴(14 位)、16 个按钮、2 个模拟触发器(1 字节)和一个 Hat Switch 的 HID 游戏手柄。我目前使用 X 轴和 Y 轴作为左模拟摇杆,Rx 轴和 Ry 轴用于右模拟摇杆,Z 轴和 Rz 轴用于左右触发器。我能够注册所有按钮和模拟读数(已在 linux 中使用 Gamepad tester in android and jstest-gtk 进行测试),但问题是在 (Android) 游戏中触发器应该是轴7 和轴 8,在我的例子中,Z 和 Rz 被指定为轴 14 和 15。我也尝试过使用加速度(轴:11),制动(轴:12),方向舵(轴:9)和油门(轴:10 ) 但轴 7 和 8(默认触发轴)未分配。
这是我的 HID 报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
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) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x33, // USAGE (Rx) - Right Analog Left(-ve), Right(+ve)
0x09, 0x34, // USAGE (Ry) - Right Analog Up(-ve), Down(+ve)
0x16, 0x01, 0xE0, // LOGICAL_MINIMUM (-8191)
0x26, 0xFF, 0x1F, // LOGICAL_MAXIMUM (8191)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0x32, // USAGE (Z) - L2 Trigger(Shoulderpads Trigger)
0x09, 0x35, // USAGE (Rz) - R2 Trigger(Shoulderpads Trigger)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0 // END_COLLECTION
非常感谢任何帮助,谢谢。
编辑:-
这是我根据Nipo指定的Anrdoid CDD文档尝试的新报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x32, // USAGE (Z) - Right Analog X
0x09, 0x35, // USAGE (Rz) - Right Analog Y
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x02, // USAGE_PAGE (Simulation Control)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0xC4, // USAGE(Acceleration)
0x09, 0xC5, // USAGE(Brake)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x09, 0x01, // USAGE(Button 1)
0x09, 0x02, // USAGE(Button 2)
0x09, 0x04, // USAGE(Button 4)
0x09, 0x05, // USAGE(Button 5)
0x09, 0x07, // USAGE(Button 7)
0x09, 0x08, // USAGE(Button 8)
0x09, 0x0E, // USAGE(Button 14)
0x09, 0x0F, // USAGE(Button 15)
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, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x65, 0x00, // Unit (None)
/*!@ The below section is taken from the page 31 of the document given
in the link below.
https://www.silabs.com/documents/public/application-notes/AN993.pdf
*/
0x05, 0x0C, // USAGE_PAGE (Consumer)
0x0A, 0x23, 0x02, // USAGE (AC Home)
0x0A, 0x24, 0x02, // USAGE (AC Back)
0x75, 0x01, // REPORT_SIZE(1)
0x95, 0x02, // REPORT_COUNT(2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x45, 0x01, // PHYSICAL_MAXIMUM (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (2)
0x75, 0x02, // REPORT_SIZE (1)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
这是对我有用的报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x32, // USAGE (Z) - Right Analog Left(-ve)Right(+ve)
0x09, 0x35, // USAGE (Rz)- Right Analog Up(-ve), Down(+ve)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x02, // USAGE_PAGE (Simulation Control)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0xC4, // USAGE(Acceleration)
0x09, 0xC5, // USAGE(Brake)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0x65, 0x00, // Unit (None)
0x05, 0x0C, // USAGE_PAGE (Consumer)
0x0A, 0x23, 0x02, // USAGE (AC Home)
0x0A, 0x24, 0x02, // USAGE (AC Back)
0x75, 0x01, // REPORT_SIZE(1)
0x95, 0x02, // REPORT_COUNT(2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x45, 0x01, // PHYSICAL_MAXIMUM (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (2)
0x75, 0x02, // REPORT_SIZE (1)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0 // END_COLLECTION
以下是我在测试时能够看到的一些发现:-
- 但是上面的描述符并不适用于所有游戏,我发现 Android 中的某些游戏可以选择 configure/customize 按钮映射,例如 DEAD TRIGGER 2 - Zombie Survival Shooter FPS, 但在此类游戏中,右摇杆的默认轴是 Rx 和 Ry,因此在此类游戏中,右摇杆和触发器(用于触发器的轴仍然是个谜)必须明确映射。
- 但在没有更改按钮映射选项的游戏中,此 HID 描述符甚至触发器也能正常工作(这让我相信这是定义描述符的正确方法)。
private static float getCenteredAxis(MotionEvent event,
InputDevice device, int axis, int historyPos) {
final InputDevice.MotionRange range =
device.getMotionRange(axis, event.getSource());
if (range != null) {
final float flat = range.getFlat();
final float value =
historyPos < 0 ? event.getAxisValue(axis):
event.getHistoricalAxisValue(axis, historyPos);
if (Math.abs(value) > flat) {
return value;
}
}
return 0;
}
// trigger_l
float l = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_BRAKE, historyPos);
textjoy7.setText(String.valueOf(l));
if (l == 0) {
l = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_LTRIGGER, historyPos);
}
//trigger_x
float r = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_GAS, historyPos);
textjoy8.setText(String.valueOf(r));
if (r == 0) {
r = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_RTRIGGER, historyPos);
}
我正在开发具有 4 轴(14 位)、16 个按钮、2 个模拟触发器(1 字节)和一个 Hat Switch 的 HID 游戏手柄。我目前使用 X 轴和 Y 轴作为左模拟摇杆,Rx 轴和 Ry 轴用于右模拟摇杆,Z 轴和 Rz 轴用于左右触发器。我能够注册所有按钮和模拟读数(已在 linux 中使用 Gamepad tester in android and jstest-gtk 进行测试),但问题是在 (Android) 游戏中触发器应该是轴7 和轴 8,在我的例子中,Z 和 Rz 被指定为轴 14 和 15。我也尝试过使用加速度(轴:11),制动(轴:12),方向舵(轴:9)和油门(轴:10 ) 但轴 7 和 8(默认触发轴)未分配。
这是我的 HID 报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
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) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x33, // USAGE (Rx) - Right Analog Left(-ve), Right(+ve)
0x09, 0x34, // USAGE (Ry) - Right Analog Up(-ve), Down(+ve)
0x16, 0x01, 0xE0, // LOGICAL_MINIMUM (-8191)
0x26, 0xFF, 0x1F, // LOGICAL_MAXIMUM (8191)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0x32, // USAGE (Z) - L2 Trigger(Shoulderpads Trigger)
0x09, 0x35, // USAGE (Rz) - R2 Trigger(Shoulderpads Trigger)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0 // END_COLLECTION
非常感谢任何帮助,谢谢。
编辑:- 这是我根据Nipo指定的Anrdoid CDD文档尝试的新报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x32, // USAGE (Z) - Right Analog X
0x09, 0x35, // USAGE (Rz) - Right Analog Y
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x02, // USAGE_PAGE (Simulation Control)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0xC4, // USAGE(Acceleration)
0x09, 0xC5, // USAGE(Brake)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x09, 0x01, // USAGE(Button 1)
0x09, 0x02, // USAGE(Button 2)
0x09, 0x04, // USAGE(Button 4)
0x09, 0x05, // USAGE(Button 5)
0x09, 0x07, // USAGE(Button 7)
0x09, 0x08, // USAGE(Button 8)
0x09, 0x0E, // USAGE(Button 14)
0x09, 0x0F, // USAGE(Button 15)
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, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x65, 0x00, // Unit (None)
/*!@ The below section is taken from the page 31 of the document given
in the link below.
https://www.silabs.com/documents/public/application-notes/AN993.pdf
*/
0x05, 0x0C, // USAGE_PAGE (Consumer)
0x0A, 0x23, 0x02, // USAGE (AC Home)
0x0A, 0x24, 0x02, // USAGE (AC Back)
0x75, 0x01, // REPORT_SIZE(1)
0x95, 0x02, // REPORT_COUNT(2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x45, 0x01, // PHYSICAL_MAXIMUM (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (2)
0x75, 0x02, // REPORT_SIZE (1)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
这是对我有用的报告描述符:-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // REPORT_ID (1)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X) - Left Analog Left(-ve),Right(+ve)
0x09, 0x31, // USAGE (Y) - Left Analog Up(-ve), Down(+ve)
0x09, 0x32, // USAGE (Z) - Right Analog Left(-ve)Right(+ve)
0x09, 0x35, // USAGE (Rz)- Right Analog Up(-ve), Down(+ve)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x02, // USAGE_PAGE (Simulation Control)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xFF, 0x00, // LOGICAL_MAXIMUM (255)
0x09, 0xC4, // USAGE(Acceleration)
0x09, 0xC5, // USAGE(Brake)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x10, // REPORT_COUNT (16)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x07, // LOGICAL_MAXIMUM (7)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM (315)
0x65, 0x14, // UNIT (Eng Rotation:Centimeter)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0x65, 0x00, // Unit (None)
0x05, 0x0C, // USAGE_PAGE (Consumer)
0x0A, 0x23, 0x02, // USAGE (AC Home)
0x0A, 0x24, 0x02, // USAGE (AC Back)
0x75, 0x01, // REPORT_SIZE(1)
0x95, 0x02, // REPORT_COUNT(2)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x45, 0x01, // PHYSICAL_MAXIMUM (1)
0x81, 0x42, // INPUT (Data,Var,Abs,Null)
0x95, 0x01, // REPORT_COUNT (2)
0x75, 0x02, // REPORT_SIZE (1)
0x81, 0x43, // INPUT (Cnst,Var,Abs,Null)
0xc0 // END_COLLECTION
以下是我在测试时能够看到的一些发现:-
- 但是上面的描述符并不适用于所有游戏,我发现 Android 中的某些游戏可以选择 configure/customize 按钮映射,例如 DEAD TRIGGER 2 - Zombie Survival Shooter FPS, 但在此类游戏中,右摇杆的默认轴是 Rx 和 Ry,因此在此类游戏中,右摇杆和触发器(用于触发器的轴仍然是个谜)必须明确映射。
- 但在没有更改按钮映射选项的游戏中,此 HID 描述符甚至触发器也能正常工作(这让我相信这是定义描述符的正确方法)。
private static float getCenteredAxis(MotionEvent event,
InputDevice device, int axis, int historyPos) {
final InputDevice.MotionRange range =
device.getMotionRange(axis, event.getSource());
if (range != null) {
final float flat = range.getFlat();
final float value =
historyPos < 0 ? event.getAxisValue(axis):
event.getHistoricalAxisValue(axis, historyPos);
if (Math.abs(value) > flat) {
return value;
}
}
return 0;
}
// trigger_l
float l = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_BRAKE, historyPos);
textjoy7.setText(String.valueOf(l));
if (l == 0) {
l = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_LTRIGGER, historyPos);
}
//trigger_x
float r = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_GAS, historyPos);
textjoy8.setText(String.valueOf(r));
if (r == 0) {
r = getCenteredAxis(event, mInputDevice,
MotionEvent.AXIS_RTRIGGER, historyPos);
}