файлы устройств /dev/input/event
файлы устройств /dev/input/event — это специальные символьные файлы в операционных системах семейства Linux, предоставляющие интерфейс для чтения событий от устройств ввода (клавиатур, мышей, тачпадов, джойстиков, сенсорных экранов и других). Они являются частью подсистемы ввода ядра Linux (Input Subsystem) и служат основным способом взаимодействия пользовательских приложений с аппаратными устройствами ввода на уровне событий.
Архитектура подсистемы ввода
Подсистема ввода в Linux представляет собой трехуровневую иерархию, обеспечивающую абстракцию аппаратного обеспечения и унифицированный доступ к нему.
Уровни подсистемы
- Аппаратный уровень (Device Drivers): Драйверы устройств, взаимодействующие непосредственно с физическим оборудованием через шины (USB, PS/2, I²C, Bluetooth и др.). Они регистрируют устройство в ядре и сообщают о необработанных событиях (например, нажатие клавиши, изменение координат мыши).
- Ядро (Input Core): Центральный модуль (
input.c), который управляет регистрацией устройств, обработкой событий и их маршрутизацией. Он получает события от драйверов и передает их зарегистрированным обработчикам — как в пространство ядра, так и в пространство пользователя. - Пространство пользователя (User Space): Интерфейсы, через которые приложения получают доступ к событиям. Основным интерфейсом являются файлы устройств
/dev/input/event(символьные файлы с мажорным номером 13, минорным номером 64+). Также существуют другие интерфейсы, такие как/dev/input/mice(для мышей),/dev/input/js(для джойстиков, устаревший) и интерфейс evdev.
Роль файлов /dev/input/event*
Файлы /dev/input/event* предоставляют прямой, небуферизованный доступ к потоку событий ввода от конкретного устройства. Каждое физическое устройство ввода (или виртуальное, созданное программно) получает свой собственный файл, например /dev/input/event0, /dev/input/event1 и так далее. Нумерация не является фиксированной и может меняться при перезагрузке системы или подключении/отключении устройств.
Структура события
Каждое событие, передаваемое через файл /dev/input/event*, представляет собой структуру фиксированного размера, определенную в заголовочном файле <linux/input.h>. Структура struct input_event имеет следующий вид:
``c struct input_event { struct timeval time; // Метка времени события (секунды и микросекунды) __u16 type; // Тип события (EV_KEY, EV_REL, EV_ABS и др.) __u16 code; // Код события (конкретная клавиша, ось, кнопка) __s32 value; // Значение события (0/1 для клавиш, смещение для относительных осей, абсолютное значение для абсолютных осей) }; ``
Поля структуры
- time: Метка времени, когда событие было сгенерировано ядром, с точностью до микросекунд. Позволяет синхронизировать события во времени.
- type: Определяет категорию события. Основные типы:
EV_KEY(0x01): События клавиш и кнопок (клавиатуры, мыши, джойстики). Значениеvalueравно 0 (отпускание), 1 (нажатие) или 2 (автоповтор).EV_REL(0x02): События относительного перемещения (мышь, трекбол).value— смещение относительно предыдущего положения.EV_ABS(0x03): События абсолютного позиционирования (тачпад, сенсорный экран, джойстик).value— абсолютное значение по оси.EV_SYN(0x00): Синхронизирующие события. Используются для разделения групп событий, произошедших одновременно.EV_SYNс кодомSYN_REPORT(0) сигнализирует о завершении пакета событий.- code: Уточняет тип события. Для
EV_KEYэто код клавиши (например,KEY_A,KEY_ENTER). ДляEV_REL— код оси (REL_X,REL_Y,REL_WHEEL). ДляEV_ABS— код оси (ABS_X,ABS_Y,ABS_MT_POSITION_X). - value: Значение события. Для
EV_KEY— 0 или 1. ДляEV_REL— целое число со знаком. ДляEV_ABS— целое число без знака в пределах диапазона оси.
Чтение и использование
Доступ к файлам
Файлы /dev/input/event* по умолчанию доступны для чтения только пользователю root или членам группы input. Для предоставления доступа обычным пользователям необходимо добавить их в группу input или изменить права доступа через udev-правила.
Чтение в программе
Чтение из файла /dev/input/event* осуществляется стандартными системными вызовами (open, read, close). Приложение считывает данные блоками размером sizeof(struct input_event) (обычно 16 байт на 32-битных системах и 24 байта на 64-битных). Пример на языке C:
```c
include <stdio.h>
include <stdlib.h>
include <fcntl.h>
include <unistd.h>
include <linux/input.h>
int main() { int fd = open("/dev/input/event0", O_RDONLY); if (fd == -1) { perror("open"); return 1; }
struct input_event ev; while (1) { if (read(fd, &ev, sizeof(ev)) < sizeof(ev)) { perror("read"); break; } if (ev.type == EV_KEY && ev.value == 1) { printf("Key %d pressed\n", ev.code); } } close(fd); return 0; } ```
Инструменты командной строки
evtest: Основной инструмент для отладки и тестирования устройств ввода. Выводит список доступных устройств и отображает все события в удобочитаемом формате.input-utils: Набор утилит, включающийinput-evt(аналогevtest),input-kbd(для эмуляции нажатий) и другие.cat /dev/input/event0 | od -t x1: Позволяет просматривать сырые шестнадцатеричные данные.
Идентификация устройств
Для определения, какому физическому устройству соответствует конкретный файл /dev/input/event*, используются следующие методы:
- Символические ссылки в /dev/input/by-id/ и /dev/input/by-path/: Эти каталоги содержат символические ссылки, указывающие на файлы
/dev/input/event*. Названия ссылок основаны на идентификаторах устройства (например,usb-Logitech_USB_Receiver-event-mouse) или на пути подключения (например,pci-0000:00:14.0-usb-0:1:1.0-event-mouse). Это позволяет однозначно идентифицировать устройство независимо от динамической нумерации. - Файловая система sysfs: Каждое устройство ввода имеет запись в
/sys/class/input/. Например,/sys/class/input/event0/device/содержит информацию о производителе, продукте, версии и возможностях устройства. - Утилита
evtest: При запуске без аргументов выводит список всех доступных устройств с их описанием.
Применение
Графические серверы и оконные менеджеры
X.Org Server и Wayland Compositor (например, Weston, GNOME Shell, KWin) используют файлы /dev/input/event* для получения событий от устройств ввода. Они читают события напрямую или через библиотеку libinput, которая предоставляет более высокоуровневый API и обрабатывает сложные случаи (например, мультитач, настройки тачпада).
Промышленные и встраиваемые системы
В системах с ограниченными ресурсами (например, на базе Raspberry Pi, BeagleBone) файлы /dev/input/event* используются для реализации пользовательских интерфейсов, обработки нажатий кнопок, считывания данных с энкодеров и других устройств.
Игровые приложения
Многие игры и игровые движки (например, SDL, Unity) используют evdev для поддержки джойстиков, рулей и других игровых контроллеров.
Специализированное программное обеспечение
- Системы автоматизации: Программы, управляющие роботами или станками, могут считывать данные с датчиков через evdev.
- Программное обеспечение для людей с ограниченными возможностями: Утилиты для эмуляции ввода или переназначения клавиш.
- Инструменты для тестирования: Автоматические системы тестирования, имитирующие действия пользователя.
Ограничения и альтернативы
Ограничения
- Прямой доступ к оборудованию: Не все устройства ввода предоставляют полный набор событий через evdev. Некоторые функции (например, управление светодиодами клавиатуры, настройка DPI мыши) могут быть доступны только через специальные интерфейсы (например,
hidraw). - Производительность: Для высоконагруженных приложений (например, обработка мультитач с высокой частотой опроса) может потребоваться оптимизация чтения (неблокирующий режим, epoll).
- Безопасность: Предоставление доступа к
/dev/input/event*обычным пользователям может быть рискованным, так как позволяет перехватывать все события ввода (включая пароли).
Альтернативы
- libinput: Библиотека, предоставляющая более высокоуровневый API для работы с устройствами ввода. Она абстрагирует работу с evdev, обрабатывает мультитач, настройки тачпада, калибровку и другие сложные функции.
- /dev/input/mice: Устаревший интерфейс, предоставляющий события только от мышей в упрощенном формате.
- /dev/input/js*: Устаревший интерфейс для джойстиков.
- hidraw: Интерфейс для прямого доступа к HID-устройствам (Human Interface Device). Позволяет отправлять и получать необработанные HID-отчеты, что дает более полный контроль над устройством, но требует большего объема работы по разбору данных.
Источники
- Документация ядра Linux:
Documentation/input/input.rst,Documentation/input/event-codes.rst. - Исходный код ядра Linux:
drivers/input/input.c,include/uapi/linux/input.h. - Man-страницы:
evtest(1),input(4),libinput(3). - Спецификация Linux Input Subsystem.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →