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

C 在Linux系统中,如何直接处理来自角色设备/游戏板的输入?,c,linux,input,gamepad,C,Linux,Input,Gamepad,我正在用C语言开发一个程序,在基于RPM的发行版上使用a作为输入。是否有一个任何人都知道的库使其更易于交互,或者有某种工具(joydev?)允许正确读取设备的输入?我不需要整个游戏引擎;它仅用于字符设备的输入 如果有一个图书馆已经为我做了这件事,那将是非常好的(我可以自己看看图书馆做了什么),这可以通过一个链接关闭;否则,如果我必须自己做这件事,我有几个具体问题: 问题是: 是否已有一个C库可以为我处理所有与gamepad的USB设备交互?我很乐意学习一个新的图书馆。(我的谷歌fu让我失望了,

我正在用C语言开发一个程序,在基于RPM的发行版上使用a作为输入。是否有一个任何人都知道的库使其更易于交互,或者有某种工具(joydev?)允许正确读取设备的输入?我不需要整个游戏引擎;它仅用于字符设备的输入

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

问题是:
  • 是否已有一个C库可以为我处理所有与gamepad的USB设备交互?我很乐意学习一个新的图书馆。(我的谷歌fu让我失望了,如果这太明显了,我道歉)
  • 当会话/初始化之间的事件*名称发生变化时,如何确保每次打开正确的字符设备
  • 从我的应用程序中处理这些设备输入的适当方法是什么?当我们在角色设备上轮询时,只需确定每按一次按钮的值,并根据该输入执行操作即可
简而言之,像这样的

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
,看看它打开了什么设备以及它如何读取输入,但我仍然在学习如何使用它。我也看到了一些关于乔伊德夫的模糊提及,但是,再一次,我还没有学会如何使用它们。我现在正在这样做,如果我学到了任何有价值的东西,我会发布结果

除此之外,通过ASCII和hexdump查看按钮按下情况,我注意到它们基于按钮有类似的输入,但我认为在上面的输出(0xf53a到0xf53c)末尾有USB总线中断计数。这似乎总是在增加,而且,出于我的目的,可能会被丢弃

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

搜索了一段时间后,我没有看到任何能准确显示我想要的东西,但我很乐意接受重定向到其他问题/主题的阅读


提前谢谢你

它是USB Hid设备,因此由Hid驱动程序处理-请参阅调试输出中的“USB Hid v1.10 Gamepad” 这里有各种各样的教程和例子来说明如何做到这一点

作为起点,您可以在“apt get install GOOGLE”上安装操纵杆,并查看源代码


libhidapi也是一个不错的选择。

Linux中的USB输入设备通常由HID驱动程序(人机界面设备)处理,而HID驱动程序又被转换为输入设备

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

如果您有适当的权限,您可以阅读
/dev/input/*
设备。通常,它们只能通过根来读取。如果您不想读取原始字节,那么有一些库(例如)可以为您执行此任务

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

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

如果您想读取原始输入设备,让我解释一下您的hextdump。您正在读取
input*
设备,因此您将获得
struct input\u event类型的值(请参见
/usr/include/linux/input.h
):

例如,在第一次转储中:

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\u事件
s。第一个是:

f53a 569f 0000 0000 ac6c 000c 0000 0000 0003 0000 007f 0000
前64个字节是时间戳。然后,
0003(EV\u ABS)
表示绝对轴的移动,
0000(ABS\u X)
是轴索引,
0000007f
是该轴的位置。绝对轴有时用于表示油门、操纵手柄等(有时键盘作为操纵杆而不是4个按钮发送),即使不移动控件,也可以在第一次读取时获得位置以了解控件的位置

第二项活动是:

f53a 569f 0000 0000 ac6c 000c 0000 0000 0000 0000 0000 0000
前64个字节是时间戳(同上)。然后
0000(EV_-SYN)
表示同步事件。使用
EV_-SYN
,其他字段未使用。
EV_-SYN
用于将单个事件的不同值组合在一起,例如鼠标或操纵杆的水平轴和垂直轴

您的另一个转储类似,但适用于轴Y

我的猜测是,键盘被视为一个数字操纵杆,两个轴
ABS_X
ABS_Y
,是
0x7F
中间点(范围从
0x00
0xFF
),您收到的消息是s
f53a 569f 0000 0000 ac6c 000c 0000 0000 0000 0000 0000 0000