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?
2 Answers
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.

- 3,782
- 32
- 46
-
1You state that "input19 is my uinput device." How do you know *that*? The best approach that I can see is to specify a unique name when creating that uinput device, and then grep the /sys/devices/virtual/input/*/name files for that name. Is there a better approach (other than using libudev)? – Martin Carroll Mar 26 '13 at 13:00
-
@MartinCarroll I know that is my uinput device because I'm the only user who is creating uinput devices on my machine. All inputXX devices (except _mice_) in _/sys/devices/virtual/input/_ are mine. Obviously, if other users (or programs not under your control) can create uinput device you have a problem. To be sure, you must use an "unique" name and check it from sysfs, as you said. (I update the answer with these extra consideration). With libudev you can monitor the device creation and intercept the creation of your device. Or you can make a search with a given pattern – Federico Mar 26 '13 at 13:39
-
Happy to help :) If you think that I answered to your question please give me the feedback on the answer ;) – Federico Mar 27 '13 at 15:19
-
I tried to give you positive feedback, but my reputation isn't high enough yet... – Martin Carroll Apr 02 '13 at 14:48
-
That's a terrible way of doing things (racy, relies on being the only user), there is an API you should be using instead - see the answer below, or for more details: https://stackoverflow.com/questions/34064047/ – totaam Jul 30 '17 at 09:30
-
1Each answer is dated. My answer comes from 2013, the Linux kernel patch that introduce that API has been published in 2014. Today the answer I suggested 5 years ago is out of date: of course! Indeed the questions says "The uinput kernel module does not appear to provide any ioctl for getting that information". Since today there is a better way to do it, you should have updated the question and my answer. People typically look for the accepted answer, so it is good to keep them updated – Federico Jul 30 '17 at 18:44
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.