Как определить файлы, соответствующие устройству ввода?

В Linux, когда создается устройство ввода данных, в файловой системе создается один или несколько файлов событий, соответствующих этому устройству. (Например, если я создаю мышь 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 - это мое устройство ввода данных. Какое корреспондентное устройство char?

$ ls /sys/devices/virtual/input/input19/
event14 name id ...

Мое устройство char /dev/input/event14, я знаю это input19 мое устройство ввода, потому что я единственный пользователь, который создает устройства ввода. Если вы хотите быть уверены, вы должны прочитать его имя атрибута 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

ОБНОВЛЕНИЕ: благодаря вашему вопросу я улучшил свою библиотеку libuinput, доступную на github: libuinput от Federico. Я реализовал решение, которое использует устройство hte kmsg.

ОБНОВЛЕНИЕ: в 2014 году Linux uinput драйвер был улучшен (git SHA1 e3480a61fc). Теперь можно получить путь sysfs непосредственно из uinput водитель с помощью следующего ioctl команда:

/**
 * 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)

Так что, если у вас есть возможность использовать ядро ​​Linux более свежего, чем 3.13, вы можете использовать выше ioctl улучшить ваш код, который использует uinput.

Это лучший способ, который я нашел до сих пор, в сочетании с ответом, приведенным здесь, я бы сделал что-то вроде:

Как получить имя (путь) устройства, созданного 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 для отправки событий.

Другие вопросы по тегам