evdev:找到游戏手柄轴的 "rest" 值
evdev: Find the "rest" value of a gamepad axis
如何找到游戏控制器任意轴的静止值?例如,在我的 Dualshock 4 上,这里是来自 evtest
:
的相关数据
Event code 0 (ABS_X)
Value 126
Min 0
Max 255
Flat 15
Event code 1 (ABS_Y)
Value 127
Min 0
Max 255
Flat 15
Event code 2 (ABS_Z)
Value 255
Min 0
Max 255
Flat 15
Event code 3 (ABS_RX)
Value 127
Min 0
Max 255
Flat 15
Event code 4 (ABS_RY)
Value 123
Min 0
Max 255
Flat 15
Event code 5 (ABS_RZ)
Value 0
Min 0
Max 255
Flat 15
在上面的例子中,我在运行 evtest
的时候一直在扣右边的扳机;因此,ABS_Z
的 value
变为 255 而不是 0。因此,由于我们不能为此目的使用 value
,他们是否有任何方法可以找出静止状态值是?
编辑: 我正在使用 libevdev
API 访问游戏手柄。可以从 input_absinfo
结构访问上面打印的信息。
这不能仅使用 evdev 提供的信息来一般地完成。
大多数游戏手柄使用前 6 个轴报告轴输入(摇杆和触发器):
ABS_X
ABS_Y
ABS_Z
ABS_RX
ABS_RY
ABS_RZ
左摇杆始终使用 ABS_X 和 ABS_Y。右摇杆有时使用 ABS_Z 和 ABS_RZ,但也可能使用 ABS_RX 和 ABS_RY,DS4 就是这种情况。对于摇杆轴,中性值介于最小值和最大值之间。
触发器通常使用剩下的任何东西。例如,如果右摇杆是 ABS_Z/ABS_RZ,那么触发器通常是 ABS_RX/ABS_RY。一些游戏手柄使用 ABS_BRAKE/ABS_GAS 代替。对于触发轴,中性值为 Min.
一些设备正确地报告摇杆轴的负最小值。例如,这是通过 USB 连接的 Xbox One 控制器的 evtest 得到的结果:
Event code 0 (ABS_X)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 1 (ABS_Y)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 2 (ABS_Z)
Value 0
Min 0
Max 1023
Event code 3 (ABS_RX)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 4 (ABS_RY)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 5 (ABS_RZ)
Value 0
Min 0
Max 1023
在这种情况下,驱动程序(xpad)识别设备并知道每个轴的逻辑范围,而不依赖于设备报告的信息。 DS4 的问题在于它是符合 HID 标准的游戏手柄。 HID 协议允许设备定义其逻辑范围,DS4 报告 0 作为每个轴的最小值。 DS4 驱动程序 (hid-sony) 按原样报告这些轴边界。
在 DS4 的 HID 报告描述符中定义摇杆轴的部分如下所示:
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x09, 0x35, // Usage (Rz)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x04, // Report Count (4)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
其中带有 "Usage" 的行定义每个轴输入使用哪些轴。 X、Y、Z 和 Rz 在 evdev 中被翻译成 ABS_X、ABS_Y、ABS_Z、ABS_RZ。轴范围由适用于所有四个轴的 "Logical Minimum" 和 "Logical Maximum" 定义。从"Report Size"我们也可以看出,每个轴都是一个8位的值
这是定义触发器的部分,请注意,逻辑范围的定义与摇杆轴的定义完全相同:
0x09, 0x33, // Usage (Rx)
0x09, 0x34, // Usage (Ry)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
由于这些歧义,您不能仅依靠启发式方法来区分扳机轴和摇杆轴。为了在一般情况下做到这一点,您需要一个已知游戏手柄的注册表,告诉您哪些输入映射到哪些轴。 SDL2 非常适合这个,它有大量的游戏手柄,包括许多控制台游戏手柄,如 DS4。
https://github.com/spurious/SDL-mirror/blob/master/src/joystick/controller_type.h#L72
如何找到游戏控制器任意轴的静止值?例如,在我的 Dualshock 4 上,这里是来自 evtest
:
Event code 0 (ABS_X)
Value 126
Min 0
Max 255
Flat 15
Event code 1 (ABS_Y)
Value 127
Min 0
Max 255
Flat 15
Event code 2 (ABS_Z)
Value 255
Min 0
Max 255
Flat 15
Event code 3 (ABS_RX)
Value 127
Min 0
Max 255
Flat 15
Event code 4 (ABS_RY)
Value 123
Min 0
Max 255
Flat 15
Event code 5 (ABS_RZ)
Value 0
Min 0
Max 255
Flat 15
在上面的例子中,我在运行 evtest
的时候一直在扣右边的扳机;因此,ABS_Z
的 value
变为 255 而不是 0。因此,由于我们不能为此目的使用 value
,他们是否有任何方法可以找出静止状态值是?
编辑: 我正在使用 libevdev
API 访问游戏手柄。可以从 input_absinfo
结构访问上面打印的信息。
这不能仅使用 evdev 提供的信息来一般地完成。
大多数游戏手柄使用前 6 个轴报告轴输入(摇杆和触发器):
ABS_X
ABS_Y
ABS_Z
ABS_RX
ABS_RY
ABS_RZ
左摇杆始终使用 ABS_X 和 ABS_Y。右摇杆有时使用 ABS_Z 和 ABS_RZ,但也可能使用 ABS_RX 和 ABS_RY,DS4 就是这种情况。对于摇杆轴,中性值介于最小值和最大值之间。
触发器通常使用剩下的任何东西。例如,如果右摇杆是 ABS_Z/ABS_RZ,那么触发器通常是 ABS_RX/ABS_RY。一些游戏手柄使用 ABS_BRAKE/ABS_GAS 代替。对于触发轴,中性值为 Min.
一些设备正确地报告摇杆轴的负最小值。例如,这是通过 USB 连接的 Xbox One 控制器的 evtest 得到的结果:
Event code 0 (ABS_X)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 1 (ABS_Y)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 2 (ABS_Z)
Value 0
Min 0
Max 1023
Event code 3 (ABS_RX)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 4 (ABS_RY)
Value 0
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 5 (ABS_RZ)
Value 0
Min 0
Max 1023
在这种情况下,驱动程序(xpad)识别设备并知道每个轴的逻辑范围,而不依赖于设备报告的信息。 DS4 的问题在于它是符合 HID 标准的游戏手柄。 HID 协议允许设备定义其逻辑范围,DS4 报告 0 作为每个轴的最小值。 DS4 驱动程序 (hid-sony) 按原样报告这些轴边界。
在 DS4 的 HID 报告描述符中定义摇杆轴的部分如下所示:
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x09, 0x35, // Usage (Rz)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x04, // Report Count (4)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
其中带有 "Usage" 的行定义每个轴输入使用哪些轴。 X、Y、Z 和 Rz 在 evdev 中被翻译成 ABS_X、ABS_Y、ABS_Z、ABS_RZ。轴范围由适用于所有四个轴的 "Logical Minimum" 和 "Logical Maximum" 定义。从"Report Size"我们也可以看出,每个轴都是一个8位的值
这是定义触发器的部分,请注意,逻辑范围的定义与摇杆轴的定义完全相同:
0x09, 0x33, // Usage (Rx)
0x09, 0x34, // Usage (Ry)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
由于这些歧义,您不能仅依靠启发式方法来区分扳机轴和摇杆轴。为了在一般情况下做到这一点,您需要一个已知游戏手柄的注册表,告诉您哪些输入映射到哪些轴。 SDL2 非常适合这个,它有大量的游戏手柄,包括许多控制台游戏手柄,如 DS4。
https://github.com/spurious/SDL-mirror/blob/master/src/joystick/controller_type.h#L72