запись в /dev/uinput (в Ubuntu 12.04)

Я разрабатываю небольшую программу, которая создает виртуальные джойстики в Linux с интерфейсом Python. Это ответвление Linux-Virtual-Joystick.

Мне нужно написать в dev/uinput, чтобы создать определяемый пользователем джойстик. Файл открывается с помощью O_RDWR (во время отладки я временно добавил другие права на чтение/запись для файла). Когда я делаю

write(uifd, &uidev, sizeof(uinput_user_dev));

он возвращает -1 и устанавливает для errno значение 22 (EINVAL). Аргументы верны, и файл был успешно открыт.

Кто-нибудь еще сталкивался с этой проблемой? Я отложил проект примерно на месяц, но помню, что он работал в последней версии Ubuntu.

Обновление: uinput работает на Ubuntu 12.10


person ferry    schedule 13.08.2012    source источник
comment
Привет, модуль uinput загружен?   -  person A.J.    schedule 13.08.2012
comment
/dev/uinput присутствует в моей системе (Lubuntu 11.10), но я не могу загрузить модуль uinput   -  person A.J.    schedule 13.08.2012
comment
эээ.. как мне это сделать? модуль, как в разделяемой библиотеке?   -  person ferry    schedule 13.08.2012
comment
Введите lsmod в терминал, чтобы увидеть все загруженные модули (загружаемые модули ядра).   -  person A.J.    schedule 13.08.2012
comment
modprobe uinput && lsmod | grep uinput ничего не дает   -  person ferry    schedule 13.08.2012


Ответы (3)


Я думаю проблема у вас с правами доступа к uinput. Сообщение об ошибке, которое вы получаете, типично для этого, и я уже видел такое же поведение на других устройствах.

Чтобы проверить это предположение, измените разрешения /dev/uinput, чтобы разрешить доступ ко всем:

chmod +0666 /dev/uinput

Затем попробуйте еще раз ваш код. Если теперь он работает нормально, вам нужно будет сделать это изменение постоянным, так как в противном случае после перезагрузки он вернется к исходным разрешениям.

Чтобы сделать это безопасным образом, добавьте файл правил, который будет находиться по адресу: /etc/dev/rules.d

со следующей строкой:

KERNEL=="uinput", GROUP="udev_group"

Чтобы увидеть, как должен выглядеть файл правил, проверьте файл правил udev, расположенный по адресу:

/lib/udev/rules.d/50-udev-default.rules

Когда будете готовы, добавьте группу с именем udev_group и добавьте в нее свое имя пользователя (или любого пользователя, который должен иметь права на запись в uinput).

Возможно, вам придется перезагрузиться, чтобы новое правило заработало.

В результате любой пользователь, являющийся членом этой группы, будет иметь полный доступ к uinput, чего вы и хотели.


для добавления группы можно установить «Пользователи и группы»:

sudo apt-get install gnome-system-tools

и запустить его по адресу:

Application -> System Tools -> Administration -> Users and Groups**

или в терминале:

gnome-system-tools
person OM55    schedule 13.08.2012
comment
Спасибо за ваш ответ. Проблема в том, что я попробовал программу как суперпользователь, а затем добавил o+rw в /dev/uinput, чтобы запустить ее как обычный пользователь, подключенный к gdb в eclipse. В любом случае он потерпел неудачу в одном и том же месте. Я не думаю, что это проблема с разрешениями. - person ferry; 13.08.2012
comment
мы можем добавить команду chmod также в файл rule.d?. Это связано с тем, что конечные пользователи могут не знать об установке необходимых прав доступа для /dev/uinput. - person Dig The Code; 13.03.2017
comment
Автоматический доступ для зарегистрированного пользователя: Добавить файл /etc/udev/rules.d/50-uinput.rules с содержимым: KERNEL=="uinput", TAG+="uaccess" - person Gima; 07.06.2017

Поскольку модуль uinput отсутствует, вам следует подумать о его сборке, прежде чем идти дальше.

Я никогда не пересобирал модуль ядра Linux таким образом, поэтому вы можете следовать объяснению здесь

Во-первых, вам нужно получить соответствующий исходный код и заголовки Linux. Также установите module-init-tools
Затем измените каталог на /usr/src/linux и выполните действия от имени пользователя root.

cp /boot/config-* ./.config
make drivers/input/misc/uinput.ko

Сборка uinput.ko займет несколько минут.

Проверьте, работает ли он, прежде чем переместить uinput.ko в /lib/modules/‹"yourkernelversion">/kernel/drivers/input/misc.

insmod ./drivers/input/misc/uinput.ko

Редактировать 1:

Похоже, что начиная с Linux 2.6.35-17.23, uinput является встроенным в модуле. Вот почему это не отображается lsmod.

Я только что посмотрел на ваш код, и я думаю, что проблема в этой строке

if (write(uifd, &uidev, sizeof(uinput_user_dev) != sizeof(uinput_user_dev))) 

Так должно быть

if (write(uifd, &uidev, sizeof(uinput_user_dev)) != sizeof(uinput_user_dev))

надеюсь, это поможет

person A.J.    schedule 13.08.2012
comment
Это действительно ставит заслон вещей. Я надеялся создать малополезную игрушку, которая работает «из коробки». - person ferry; 15.08.2012
comment
(действительно должно быть редактирование) Вы уверены, что uinput отсутствует? lsmod не показывает uinput, а modprobe uinput ничего не возвращает, поэтому он присутствует, но неактивен. Я попробую добавить его /etc/modules и посмотреть, что произойдет после перезагрузки. Спасибо за ваш ответ - person ferry; 15.08.2012
comment
Ну... не сейчас. Похоже, uinput действительно загружен: / я отредактирую свой ответ - person A.J.; 15.08.2012

У меня была эта ошибка и в Ubuntu 14.04 из вашего репозитория (https://github.com/ferry-/Linux-Virtual-Joystick-cpp). Я исправил это, обнулив элемент device::uidev в конструкторе устройства в device.h.

memset(&uidev, 0, sizeof(uidev));

person daemacles    schedule 23.07.2014