4

在 linux 中,当创建 uinput 设备时,会在文件系统中创建与该设备对应的一个或多个事件文件。(例如,如果我创建了一个 uinput 鼠标,则会创建文件 /dev/input/mouseN。)但是我如何确定为给定的 uinput 设备创建了哪些文件?uinput 内核模块似乎没有提供任何 ioctl 来获取该信息。一种可能的方法是在创建 uinput 设备后立即轮询文件系统以查看出现的文件,但该方法不起作用,因为与其他设备(真实和 uinput)竞争,这些设备也大约在同一时间插入或创建. 我是否忽略了某些东西,或者我必须破解内核才能获取此信息?

4

2 回答 2

7

如果您查看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 的代码。

于 2013-03-26T12:38:23.370 回答
1

这是迄今为止我找到的最好的方法,结合这里给出的答案,我会做类似的事情:

如何获取 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。

于 2016-08-25T20:54:15.050 回答