In linux when a uinput device is created, one or more event files corresponding to that device get created in the file system. (For example, if I create a uinput mouse, then the file /dev/input/mouseN is created.) But how do I determine which files got created for a given uinput device? The uinput kernel module does not appear to provide any ioctl for getting that information. One possible approach is to poll the file system immediately after creating the uinput device to see what files appear, but that approach does not work because of races with other devices, both real and uinput, that are also plugged in or created around the same time. Am I overlooking something, or must I hack the kernel to get this info?
If you look in sysfs you can find your information. Once you have created your uinput device do:
$ ls /sys/class/input/
event0 event1 ... eventN
input0 input2 ... input19 ... inputN
mouse0 mouse1 ... mouseN
mice
$ ls /sys/devices/virtual/input/
input19 mice
Notice that you can find virtual device in a different path. In this case, input19 is my uinput device. Which is the correspondent char device?
$ ls /sys/devices/virtual/input/input19/
event14 name id ...
My char device is /dev/input/event14
. I know that input19
is my uinput device because I'm the only user who is creating uinput devices. If you want to be sure, you must read its sysfs attribute name and verify that it is really your device
$ cat /sys/devices/virtual/input/input19/name
foo-keyboard-201303261446
You can retrieve information about your new uinput devices by reading kernel messages:
$ 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
From your program you can read from /dev/kmsg
and catch your event. Maybe you can open the device /dev/kmsg
, flush it, wait on select()
until you receive the uinput notification.
An alternative is to use libudev to retrieve you uinput device. Take a look at the following link: libudev tutorial
UPDATE: thanks to your question I improved my libuinput library available on github: libuinput by Federico. I implemented the solution that use hte kmsg device.
UPDATE: in 2014 the Linux uinput
driver has been improved (git SHA1 e3480a61fc). Now it is possible to get the sysfs path directly form the uinput
driver using the following ioctl
command:
/**
* 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)
So if you have the possibility to use a Linux kernel more recent than 3.13, you can use the above ioctl
to improve your code that uses uinput.
This is the best way I have found so far, combined with the answer given here I would do something like:
How to get name (path) of uinput created device
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);
Now send_input_to_fd should be the correct FD to send the events to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With