USBキーボードが差し込まれたときにキーボードレイアウトを自動でロードするudevルール


24

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 == "削除"、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 '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:実行: '/ 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:実行: 'socket:@ / org / freedesktop / hal / udev_event'
udevadm_test:実行: '/ 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:実行: '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:呼び出し:テスト
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.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:実行: 'socket:@ / org / freedesktop / hal / udev_event'
udevadm_test:実行: 'socket:/ org / kernel / udev / monitor'
udevadm_test:実行: '/ usr / bin / xmodmap〜/ .pndXmodmap'

これは動作するはずであるように見えますが、これが答えを得る助けになることを望みません。


回答:


16

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

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

  1. rizumuユーザー名で置き換えることをお勧めします。明示的でないとこれを行う方法は不可能だとわかりました。
  2. 必ずyourキーボード名をgrepしてください。
  3. lsusbudevルールで設定する必要があるハードウェアIDを検出するために使用します。私の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の2つのファイルがあります。適切な権限を持っていることを確認してくださいchmod 755 ~/bin/kbd*

~/bin/kbd_udevスクリプトが含まれています:

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

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

:おかげで私は自分の質問に答える手助けのためにたくさんのAskUbuntuあるaskubuntu.com/questions/337411/...
サディ

また、このスクリプトの最後に通知メッセージを追加するのを手伝ってもらえますか(たとえばnotify-send "USB Keyboard is plugged in and ready for use now." -i gtk-dialog-info -t 1000 -u normal)。スクリプトについてあまり知らないので、「fi」の前後に挿入しようとしましたが、どちらの場合も通知メッセージが繰り返し表示され続けました:
Sadi

OWNERこのデバイスに設定する理由
リンボペン14

1
xset r rate 200 30行は何をしますか?xsetUbuntu 17.04のインストールでは使用できません。
kleinfreund

1
xmodmap $HOME/.Xmodmap「/ home / rizumu / bin / kbd」に類似したスクリプトを使用して実行することはできません。どうしてですか?
ジェレミア

5

ディストリビューションによっては、キーボードのudevルールが/lib/udev/rules.d/64-xorg-xkb.rulesにすでにある場合があります。Ubuntuでは、これにより/ 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

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

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

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


オングストロームを実行しています。これは機能しますか?
ジェイクエイチソン

ÅngströmでGNOMEを使用していますか?
イグナシオバスケスエイブラムス

いやイムXFCE 4.6.1使用して
ジェイクAitchison

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

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

  • 注:、複数を表示します。それはできませんつ以上が存在する可能性があるため、「」X11ディスプレイを使用します。たとえば、「高速ユーザー切り替え」を使用する場合。

どうすればこの作品を作ることができますか?
ジェイクエイチソン

誰も私がこれを修正する方法を知っていますか?
ジェイクエイチソン

1
setxkbmapを呼び出すためにudevを取得しました。udevルールは、別のスクリプトをバックグラウンドにするスクリプトを呼び出します(したがって、udevは完了できます)。2番目のスクリプトは1秒間停止し、予想されるX11変数を設定し、setxkbmapをトリガーします。詳細については、メインの質問に対する私の答えをご覧ください。
トーマスシュライバー

@rizumu:ああ、幸運にもGDMで動作するようになった。
悲しみ

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、システム初期化スクリプトを使用して悪魔化できます。


おかげで、スクリプト自体は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を使用し、既存の/etc/X11/xorg.conf.d/vim 10-evdev.confで独自のUSBキーボードを構成しました。

@rizumu:賢いごっこ、共有してくれてありがとう。


1
私は18.2 Linuxのミントにx.org.conf.dディレクトリを持っていない
マックス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()

次に、この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秒間イベントがトリガーされないことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.