Правило udev для автоматической загрузки раскладки клавиатуры, когда USB-клавиатура подключена


22

Я пытаюсь загрузить новую раскладку клавиатуры, когда я подключаю USB-клавиатуру, но мое правило udev не работает.

SUBSYSTEM == "input", ATTR {idVendor} == "062a", ATTR {idProduct} == "0201", GOTO = "usb_xmodmap_auto"

LABEL = "usb_xmodmap_auto"
ДЕЙСТВИЕ == "добавить", RUN + = "/ usr / bin / xmodmap ~ / .usbXmodmap"
ДЕЙСТВИЕ == "удалить", RUN + = "/ usr / bin / xmodmap ~ / .pndXmodmap"

Я перезагрузил правила, используя:

> sudo udevadm control --reload-rules

и перезагружая систему, но когда я подключаю USB-клавиатуру, оригинальный xmodmap все еще загружается и, таким образом, раскладка клавиатуры неверна, но если я запускаю команду в терминале

> / usr / bin / xmodmap ~ / .usbXmodmap
или же
> / usr / bin / xmodmap ~ / .pndXmodmap

они работают просто отлично.

надеюсь, кто-то может помочь.

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

просто чтобы помочь больше, я провел несколько тестов udevadm:

> udevadm test --action = add /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10

выходы:

run_command: вызов: тест
udevadm_test: версия 151
Эта программа предназначена только для отладки, она не запускает никаких программ,
определяется ключом RUN. Это может показать неверные результаты, потому что
некоторые значения могут отличаться или не быть доступными во время симуляции.

[...]
parse_file: чтение '/etc/udev/rules.d/usb-keyboard.rules' как файла правил
udev_rules_new: правила используют токены 100572 байта (8381 * 12 байтов), буфер 21523 байта
udev_rules_new: временный индекс использовал 35380 байт (1769 * 20 байт)
udev_device_new_from_syspath: устройство 0x3b4d8 имеет devpath '/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10'
udev_rules_apply_to_event: RUN '/ sbin / modprobe -b $ env {MODALIAS}' /etc/udev/rules.d/80-drivers.rules:5
udev_rules_apply_to_event: RUN 'сокет: @ / org / freedesktop / hal / udev_event' /etc/udev/rules.d/90-hal.rules:2
udev_rules_apply_to_event: RUN '/ sbin / modprobe $ env {MODALIAS}' /etc/udev/rules.d/local.rules:31
udev_rules_apply_to_event: RUN 'сокет: / org / kernel / udev / monitor' /etc/udev/rules.d/run.rules:2
udev_rules_apply_to_event: RUN '/ usr / bin / xmodmap ~ / .usbXmodmap' /etc/udev/rules.d/usb-keyboard.rules:4
udevadm_test: UDEV_LOG = 6
udevadm_test: DEVPATH = / devices / platform / ehci-omap.0 / usb1 / 1-2 / 1-2.3 / 1-2.3: 1.1 / input / input10
udevadm_test: PRODUCT = 3 / 62a / 201/110
udevadm_test: NAME = "USB-совместимая клавиатура"
udevadm_test: PHYS = "usb-ehci-omap.0-2.3 / input1"
udevadm_test: UNIQ = ""
udevadm_test: EV == 1f
udevadm_test: KEY == 837fff 2c3027 bf004444 0 0 1fe3 c04 a27c000 267bfa d941дфедированный 9e0000 0 0 0
udevadm_test: REL == 143
udevadm_test: ABS == 1 0
udevadm_test: MSC == 10
udevadm_test: MODALIAS = вход: b0003v062Ap0201e0110-e0,1,2,3,4, k71,72,73,74,77,80,82,83,85,86,87,88,89,8A, 8B, 8C, 8E, 8F, 90,96,98,9B, 9С, 9Е, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1, B2, B5, CE, CF, D0, D1, D2, D5, D9, БД, Е2, ЕА, ЕВ, 100,101,105,106,107,108,109,10A, 10B, 10C, 162,166,16A, 16E, 178,179,17A, 17B, 17C, 17D, 17F, 180,181,182,185,18C, 18D, 192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA, 1AB, 1AC, 1AD, 1AE, 1B0,1B1,1B7, r0,1,6,8, а20, m4, lsfw
udevadm_test: ACTION = добавить
udevadm_test: SUBSYSTEM = вход
udevadm_test: run: '/ sbin / modprobe -b вход: b0003v062Ap0201e0110-e0,1,2,3,4, k71,72,73,74,77,80,82,83,85,86,87,88,89 , 8А, 8В, 8С, 8Е, 8F, 90,96,98,9B, 9С, 9Е, 9F, А1, А3, А4, А5, А6, А7, А8, А9, AB, AC, AD, AE, В1 , В2, В5, CE, CF, D0, D1, D2, D5, D9, БД, Е2, ЕА, ЕВ, 100,101,105,106,107,108,109,10A, 10B, 10C, 162,166,16A, 16E, 178,179,17A, 17B, 17C, 17D , 17F, 180,181,182,185,18C, 18D, 192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA, 1AB, 1AC, 1AD, 1AE, 1B0,1B1,1B7, r0,1 , 6,8, а20, m4, lsfw»
udevadm_test: run: 'socket: @ / org / freedesktop / hal / udev_event'
udevadm_test: run: '/ sbin / modprobe вход: b0003v062Ap0201e0110-e0,1,2,3,4, k71,72,73,74,77,80,82,83,85,86,87,88,89,8A , 8В, 8С, 8Е, 8F, 90,96,98,9B, 9С, 9Е, 9F, А1, А3, А4, А5, А6, А7, А8, А9, AB, AC, AD, АЕ, В1, В2 , В5, CE, CF, D0, D1, D2, D5, D9, БД, Е2, ЕА, ЕВ, 100,101,105,106,107,108,109,10A, 10B, 10C, 162,166,16A, 16E, 178,179,17A, 17B, 17C, 17D, 17F , 180,181,182,185,18C, 18D, 192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA, 1AB, 1AC, 1AD, 1AE, 1B0,1B1,1B7, r0,1,6 , 8, а20, m4, lsfw»
udevadm_test: run: 'socket: / org / kernel / udev / monitor'
udevadm_test: run: '/ usr / bin / xmodmap ~ / .usbXmodmap'

а также

> udevadm test --action = remove /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10

выходы:

run_command: вызов: тест
udevadm_test: версия 151
Эта программа предназначена только для отладки, она не запускает никаких программ,
определяется ключом RUN. Это может показать неверные результаты, потому что
некоторые значения могут отличаться или не быть доступными во время симуляции.

[...]
parse_file: чтение '/etc/udev/rules.d/usb-keyboard.rules' как файла правил
udev_rules_new: правила используют токены 100572 байта (8381 * 12 байтов), буфер 21523 байта
udev_rules_new: временный индекс использовал 35380 байт (1769 * 20 байт)
udev_device_new_from_syspath: устройство 0x3b4d8 имеет devpath '/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10'
udev_rules_apply_to_event: RUN 'сокет: @ / org / freedesktop / hal / udev_event' /etc/udev/rules.d/90-hal.rules:2
udev_rules_apply_to_event: RUN 'сокет: / org / kernel / udev / monitor' /etc/udev/rules.d/run.rules:2
udev_rules_apply_to_event: RUN '/ usr / bin / xmodmap ~ / .pndXmodmap' /etc/udev/rules.d/usb-keyboard.rules:5
udevadm_test: UDEV_LOG = 6
udevadm_test: DEVPATH = / devices / platform / ehci-omap.0 / usb1 / 1-2 / 1-2.3 / 1-2.3: 1.1 / input / input10
udevadm_test: PRODUCT = 3 / 62a / 201/110
udevadm_test: NAME = "USB-совместимая клавиатура"
udevadm_test: PHYS = "usb-ehci-omap.0-2.3 / input1"
udevadm_test: UNIQ = ""
udevadm_test: EV == 1f
udevadm_test: KEY == 837fff 2c3027 bf004444 0 0 1fe3 c04 a27c000 267bfa d941дфедированный 9e0000 0 0 0
udevadm_test: REL == 143
udevadm_test: ABS == 1 0
udevadm_test: MSC == 10
udevadm_test: MODALIAS = вход: b0003v062Ap0201e0110-e0,1,2,3,4, k71,72,73,74,77,80,82,83,85,86,87,88,89,8A, 8B, 8C, 8E, 8F, 90,96,98,9B, 9С, 9Е, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1, B2, B5, CE, CF, D0, D1, D2, D5, D9, БД, Е2, ЕА, ЕВ, 100,101,105,106,107,108,109,10A, 10B, 10C, 162,166,16A, 16E, 178,179,17A, 17B, 17C, 17D, 17F, 180,181,182,185,18C, 18D, 192,193,195,1A0,1A1,1A2,1A3,1A4,1A5,1A6,1A7,1A8,1A9,1AA, 1AB, 1AC, 1AD, 1AE, 1B0,1B1,1B7, r0,1,6,8, а20, m4, lsfw
udevadm_test: ACTION = удалить
udevadm_test: SUBSYSTEM = вход
udevadm_test: run: 'socket: @ / org / freedesktop / hal / udev_event'
udevadm_test: run: 'socket: / org / kernel / udev / monitor'
udevadm_test: run: '/ usr / bin / xmodmap ~ / .pndXmodmap'

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


Ответы:


14

Я нашел способ обойти это, хотя это немного глупо.

Сегодня я пришел к той же самой точке, пытаясь настроить две клавиатуры с помощью udev, setxkbmap и xinput --list и для них, чтобы они работали с горячим подключением через usb. Я обмениваюсь клавишами, не меняя раскладку, но все равно, после того, как вы определили клавиатуру с помощью горячей замены и можете условно вызывать setxkbmap, тогда вы сможете установить язык только для той клавиатуры, которую вы указали , Список раскладок клавиатуры можно найти здесь, ls -l /usr/share/kbd/keymaps/i386/и вы можете найти имя вашего устройства, чтобы продолжить xinput -list.

  1. Вы захотите заменить его rizumuсвоим именем пользователя, так как я обнаружил, что невозможно сделать это без явного указания.
  2. Убедитесь, что вы набрали yourназвание клавиатуры.
  3. Используйте lsusbдля обнаружения идентификатора оборудования, который необходимо установить в правиле udev. Моя клавиатура DAS выглядит такBus 002 Device 009: ID 04d9:2013 Holtek Semiconductor, Inc.

Сначала я настроил правило udev для автоматического определения клавиатуры, создав правило udev:

В файле /etc/udev/rules.d/00-usb-keyboards.rules:

ACTION=="add", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="2013", RUN+="/home/rizumu/bin/kbd_udev", OWNER="rizumu"

У меня есть два файла ~ / bin / kbd и ~ / bin / kbd_udev. Убедитесь, что у них есть нужные разрешенияchmod 755 ~/bin/kbd*

~/bin/kbd_udevСценарий содержит:

#!/bin/bash
/home/rizumu/bin/kbd &

И вы заметите, что все, что он делает, это вызывает ~/bin/kbdв фоновом режиме, чтобы udev мог завершить свой процесс и активировать клавиатуру. Внутри ~/bin/kbdскрипта мы спим на секунду, потому что нам нужно дождаться активации клавиатуры, чтобы мы могли получить идентификатор устройства с помощью xinput. Для того чтобы достигнуть этого я установить некоторые переменные и экспортировать их так XInput setxkbmap могут сделать тир работы: DISPLAY, XAUTHORITY, HOME, и один daskb_idдля ид моего daskeyboard:

#!/bin/bash
sleep 1
DISPLAY=":0.0"
HOME=/home/rizumu/
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME
daskb_id=`xinput -list | grep -i 'daskeyboard' | grep -o id=[0-9]. | grep -o [0-9]. | head -1`

xset r rate 200 30
setxkbmap -layout colemak
setxkbmap -option ctrl:nocaps
if [ "${daskb_id}" ]; then
    setxkbmap -device "${daskb_id}" -option altwin:swap_lalt_lwin
fi

Большое спасибо за помощь в ответе на мой вопрос AskUbuntu: askubuntu.com/questions/337411/…
Sadi

И мне интересно, если вы также можете помочь мне добавить уведомление в конце этого скрипта (например notify-send "USB Keyboard is plugged in and ready for use now." -i gtk-dialog-info -t 1000 -u normal). Поскольку я не очень разбираюсь в сценариях, я пытался вставить его до или после «fi», но в обоих случаях уведомление продолжало появляться снова и снова :-(
Sadi

Почему настройка OWNERдля этого устройства?
Лимбо Пэн

1
Что делает xset r rate 200 30линия? xsetне доступно на моей установке Ubuntu 17.04.
kleinfreund

1
Я не могу запустить xmodmap $HOME/.Xmodmapскрипт, аналогичный вашему "/ home / rizumu / bin / kbd". С чего бы это?
Джеремия

3

Если вы используете GNOME, вам нужно отключить плагин управления клавиатурой, чтобы он не отменял изменения макета.

gconftool-2 --toggle /apps/gnome_settings_daemon/plugins/keyboard/active

Повторите ту же команду еще раз, чтобы включить ее по желанию.


Я бегу Ангстрем. это будет работать?
Джейк Эйтчисон,

Вы используете GNOME на Ангстреме?
Игнасио Васкес-Абрамс

Нет, я использую xfce 4.6.1
Джейк Эйчисон

1
В моем Ubuntu 13.04 это находится dconfпод /org/gnome/settings-daemon/plugins/keyboard/active.
nh2

1
И команда для Ubuntu 13.04:gsettings set org.gnome.settings-daemon.plugins.keyboard active false
Сади

3

Она не работает , потому что udevи xmodmapне имеет доступ к дисплею X11. На самом деле, udevдаже не знает, есть ли активные дисплеи X11.

  • Примечание: дисплеи , множественное число. Он не может использовать дисплей X11, потому что их может быть больше одного. Например, если вы используете «быстрое переключение пользователей».

так как я мог сделать эту работу?
Джейк Эйтчисон

Кто-нибудь знает, как я могу это исправить?
Джейк Эйтчисон,

1
Я получил udev для вызова setxkbmap. Правило udev вызывает скрипт, который поддерживает другой скрипт (так что udev может его завершить). Второй сценарий делает паузу на секунду, устанавливает ожидаемые переменные X11 и запускает setxkbmap. Смотрите мой ответ на главный вопрос для более подробной информации.
Томас Шрайбер

@rizumu: Ага, удачи в работе с GDM.
Гравитация

3

Как насчет конфигурации X.Org? Из Gentoo Wiki: X.Org/Input_drivers - udev :

Пример: если у вас есть клавиатура Logitech Access для французской части Швейцарии, вы можете использовать следующее:

Файл: /etc/X11/xorg.conf.d/10-keyboard.conf

Section "InputClass"
    Identifier             "evdev keyboard catchall"
    MatchIsKeyboard        "on"
    MatchDevicePath        "/dev/input/event*"
    Driver                 "evdev"
    Option                 "XkbModel" "logiaccess"
    Option                 "XkbLayout" "ch"
    Option                 "XkbVariant" "fr"
EndSection

Для подробного объяснения читайте:

man xorg.conf

а также:

man evdev

ArchWiki демонстрирует использование того же синтаксиса в xorg.conf, но отмечает, что «в настоящее время вы должны создать отдельный файл конфигурации, например /etc/X11/xorg.conf.d/90-keyboard-layouts.conf». Я использую Arch и настроил свою собственную USB-клавиатуру в существующем /etc/X11/xorg.conf.d/vim 10-evdev.conf.

@rizumu: Умный Kludge, спасибо, что поделились.


1
У меня нет каталога x.org.conf.d в Linux Mint 18.2
Макс. N

3

В зависимости от вашего дистрибутива, вы можете уже иметь правило udev для клавиатур в /lib/udev/rules.d/64-xorg-xkb.rules. В Ubuntu это импортирует / etc / default / keyboard, параметры которого примерно такие:

XKBMODEL="pc105"
XKBLAYOUT="us"
XKBVARIANT=""
XKBOPTIONS=""

Для моей установки я обнаружил, что это встроенное правило выполняется после моего пользовательского правила udev и переопределяет мои настройки. Вместо этого я изменил XKBOPTIONS в / etc / default / keyboard на:

XKBOPTIONS="-option ctrl:nocaps"

Чтобы получить поведение «Caps Lock is Control», я хотел на всех клавиатурах.


1
Отличная идея! Мой работает только сXBKOPTIONS="ctrl:nocaps"
RasmusWL

2

Чтобы ответить на ваш вопрос о доступе к работающему дисплею, вы можете экспортировать соответствующую переменную DISPLAY в сценарии, предполагая, что разрешения для дисплея установлены правильно. ( man xsetдля разрешений на отображение.)

Во многих обычных случаях вы можете просто выполнить export DISPLAY=:0команду, так как это первое отображение в однопользовательской системе. Вероятно, проще всего запустить скрипт, а не xmodmap напрямую, так как это позволит вам лучше контролировать переменные окружения и все остальное. (Поэтому замените "/ usr / bin / xmodmap ~ / .usbXmodmap" в вашем правиле на "/usr/local/bin/keyboard_plug.sh" и поместите соответствующие команды в этот скрипт вместе с переменной DISPLAY.)

Однако, как отмечалось выше, если вы примете DISPLAY =: 0, вы можете столкнуться с проблемами позже, если у вас несколько пользователей или дисплеев. Вы можете написать сценарии для определения соответствующего отображения, но в этом случае вы по своему усмотрению (что касается этого ответа). :)


2

Я думаю, что нашел более чистый способ настройки этого, который не требует специального взлома X11.

Идея заключается в том, что он udevбудет обнаруживать только новый ввод с клавиатуры и создавать символическую ссылку для каждого макета, а затем inotifyбудет отслеживать новый макет в пространстве пользователя.

правила удев

#/etc/udev/rules.d/61-usb-keyboard-layout.rules

# will match my Logitech keyboard with US layout 
SUBSYSTEM=="input", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c31c", GROUP="plugdev", MODE="0660", SYMLINK+="input/by-layout/us"

# will match my Lenovo integrated keyboard with IT layout
SUBSYSTEM=="input", ENV{ID_PATH}=="platform-i8042-serio-0", SYMLINK+="input/by-layout/it"

# force the directory to be recreated, just in case you unplug all input
SUBSYSTEM=="input", RUN="/bin/mkdir -p /dev/input/by-layout"

С этими правилами у меня есть каталог под dev ( /dev/input/by-layout) для наблюдения за изменениями в скриптах пространства пользователя.

Скрипт пользовательского пространства для KDE

Например, при использовании KDE у меня работает этот скрипт (авто):

#!/bin/bash

# In case no link are found, switch to this layout
DEFAULT="it"

switch_layout () {
        [ ! -z "$1" ] || return 0
        /usr/bin/qdbus org.kde.keyboard /Layouts org.kde.KeyboardLayouts.setLayout $1
}

best_layout() {
        local LAYOUT=$(ls -1t /dev/input/by-layout/ | head -n 1)
        if [ -z "$LAYOUT" ] ; then
                LAYOUT=$DEFAULT
        fi
        echo $LAYOUT
}

switch_layout $(best_layout)

while true ; do
        EVENT=$(inotifywait -q -e create -e delete --exclude '.*tmp.*' /dev/input/by-layout/)

        if echo "$EVENT" | grep -qe CREATE ; then
                LAYOUT=${EVENT#?*CREATE }
        fi

        if echo "$EVENT" | grep -qe DELETE ; then
                LAYOUT=$(best_layout)
        fi

        switch_layout $LAYOUT
done

Это работает как очарование для меня. Чтобы изменить структуру системы (которая мне сейчас не нужна), аналогичный скрипт, который loadkeysможно использовать, может быть демонизирован с помощью сценария системной инициализации.


Спасибо, это заставило меня понять, что я могу просто использовать inotifywaitдля запуска сценария установки любое изменение /dev/input, так как сам сценарий является идемпотентным.
Чарли Горичаназ

0

Поскольку я не мог заставить хаки заставить работать правила udev, я написал небольшой скрипт на Python, который использовался pyudevдля отслеживания входных событий.

#! /usr/bin/env python3

import pyudev
import time
import subprocess

ctx = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(ctx)
monitor.filter_by("input")

def defer_xmodmap():
    time.sleep(1) # not sure if there's a race here, but it feels like there could be.
    subprocess.run("xmodmap ~/dotfiles/.xmodmap", shell=True)


for device in iter(monitor.poll, None):
    # there might be a way to add the action condition to the filter, but I couldn't find it
    if device.action != "add":
        continue

    # ensure the KB is initialized -- not sure if this is actually a needed check
    if not device.is_initialized:
        continue

    # my keyboard, from the output of `lsusb`
    if not "045E:07A5" in device.device_path:
        continue

    # it's the keyboard being added.
    defer_xmodmap()

Затем я использую этот системный пользовательский файл systemd, чтобы он работал ( systemctl --user enable name_of_service_file):

[Unit]
Description=udev xmodmap monitor

[Service]
ExecStart=/usr/bin/env python3 %h/local/bin/monitor_kb_udev
Restart=always
RestartSec=10

[Install]
WantedBy=default.target

inotifywaitРешение от @ giosh94mhz немного проще, и позволяет избежать зависимости pyudev. Однако по какой-то причине я обнаружил, что inotifyсобытие не вызывалось в течение 10-20 секунд после подключения клавиатуры.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.