22

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

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

LABEL="usb_xmodmap_auto"
ACTION=="add", RUN+="/usr/bin/xmodmap ~/.usbXmodmap"
ACTION=="remove", 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: calling: test
udevadm_test: version 151
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

[...]
parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file
udev_rules_new: rules use 100572 bytes tokens (8381 * 12 bytes), 21523 bytes buffer
udev_rules_new: temporary index used 35380 bytes (1769 * 20 bytes)
udev_device_new_from_syspath: device 0x3b4d8 has 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 '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: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-compliant keyboard"
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=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: ACTION=add
udevadm_test: SUBSYSTEM=input
udevadm_test: run: '/sbin/modprobe -b 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/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=remove /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10

выходы:

run_command: calling: test
udevadm_test: version 151
This program is for debugging only, it does not run any program,
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

[...]
parse_file: reading '/etc/udev/rules.d/usb-keyboard.rules' as rules file
udev_rules_new: rules use 100572 bytes tokens (8381 * 12 bytes), 21523 bytes buffer
udev_rules_new: temporary index used 35380 bytes (1769 * 20 bytes)
udev_device_new_from_syspath: device 0x3b4d8 has 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.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-compliant keyboard"
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=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: ACTION=remove
udevadm_test: SUBSYSTEM=input
udevadm_test: run: 'socket:@/org/freedesktop/hal/udev_event'
udevadm_test: run: 'socket:/org/kernel/udev/monitor'
udevadm_test: run: '/usr/bin/xmodmap ~/.pndXmodmap'

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

7 ответов7

13

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

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

  1. Вы захотите заменить rizumu своим именем пользователя, так как я обнаружил, что невозможно сделать это без явного указания.
  2. Убедитесь , что вы Grep на 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
3

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

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

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

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

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

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, спасибо, что поделились.

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", я хотел на всех клавиатурах.

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 может быть демонизирован с помощью скрипта инициализации системы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .