如何直接在Linux系统中处理来自角色设备/游戏手柄的输入?

前端之家收集整理的这篇文章主要介绍了如何直接在Linux系统中处理来自角色设备/游戏手柄的输入?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在开发一个C程序,它使用 USB SNES controller输入基于RPM的分发.有没有人知道的库可以让它更容易与之交互,或者某些工具(joydev?)允许从设备中正确读取输入?我不需要整个游戏引擎;它仅用于来自角色设备的输入.

如果有一个库已经为我做了这个,那将是非常好的(我可以看看库自己做了什么),这可以通过一个链接关闭;否则,如果我必须自己做,我有一些具体问题:

问题:

>是否有一个已经存在的C库可以为我处理所有USB设备与游戏手柄的交互?我很乐意学习一个新的图书馆. (我的google-fu在这里失败了,如果这个过于明显,我道歉)
>每次确保打开正确的字符设备的适当方法是什么,因为事件*名称在会话/初始化之间发生变化?
>从我的应用程序处理来自这些设备的输入的适当方法是什么?在我们轮询字符设备时,只需确定按下每个按钮的数量是多少,并根据该输入执行操作?

简而言之,pseduo-C,这样的事情?

struct gamepad {
    int fd;
};

void get_input(struct gamepad *gamepad)
{
    char *buf;
    read(gamepad->fd,buf,48);
    switch(buf)
    {
        /* insert cases about handling differing buttons */
    }
}

设备如何呈现:

据我所见,我可以清楚地看到设备正确注册

$dmesg | tail
[198564.517068] usb 1-1: USB disconnect,device number 17
[198566.154324] usb 1-1: new low-speed USB device number 18 using xhci_hcd
[198566.323309] usb 1-1: New USB device found,idVendor=12bd,idProduct=d015
[198566.323312] usb 1-1: New USB device strings: Mfr=0,Product=2,SerialNumber=0
[198566.323313] usb 1-1: Product: 2Axes 11Keys Game  Pad
[198566.323792] usb 1-1: ep 0x81 - rounding interval to 64 microframes,ep desc says 80 microframes
[198566.328692] input: 2Axes 11Keys Game  Pad as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/input/input20
[198566.329036] hid-generic 0003:12BD:D015.0006: input,hidraw2: USB HID v1.10 Gamepad [2Axes 11Keys Game  Pad] on usb-0000:00:14.0-1/input0

如果我从设备读取,我可以看到它接收到一个中断,并且设备的输入只是使用hexdump:

$ls -lattr /dev/input/by-id/usb-12bd_2Axes_11Keys_Game_Pad-event-joystick 
lrwxrwxrwx. 1 root root 10 Jan 20 15:56 /dev/input/by-id/usb-12bd_2Axes_11Keys_Game_Pad-event-joystick -> ../event17

当我按下一个键(不释放)时,它似乎按预期工作,虽然我还无法解释从缓冲区返回的内容,如果没有上下文:

$hexdump /dev/input/event17 
0000000 f53a 569f 0000 0000 ac6c 000c 0000 0000
0000010 0003 0000 007f 0000 f53a 569f 0000 0000
0000020 ac6c 000c 0000 0000 0000 0000 0000 0000

在释放按钮时,您会收到类似的输出

0000030 f53c 569f 0000 0000 8be3 0007 0000 0000
0000040 0003 0001 007f 0000 f53c 569f 0000 0000
0000050 8be3 0007 0000 0000 0000 0000 0000 0000

这就是上方按下并释放的“向上”按钮.

这个调查:

为了确定其他库如何做到这一点,我想在python中做一个pygame的strace,看看它打开了什么设备以及它如何读取输入,但我还在学习如何使用它.我还看到一些关于joydev的模糊提及,但是,再一次,还没有学会如何使用它们.我现在正在这样做,如果我学到任何有价值的东西,我会发布结果.

除此之外,通过ASCII和hexdump观看按钮按下,我注意到他们有一个类似于基于按钮的输入,但似乎我的数字是上面输出结束时USB总线的中断计数(0xf53a到0xf53c).这似乎总是增加,并且,为了我的目的,可能会被丢弃.

还有可能我只是没有正确安装设备,因为我缺少一些模块或包(再次考虑一下joydev以及它应该做什么).我根本没有经常使用USB,所以这种类型的设备处理对我来说是新的.

搜索一下,我没有看到任何显示我正在寻找的东西,但我很乐意接受重定向到其他问题/主题阅读.

先感谢您!

解决方法

Linux中的USB输入设备通常由HID驱动程序(人机接口设备)处理,后者又转换为输入设备.

您可以将它们作为原始USB设备读取,但这通常不是一个好主意,因为它是一种非常低级别的协议.

如果您具有适当的权限,则可以读取/ dev / input / *设备.通常它们只能由root读取.如果您不想读取原始字节,那么有一些库(例如libinput)可以为您完成这项工作.

但是如果您的游戏在XWindows中运行(最有可能),那么您应该管理XInput设备.你可以用原始X调用来做到这一点,但是你可能更好地使用一些库,例如SDL.实际上SDL是pygame在引擎盖下使用的,所以我先尝试一下.

关于如何识别正确的设备,每个输入设备都有一个名称,甚至一些序列号(你在/ dev / input / by-id下看到那些符号链接这些通常足以识别设备,而不是输入数.

如果你想阅读原始输入设备,让我解释一下关于你的hexdumps的回合.您正在读取输入*设备,因此您将获得struct input_event类型的值(请参阅/usr/include/linux/input.h):

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

在您的第一个转储中,例如:

0000000 f53a 569f 0000 0000 ac6c 000c 0000 0000
0000010 0003 0000 007f 0000 f53a 569f 0000 0000
0000020 ac6c 000c 0000 0000 0000 0000 0000 0000

实际上有两个input_events.第一个是:

f53a 569f 0000 0000 ac6c 000c 0000 0000 0003 0000 007f 0000

前64个字节是时间戳.然后,0003(EV_ABS)表示绝对轴的移动,0000(ABS_X)是轴索引,0000007f是该轴的位置.绝对轴有时用于表示节流阀,操纵杆等(有时键盘作为操纵杆而不是4个按钮发送),并且您在第一次读取时获得位置以知道控件的位置,即使您不移动它.

第二个事件是:

f53a 569f 0000 0000 ac6c 000c 0000 0000 0000 0000 0000 0000

前64个字节是时间戳(与上面相同.然后0000(EV_SYN)表示同步事件.使用EV_SYN,其他字段未使用.EV_SYN用于将单个事件的不同值组合在一起,例如水平和鼠标或操纵杆的垂直轴.

您的其他转储类似,但适用于AXIS_Y.

我的猜测是键盘被视为数字操纵杆,两个轴ABS_X和ABS_Y,中间点为0x7F(范围从0x00到0xFF).您获得的消息只是中间点,即没有按下键盘按钮.也许你的hexdump输出正在被缓冲?

猜你在找的Linux相关文章