【问题标题】:evdev: Find the "rest" value of a gamepad axisevdev:查找游戏手柄轴的“剩余”值
【发布时间】:2019-12-23 11:30:22
【问题描述】:

如何找到游戏控制器任意轴的静止值是多少?例如,在我的 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_Zvalue 变为 255 而不是 0。所以,既然我们不能为此目的使用 value,那么他们有什么方法可以找出静态值是多少?


编辑:我正在使用libevdev API 来访问游戏手柄。上面打印的信息可以从input_absinfo 结构中访问。

【问题讨论】:

    标签: linux game-engine gamepad evdev


    【解决方案1】:

    一般来说,仅使用 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 就是这种情况。对于摇杆轴,中性值介于 Min 和 Max 之间。

    触发器通常使用剩下的任何东西。例如,如果右摇杆是 ABS_Z/ABS_RZ,那么触发器通常是 ABS_RX/ABS_RY。一些游戏手柄使用 ABS_BRAKE/ABS_GAS 代替。对于触发轴,中性值为 Min。

    某些设备正确地报告拇指杆轴的负最小值。例如,下面是 evtest 为通过 USB 连接的 Xbox One 控制器获得的结果:

    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。轴范围由适用于所有四个轴的“逻辑最小值”和“逻辑最大值”定义。从“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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      相关资源
      最近更新 更多