在 linux 中,当创建 uinput 设备时,会在文件系统中创建与该设备对应的一个或多个事件文件。(例如,如果我创建了一个 uinput 鼠标,则会创建文件 /dev/input/mouseN。)但是我如何确定为给定的 uinput 设备创建了哪些文件?uinput 内核模块似乎没有提供任何 ioctl 来获取该信息。一种可能的方法是在创建 uinput 设备后立即轮询文件系统以查看出现的文件,但该方法不起作用,因为与其他设备(真实和 uinput)竞争,这些设备也大约在同一时间插入或创建. 我是否忽略了某些东西,或者我必须破解内核才能获取此信息?
2 回答
如果您查看sysfs,您可以找到您的信息。创建 uinput 设备后,请执行以下操作:
$ ls /sys/class/input/
event0 event1 ... eventN
input0 input2 ... input19 ... inputN
mouse0 mouse1 ... mouseN
mice
$ ls /sys/devices/virtual/input/
input19 mice
请注意,您可以在不同的路径中找到虚拟设备。在这种情况下,input19 是我的 uinput 设备。对应的字符设备是哪个?
$ ls /sys/devices/virtual/input/input19/
event14 name id ...
我的字符设备是/dev/input/event14
. 我知道那input19
是我的 uinput 设备,因为我是唯一创建 uinput 设备的用户。如果你想确定,你必须阅读它的 sysfs 属性名称并验证它确实是你的设备
$ cat /sys/devices/virtual/input/input19/name
foo-keyboard-201303261446
您可以通过阅读内核消息来检索有关新 uinput 设备的信息:
$ dmesg | tail -n 7
input: foo-keyboard-201303261445 as /devices/virtual/input/input14
input: foo-keyboard-201303261445 as /devices/virtual/input/input15
input: foo-keyboard-201303261445 as /devices/virtual/input/input16
input: foo-keyboard-201303261445 as /devices/virtual/input/input17
input: foo-keyboard-201303261446 as /devices/virtual/input/input18
input: foo-keyboard-201303261446 as /devices/virtual/input/input19
input: foo-keyboard-201303261446 as /devices/virtual/input/input20
从您的程序中,您可以读取/dev/kmsg
并捕获您的事件。也许你可以打开设备/dev/kmsg
,刷新它,等到select()
你收到 uinput 通知。
另一种方法是使用libudev来检索您的 uinput 设备。看看下面的链接:libudev 教程
更新:感谢您的问题,我改进了 github 上的 libuinput 库:libuinput by Federico。我实现了使用 hte kmsg设备的解决方案。
更新:2014 年,Linuxuinput
驱动程序得到了改进(git SHA1 e3480a61fc)。现在可以uinput
使用以下ioctl
命令直接从驱动程序获取 sysfs 路径:
/**
* UI_GET_SYSNAME - get the sysfs name of the created uinput device
*
* @return the sysfs name of the created virtual input device.
* The complete sysfs path is then /sys/devices/virtual/input/--NAME--
* Usually, it is in the form "inputN"
*/
#define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 300, len)
因此,如果您有可能使用比 3.13 更新的 Linux 内核,您可以使用上述ioctl
方法来改进使用 uinput 的代码。
这是迄今为止我找到的最好的方法,结合这里给出的答案,我会做类似的事情:
char sysfs_device_name[16];
ioctl(uinput_fd_after_create, UI_GET_SYSNAME(sizeof(sysfs_device_name)), sysfs_device_name);
printf("/sys/devices/virtual/input/%s\n", sysfs_device_name);
//Now retrieve all files in that folder and grep for event* then
send_input_to_fd = open("the_event[n]", O_WRONLY | O_NDELAY);
现在 send_input_to_fd 应该是发送事件的正确 FD。