USB 키보드가 연결되었을 때 키보드 레이아웃을 자동로드하는 udev 규칙


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 제어 --reload-rules

시스템을 다시 시작하지만 usb 키보드를 꽂을 때 원래 xmodmap이 여전히로드되어 키보드 레이아웃이 잘못되었지만 터미널에서 명령을 실행하면

> / usr / bin / xmodmap ~ / .usbXmodmap
또는
> / usr / bin / xmodmap ~ / .pndXmodmap

그들은 잘 작동합니다.

soneone이 도울 수 있기를 바랍니다.

편집하다:

더 많은 것을 돕기 위해 udevadm 테스트를 실행했습니다.

> udevadm 테스트 --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 : 제품 = 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 1fe3 c04 a27c000 267bfa d941dfed 9e0000 000
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 : 실행 : '/ 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 , 6,8, a20, m4, lsfw '
udevadm_test : 실행 : 'socket : @ / org / freedesktop / hal / udev_event'
udevadm_test : 실행 : '/ sbin / modprobe 입력 : 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 : 실행 : 'socket : / org / kernel / udev / monitor'
udevadm_test : 실행 : '/ usr / bin / xmodmap ~ / .usbXmodmap'

> udevadm test --action = / 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 : 제품 = 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 1fe3 c04 a27c000 267bfa d941dfed 9e0000 000
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 : 실행 : 'socket : @ / org / freedesktop / hal / udev_event'
udevadm_test : 실행 : 'socket : / org / kernel / udev / monitor'
udevadm_test : 실행 : '/ usr / bin / xmodmap ~ / .pndXmodmap'

작동해야한다는 것을 보여 주지만 이것이 대답을 얻는 데 도움이되기를 바랍니다.


1
관련 .

답변:


16

조금 해키지만이 문제를 해결할 방법을 찾았습니다.

오늘 udev, setxkbmap 및 xinput --list를 사용하여 두 개의 키보드를 설정하고 USB 핫 플러깅과 작동하도록 동일한 지점에 도달했습니다. 레이아웃을 변경하지 않고 키를 교체하고 있지만 핫 플러그에서 키보드를 식별하고 조건 적으로 setxkbmap을 호출 할 수 있으면 지정한 키보드의 언어 만 설정할 수 있어야합니다. . 자판 배열 목록은 여기에서 찾을 수 있으며 다음 ls -l /usr/share/kbd/keymaps/i386/과 같은 장치 이름을 찾을 수 있습니다 xinput -list.

  1. rizumu명시 적이 지 않고이 작업을 수행하는 방법이 불가능하다는 것을 알았으므로 사용자 이름 으로 바꾸고 싶을 것 입니다.
  2. your키보드 이름을 확인하십시오 .
  3. lsusbudev 규칙에서 설정해야하는 하드웨어 ID를 발견하는 데 사용하십시오 . 내 das 키보드는 다음과 같습니다Bus 002 Device 009: ID 04d9:2013 Holtek Semiconductor, Inc.

먼저 키보드를 udev 규칙을 작성하여 autodetct하도록 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/kbdudev가 프로세스를 완료하고 키보드를 활성화 할 수 있도록 백그라운드에서 호출하는 것만 알 수 있습니다. ~/bin/kbd스크립트 안에서 xinput을 사용하여 장치 ID를 얻을 수 있도록 키보드가 활성화 될 때까지 기다려야하므로 잠자기 상태입니다. XInput에의 setxkbmap을가, 자신의 일을 할 수 있도록 내가 몇 가지 변수를 설정하고이를 내 보낸이를 실현하려 : DISPLAY, XAUTHORITY, HOME, 한 daskb_id내 daskeyboard의 ID에 대한 :

#!/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이 장치를 설정 하는 이유는 무엇 입니까?
Limbo Peng

1
뭐라고합니까 xset r rate 200 30라인은 무엇입니까? xsetUbuntu 17.04 설치에서 사용할 수 없습니다.
kleinfreund

1
xmodmap $HOME/.Xmodmap"/ home / rizumu / bin / kbd"와 유사한 스크립트를 사용하여 실행할 수 없습니다 . 왜 그런가요?
Geremia

5

배포판에 따라 /lib/udev/rules.d/64-xorg-xkb.rules에 이미 키보드에 대한 udev 규칙이있을 수 있습니다. 우분투에서는 / etc / default / keyboard를 가져 오는데, 대략 다음과 같은 옵션이 있습니다 :

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

내 설정에서이 내장 규칙이 사용자 정의 udev 규칙 이후에 실행되고 설정을 재정의하고 있음을 발견했습니다. 대신 / etc / default / keyboard에서 XKBOPTIONS를 다음과 같이 변경했습니다.

XKBOPTIONS="-option ctrl:nocaps"

"Caps Lock is Control"동작을 얻으려면 모든 키보드에서 원했습니다.


2
좋은 생각이야! 내 것과 함께 작동XBKOPTIONS="ctrl:nocaps"
RasmusWL

3

그놈을 실행하는 경우 키보드 관리 플러그인을 비활성화하여 레이아웃 변경 사항을 무시하지 않아야합니다.

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

원하는대로 동일한 명령을 다시 실행하십시오.


메신저 옹스트롬. 이게 효과가 있을까요?
Jake Aitchison

Ångström에서 그놈을 사용하고 있습니까?
이그나시오 바스케스-아 브람스

아니 XFCE 4.6.1 사용하는 메신저
제이크 Aitchison

1
내 우분투 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
Sadi

3

때문에 작동하지 않습니다 udevxmodmap당신의 X11 디스플레이에 액세스 할 수 없습니다. 사실, 활성 X11 디스플레이 udev 있는지조차 알지 못합니다 .

  • 참고 : , 복수를 표시합니다 . 그것은 할 수없는 하나 이상이있을 수 있기 때문에 "는"X11 디스플레이를 사용합니다. 예를 들어 "빠른 사용자 전환"을 사용하는 경우

어떻게이 일을 할 수 있습니까?
Jake Aitchison

누구든지 내가 어떻게 고칠 수 있는지 알고 있습니까?
Jake Aitchison

1
setxkbmap을 호출하도록 udev를 얻었습니다. udev 규칙은 다른 스크립트를 배경으로하는 스크립트를 호출하므로 udev가 완료 될 수 있습니다. 두 번째 스크립트는 1 초 동안 일시 중지하고 예상되는 X11 변수를 설정하고 setxkbmap을 트리거합니다. 자세한 내용은 주요 질문에 대한 내 대답을 참조하십시오.
Thomas Schreiber

@ rizumu : 아, 그래도 GDM과 함께 작동 시키길 바랍니다.
grawity

3

특별한 X11 해킹이 필요없는이 구성 방법이 훨씬 깨끗하다고 ​​생각합니다.

이것 뒤에 숨겨진 아이디어는 udev새로운 키보드 입력 만 감지하고 각 레이아웃에 대한 심볼릭 링크를 만든 다음 inotify사용자 공간에서 새로운 레이아웃을 감시한다는 것입니다.

udev 규칙

#/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시스템 초기화 스크립트 를 사용하여 비슷한 스크립트를 악마화할 수 있습니다.


덕분에 스크립트 자체가 dem 등성이므로 inotifywait변경 사항에 대한 설정 스크립트를 실행하는 데 사용할 수 있음을 알았습니다 /dev/input.
Charlie Gorichanaz

3

X.Org 구성은 어떻습니까? 에서 젠투 위키 : 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를 사용하고 기존 /etc/X11/xorg.conf.d/vim 10-evdev.conf에서 자체 USB 키보드를 구성했습니다.

@ rizumu : 영리한 kludge, 공유 주셔서 감사합니다.


1
Linux Mint 18.2에 x.org.conf.d 디렉토리가 없습니다.
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 규칙을 작동시키는 해킹을 얻지 못했기 때문에 pyudev입력 이벤트를 모니터링 하는 데 사용하는 작은 Python 스크립트를 작성했습니다 .

#! /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 초 동안 이벤트가 트리거되지 않는 것으로 나타났습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.