web-dev-qa-db-ja.com

USBキーボードが接続されたときにキーボードレイアウトを自動ロードするudevルール

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

彼らはうまく働きます。

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:呼び出し:test 
 udevadm_test:バージョン151 
このプログラムはデバッグ専用であり、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バイト(1769 * 20バイト)
 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準拠のキーボード" 
 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、1A3、1A3 、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、1A B、1AC、1AD、1AE、1B0,1B1,1B7、r0,1,6,8、a20、m4、lsfw '
 udevadm_test:run:' socket:/ org/kernel/udev/monitor '
 udevadm_test:実行: '/ 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:呼び出し:test 
 udevadm_test:バージョン151 
このプログラムはデバッグ専用であり、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:used temp一時インデックス35380バイト(1769 * 20バイト)
 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準拠のキーボード" 
 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:実行: '/ usr/bin/xmodmap〜/ .pndXmodmap' 

これは動作するはずですが、これが答えを得るのに役立つことは望んでいません。

24
Jake Aitchison

私はこれを回避する方法を見つけましたが、少しハックです。

Udev、setxkbmap、およびxinput --listを使用して2つのキーボードをセットアップし、それらがUSBホットプラグで動作するようにすることで、今日とまったく同じ点に到達しました。レイアウトを変更するのではなく、キーを交換していますが、ホットプラグでキーボードを特定し、条件付きでsetxkbmapを呼び出すことができれば、指定したキーボードのみの言語を設定できるはずです。 。キーボードレイアウトのリストは_ls -l /usr/share/kbd/keymaps/i386/_にあり、_xinput -list_でデバイス名を確認できます。

  1. rizumuをユーザー名に置き換えることをお勧めします。明示的にしないとこれを行う方法はありません。
  2. yourキーボード名をgrepしてください。
  3. lsusbを使用して、udevルールで設定する必要があるハードウェア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の2つのファイルがあります。適切な権限があることを確認してください_chmod 755 ~/bin/kbd*_

_~/bin/kbd_udev_スクリプトには以下が含まれます。

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

そして、バックグラウンドで_~/bin/kbd_を呼び出すだけで、udevがプロセスを完了し、キーボードをアクティブにできることがわかります。 __inputを使用してデバイスIDを取得できるようにキーボードがアクティブになるまで待機する必要があるため、_~/bin/kbd_スクリプト内で1秒間スリープします。これを実現するために、いくつかの変数を設定してエクスポートし、xinput setxkbmapがこれらの作業を実行できるようにしました:DISPLAYXAUTHORITYHOME、および1つの_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
_
16

ディストリビューションによっては、/ lib/udev/rules.d/64-xorg-xkb.rulesにすでにキーボードのudevルールがある場合があります。 Ubuntuでは、これは/ etc/default/keyboardをインポートします。これには、おおよそ次のようなオプションがあります。

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

私のセットアップでは、この組み込みルールがカスタムudevルールの後に実行され、設定を上書きしていたことがわかりました。代わりに、/ etc/default/keyboardのXKBOPTIONSを次のように変更しました。

XKBOPTIONS="-option ctrl:nocaps"

「Caps Lock is Control」動作を実現するために、すべてのキーボードで望みました。

5
jsha

udevxmodmapはX11ディスプレイにアクセスできないため、機能しません。実際、udevareアクティブなX11ディスプレイがあるかどうかさえ知りません。

  • 注:displays、複数形。 It ca n't「the」X11ディスプレイを使用します。たとえば、「ユーザーの簡易切り替え」を使用する場合。
3
user1686

GNOMEを実行している場合は、レイアウトの変更を上書きしないように、キーボード管理プラグインを無効にする必要があります。

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

同じコマンドを再度実行して、必要に応じて有効にします。

X.Org構成についてはどうですか? From 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を使用し、既存の/etc/X11/xorg.conf.d/vim 10-evdev.confで自分のUSBキーボードを構成しました。

@rizumu:賢いクラッジ、共有してくれてありがとう。

3
Casey Jones

私はこれを構成するはるかにきれいな方法を見つけたと思います、それは特別な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を使用する同様のスクリプトをシステム初期化スクリプトを使用して悪用できます。

3
giosh94mhz

実行中のディスプレイへのアクセスに関する質問に答えるために、ディスプレイの権限が正しく設定されていると想定して、スクリプト内の適切なDISPLAY変数をエクスポートできます。 (man xset(表示権限の場合)。

通常、多くの場合、単純にexport DISPLAY=:0は、シングルユーザーシステムでの最初の表示であるため、コマンド用です。 xmodmapを直接実行するのではなく、スクリプトを直接実行するのがおそらく最も簡単です。これにより、環境変数やその他の変数をより詳細に制御できるようになります。 (したがって、ルール内の「/ usr/bin/xmodmap〜/ .usbXmodmap」を「/usr/local/bin/keyboard_plug.sh」に置き換え、そのスクリプトに適切なコマンドをDISPLAY変数とともに配置します。)

ただし、上記のように、DISPLAY =:0であると想定した場合、複数のユーザーまたはディスプレイがあると、後で問題が発生する可能性があります。適切な表示を検出するスクリプトを書くことができますが、その場合は(この回答に関する限り)自分で行います。 :)

2
rust_and_moth

ハックを取得して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()

次に、この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

@ giosh94mhzのinotifywaitソリューションは少し単純で、pyudevへの依存を回避します。しかし、何らかの理由で、キーボードが接続されてから10〜20秒間inotifyイベントがトリガーされないことがわかりました。

1
Ryan Marcus