правило udev для автоматичного завантаження розкладки клавіатури, коли підключена клавіатура usb


24

Я намагаюся завантажити новий макет клавіатури, коли я підключаю клавіатуру usb, але моє правило udev не працює.

SUBSYSTEM == "введення", ATTR {idVendor} == "062a", ATTR {idProduct} == "0201", GOTO = "usb_xmodmap_auto"

LABEL = "usb_xmodmap_auto"
ACTION == "додати", RUN + = "/ usr / bin / xmodmap ~ / .usbXmodmap"
ACTION == "видалити", RUN + = "/ usr / bin / xmodmap ~ / .pndXmodmap"

Я перезавантажив правила, використовуючи:

> sudo udevadm control - правила завантаження

і перезапустивши систему, але коли я підключаю клавіатуру usb, початкова xmodmap все ще завантажена, і, таким чином, розкладка клавіатури неправильна, але якщо я запускаю команду в терміналі

> / usr / bin / xmodmap ~ / .usbXmodmap
або
> / usr / bin / xmodmap ~ / .pndXmodmap

вони працюють чудово.

сподіваюся, що soneone може допомогти.

Редагувати:

просто, щоб допомогти більше, я запустив кілька тестів на 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: call: test
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.ruleswhat
udev_rules_apply_to_event: RUN 'socket: @ / 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 'socket: / 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:2
udevadm_test: UDEV_LOG = 6
udevadm_test: DEVPATH = / пристрої / платформа / ehci-omap.0 / usb1 / 1-2 / 1-2.3 / 1-2.3: 1.1 / введення / введення10
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 d941dfed 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, 9C, 9E, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1, B2, B5, CE, CF, D0, D1, D2, D5, D9, DB, E2, EA, EB, 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, a20, 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 , 8A, 8B, 8C, 8E, 8F, 90,96,98,9B, 9C, 9E, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1 , B2, B5, CE, CF, D0, D1, D2, D5, D9, DB, E2, EA, EB, 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, a20, m4, lsfw '
udevadm_test: run: 'socket: @ / org / freedesktop / hal / udev_event'
udevadm_test: run: '/ sbin / modprobe input: 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, 9C, 9E, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1, B2 , B5, CE, CF, D0, D1, D2, D5, D9, DB, E2, EA, EB, 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, a20, m4, lsfw '
udevadm_test: run: 'socket: / org / kernel / udev / monitor'
udevadm_test: run: '/ usr / bin / xmodmap ~ / .usbXmodmap'

і

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

Виходи:

run_command: call: test
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 'socket: @ / org / freedesktop / hal / udev_event' /etc/udev/rules.d/90-hal.rules:2
udev_rules_apply_to_event: RUN 'socket: / 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.ruleswhat
udevadm_test: UDEV_LOG = 6
udevadm_test: DEVPATH = / пристрої / платформа / ehci-omap.0 / usb1 / 1-2 / 1-2.3 / 1-2.3: 1.1 / введення / введення10
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 d941dfed 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, 9C, 9E, 9F, A1, A3, A4, A5, A6, A7, A8, A9, AB, AC, AD, AE, B1, B2, B5, CE, CF, D0, D1, D2, D5, D9, DB, E2, EA, EB, 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, a20, 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'

який, здається, показує, що він повинен працювати, але він не сподівається, що це допоможе отримати відповідь.


Відповіді:


16

Я знайшов спосіб обійти це, хоч це трохи хакі.

Сьогодні я дійшов до тієї ж точності, намагаючись налаштувати дві клавіатури з 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


І мені цікаво, чи можете ви також допомогти мені додати повідомлення в кінці цього сценарію (наприклад 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". Чому це було б?
Геремія

5

Залежно від вашого дистрибутиву, у вас уже може бути правило udev для клавіатур на /lib/udev/rules.d/64-xorg-xkb.rules. Для Ubuntu це імпорт / etc / default / клавіатура, який має параметри приблизно так:

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

Під час мого налаштування я виявив, що це вбудоване правило виконується після мого користувальницького правила udev і переосмислює мої налаштування. Натомість я змінив XKBOPTIONS на / etc / default / клавіатуру на:

XKBOPTIONS="-option ctrl:nocaps"

Отримати поведінку "Caps Lock - контроль", яку я хотів на всіх клавіатурах.


2
Чудова ідея! Шахта працює простоXBKOPTIONS="ctrl:nocaps"
RasmusWL

3

Якщо ви використовуєте GNOME, вам потрібно буде відключити його плагін управління клавіатурою, щоб він не змінив зміни вашого макета.

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

Запустіть цю ж команду ще раз, щоб увімкнути її за бажанням.


їм запущений ангстрем. це буде працювати?
Джейк Ейчісон

Ви використовуєте GNOME в Ångström?
Ігнасіо Васкес-Абрамс

nope im using 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.
grawity

3

Я думаю, що я знайшов набагато більш чистий спосіб налаштування цього, який не вимагає спеціального злому 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можна демонізувати, використовуючи системний скрипт init.


Дякую, це змусило мене зрозуміти, що я можу просто використовувати inotifywaitдля запуску сценарію установки будь-яку зміну /dev/input, оскільки сам сценарій є ідентичним.
Чарлі Горічаназ

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: Розумний хитрість, дякую за обмін.


1
У мене немає каталогу x.org.conf.d на Linux Mint 18.2
Max N

2

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

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

Як зазначалося вище, проте, якщо ви припускаєте DISPLAY =: 0, згодом у вас можуть виникнути проблеми, якщо у вас є кілька користувачів або дисплей. Ви можете писати сценарії для виявлення відповідного дисплея, але в такому випадку ви самостійно (наскільки ця відповідь стосується). :)


1

Оскільки я не зміг змусити хаків змусити правила 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()

Потім я використовую цей системний файл блоку користувача, щоб тримати його ( 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.