Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine the files corresponding to a uinput device?

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?

like image 864
Martin Carroll Avatar asked Feb 17 '23 01:02

Martin Carroll


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.

like image 87
Federico Avatar answered Mar 16 '23 23:03

Federico


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.

like image 31
Vans S Avatar answered Mar 16 '23 21:03

Vans S