我正在用C开发一个程序,它使用USB SNES controller来输入基于RPM的分发。是否存在任何人都知道的库使得这更容易与之交互,或者某些工具(joydev?)允许从设备中正确读取输入?我不需要整个游戏引擎;它仅用于来自角色设备的输入。
如果有一个库已经为我做了这个,那将是非常好的(我可以看看我自己做了什么),这可以通过一个链接关闭;否则,如果我必须自己做,我有一些具体的问题:
简而言之,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,所以这种类型的设备处理对我来说是新的。
搜索一下,我没有看到任何显示我正在寻找的东西,但我很乐意接受重定向到其他问题/主题阅读。
提前谢谢!
答案 0 :(得分:4)
Linux中的USB输入设备通常由HID驱动程序(人机接口设备)处理,后者又转换为输入设备。
您可以将它们视为原始USB设备,但这通常不是一个好主意,因为它是一种非常低级别的协议。
如果您拥有适当的权限,则可以阅读/dev/input/*
设备。通常它们只能由root读取。如果您不想读取原始字节,那么有一些库(例如libinput)可以为您完成这项工作。
但如果您的游戏在XWindows中运行(最有可能),那么您应该管理XInput设备。您可以使用原始X调用执行此操作,但您可能更好地使用某些库,例如SDL。实际上SDL是pygame
在引擎盖下使用的,所以我先试试。
关于如何识别正确的设备,每个输入设备都有一个名称,甚至一些序列号(你在/dev/input/by-id
下看到它们作为符号链接这些通常足以识别设备,而不是输入号码。
如果你想阅读原始输入设备,让我解释一下关于你的hexdumps的回合。您正在阅读input*
设备,因此您获得了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_event
。第一个是:
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
到{ {1}})。您获得的消息只是中间点,即没有按下键盘按钮。也许您的0xFF
输出正在缓冲?
答案 1 :(得分:1)
它是一个USB Hid设备,因此它由hid驱动程序处理 - 请参阅调试输出“USB HID v1.10 Gamepad” 有各种教程和示例,说明如何做到这一点。
作为起点,您可以在“apt-get install joystick”上安装操纵杆,并查看源代码。
libhidapi也是一个不错的选择。