règle udev pour charger automatiquement la disposition du clavier lorsque le clavier usb est branché

24

Im essayant de charger une nouvelle disposition de clavier lorsque je branche un clavier USB mais ma règle udev ne fonctionne pas.

SOUS-SYSTÈME == "entrée", ATTR {idVendor} == "062a", ATTR {idProduct} == "0201", GOTO = "usb_xmodmap_auto"

LABEL = "usb_xmodmap_auto"
ACTION == "ajouter", RUN + = "/ usr / bin / xmodmap ~ / .usbXmodmap"
ACTION == "supprimer", RUN + = "/ usr / bin / xmodmap ~ / .pndXmodmap"

J'ai rechargé les règles en utilisant:

> sudo udevadm control --reload-rules

et en redémarrant le système, mais lorsque je branche le clavier USB, le xmodmap d'origine est toujours chargé et donc la disposition du clavier est incorrecte, mais si j'exécute la commande dans le terminal

> / usr / bin / xmodmap ~ / .usbXmodmap
ou
> / usr / bin / xmodmap ~ / .pndXmodmap

ils fonctionnent très bien.

j'espère que quelqu'un peut aider.

Modifier:

juste pour aider plus j'ai exécuté quelques tests udevadm:

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

les sorties:

run_command: appel: test
udevadm_test: version 151
Ce programme est destiné au débogage uniquement, il n'exécute aucun programme,
spécifié par une clé RUN. Il peut afficher des résultats incorrects, car
certaines valeurs peuvent être différentes ou non disponibles lors d'une simulation.

[...]
parse_file: lecture de '/etc/udev/rules.d/usb-keyboard.rules' comme fichier de règles
udev_rules_new: les règles utilisent des jetons de 100572 octets (8381 * 12 octets), 21523 octets de tampon
udev_rules_new: index temporaire utilisé 35380 octets (1769 * 20 octets)
udev_device_new_from_syspath: le périphérique 0x3b4d8 a 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: socket 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 '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: PRODUIT = 3 / 62a / 201/110
udevadm_test: NAME = "Clavier compatible 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 = entrée: 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,17917A, 17B, 17C, 17D, 17F, 180,181,182,185,185 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 = entrée
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: exécutez: '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: exécutez: '/ usr / bin / xmodmap ~ / .usbXmodmap'

et

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

les sorties:

run_command: appel: test
udevadm_test: version 151
Ce programme est destiné au débogage uniquement, il n'exécute aucun programme,
spécifié par une clé RUN. Il peut afficher des résultats incorrects, car
certaines valeurs peuvent être différentes ou non disponibles lors d'une simulation.

[...]
parse_file: lecture de '/etc/udev/rules.d/usb-keyboard.rules' comme fichier de règles
udev_rules_new: les règles utilisent des jetons de 100572 octets (8381 * 12 octets), 21523 octets de tampon
udev_rules_new: index temporaire utilisé 35380 octets (1769 * 20 octets)
udev_device_new_from_syspath: le périphérique 0x3b4d8 a devpath '/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/1-2.3:1.1/input/input10'
udev_rules_apply_to_event: socket RUN: @ / 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: PRODUIT = 3 / 62a / 201/110
udevadm_test: NAME = "Clavier compatible 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 = entrée: 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,17917A, 17B, 17C, 17D, 17F, 180,181,182,185,185 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 = supprimer
udevadm_test: SUBSYSTEM = entrée
udevadm_test: exécutez: 'socket: @ / org / freedesktop / hal / udev_event'
udevadm_test: run: 'socket: / org / kernel / udev / monitor'
udevadm_test: exécutez: '/ usr / bin / xmodmap ~ / .pndXmodmap'

ce qui semble montrer que cela devrait fonctionner, mais il n'espère pas que cela aide à obtenir une réponse.

Jake Aitchison
la source
1
liés .

Réponses:

16

J'ai trouvé un moyen de contourner cela, bien que ce soit un peu hacky.

Je suis arrivé au même point aujourd'hui en essayant de configurer deux claviers avec udev, setxkbmap et xinput --list et de les faire fonctionner avec le hotplugging USB. J'échange des touches, sans changer la disposition, mais c'est toujours la même chose, une fois que vous avez identifié votre clavier sur un hotplug et pouvez appeler conditionnellement setxkbmap, vous devriez pouvoir définir la langue du clavier que vous avez spécifié uniquement . La liste des dispositions de clavier peut être trouvée ici ls -l /usr/share/kbd/keymaps/i386/et vous pouvez trouver le nom de votre appareil avec lequel gre xinput -list.

  1. Vous voudrez remplacer rizumuvotre nom d'utilisateur, car j'ai trouvé qu'il n'était pas possible de le faire sans être explicite.
  2. Assurez-vous de grep sur le yournom du clavier.
  3. Utilisez lsusbpour découvrir l'ID matériel que vous devez définir dans la règle udev. Mon clavier das ressemble à ceciBus 002 Device 009: ID 04d9:2013 Holtek Semiconductor, Inc.

J'ai d'abord configuré la règle udev pour détecter automatiquement le clavier en créant une règle udev:

Dans le dossier /etc/udev/rules.d/00-usb-keyboards.rules:

ACTION=="add", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="2013", RUN+="/home/rizumu/bin/kbd_udev", OWNER="rizumu"

J'ai deux fichiers ~ / bin / kbd et ~ / bin / kbd_udev. Assurez-vous qu'ils ont les bonnes autorisationschmod 755 ~/bin/kbd*

Le ~/bin/kbd_udevscript contient:

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

Et vous remarquerez qu'il ne fait qu'appeler ~/bin/kbden arrière-plan, afin que udev puisse terminer son processus et activer le clavier. A l' intérieur du ~/bin/kbdscript que nous dormons pour une seconde, parce que nous devons attendre jusqu'à ce que le clavier est activé afin que nous puissions obtenir l'ID du périphérique en utilisant xinput. Pour cela , je l' ai achive définirait des variables et à les exporter afin xinput setxkbmap peut faire Thier travail: DISPLAY, XAUTHORITY, HOMEet un daskb_idpour l'id de mon 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
Thomas Schreiber
la source
Merci beaucoup de m'avoir aidé à répondre à ma propre question: AskUbuntu: askubuntu.com/questions/337411/…
Sadi
Et je me demande si vous pouvez aussi m'aider à ajouter un message de notification à la fin de ce script (par exemple notify-send "USB Keyboard is plugged in and ready for use now." -i gtk-dialog-info -t 1000 -u normal). Comme je ne connais pas grand-chose au script, j'ai essayé de l'insérer avant ou après "fi" mais dans les deux cas, le message de notification apparaissait encore et encore :-(
Sadi
Pourquoi choisir OWNERcet appareil?
Limbo Peng
1
Que fait la xset r rate 200 30ligne? xsetn'est pas disponible sur mon installation Ubuntu 17.04.
kleinfreund
1
Je ne suis pas en mesure d'exécuter en xmodmap $HOME/.Xmodmaputilisant un script analogue à votre "/ home / rizumu / bin / kbd". Pourquoi serait-ce?
Geremia
5

Selon votre distribution, vous pouvez déjà avoir une règle udev pour les claviers dans /lib/udev/rules.d/64-xorg-xkb.rules. Sur Ubuntu, cela importe / etc / default / keyboard, qui a des options à peu près comme ceci:

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

Pour ma configuration, j'ai constaté que cette règle intégrée s'exécutait après ma règle udev personnalisée et remplaçait mes paramètres. Au lieu de cela, j'ai changé XKBOPTIONS dans / etc / default / keyboard pour être:

XKBOPTIONS="-option ctrl:nocaps"

Pour obtenir le comportement "Caps Lock is Control" que je voulais sur tous les claviers.

jsha
la source
2
Bonne idée! Le mien fonctionne avec justeXBKOPTIONS="ctrl:nocaps"
RasmusWL
3

Si vous exécutez GNOME, vous devrez désactiver son plug-in de gestion du clavier afin qu'il ne remplace pas vos modifications de disposition.

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

Exécutez à nouveau la même commande pour l'activer comme vous le souhaitez.

Ignacio Vazquez-Abrams
la source
im exécutant angstrom. Est-ce que ça va marcher?
Jake Aitchison
Utilisez-vous GNOME sur Ångström?
Ignacio Vazquez-Abrams
non, j'utilise xfce 4.6.1
Jake Aitchison
1
Dans mon Ubuntu 13.04, c'est en dconfdessous /org/gnome/settings-daemon/plugins/keyboard/active.
nh2
1
Et la commande pour Ubuntu 13.04 est:gsettings set org.gnome.settings-daemon.plugins.keyboard active false
Sadi
3

Cela ne fonctionne pas car udevet xmodmapn'avez pas accès à votre écran X11. En fait, il udevne sait même pas s'il y a affichages actifs X11.

  • Remarque: affiche , pluriel. Il ne peut pas utiliser "l'affichage" X11 car il peut y en avoir plusieurs. Par exemple, si vous utilisez le "changement rapide d'utilisateur".
grawity
la source
alors comment pourrais-je faire fonctionner cela?
Jake Aitchison
quelqu'un sait comment je peux résoudre ce problème?
Jake Aitchison
1
J'ai demandé à udev d'appeler setxkbmap. La règle udev appelle un script qui met en arrière-plan un autre script (afin que udev puisse terminer). Le deuxième script fait une pause d'une seconde, configure les variables X11 attendues et déclenche setxkbmap. Voir ma réponse à la question principale pour plus de détails.
Thomas Schreiber,
@rizumu: Ahh, bonne chance pour que cela fonctionne avec GDM.
grawity
3

Je pense avoir trouvé une façon beaucoup plus propre de configurer cela, qui ne nécessite pas de hack X11 spécial.

L'idée derrière cela est que udev ne détectera que les nouvelles entrées au clavier et créera un lien symbolique pour chaque disposition, puis inotifysurveillera la nouvelle disposition dans l'espace utilisateur.

règles 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"

Avec ces règles, j'ai un répertoire sous dev ( /dev/input/by-layout) pour surveiller les changements dans les scripts de l'espace utilisateur.

Script d'espace utilisateur pour KDE

Par exemple, lorsque j'utilise KDE, j'ai ce script (auto) en cours d'exécution:

#!/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

Cela fonctionne comme un charme pour moi. Pour changer la disposition du système (dont je n'ai pas besoin pour l'instant), un script similaire qui loadkeyspeut être utilisé peut être diabolisé à l'aide d'un script d'initialisation système.

giosh94mhz
la source
Merci, cela m'a fait réaliser que je peux simplement utiliser inotifywaitpour exécuter un script de configuration à tout changement /dev/input, car le script lui-même est idempotent.
Charlie Gorichanaz
3

Qu'en est-il de la configuration X.Org? Du Gentoo Wiki: X.Org/Input_drivers - udev :

Exemple: si vous disposez d'un clavier Logitech Access pour la Suisse romande, vous pouvez utiliser les éléments suivants:

Fichier: /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

Pour une explication approfondie, lisez:

man xorg.conf

et:

man evdev

ArchWiki montre l'utilisation de la même syntaxe dans xorg.conf mais note que "de nos jours, vous devez créer un fichier de configuration séparé, comme /etc/X11/xorg.conf.d/90-keyboard-layouts.conf". J'utilise Arch et j'ai configuré mon propre clavier USB dans le fichier /etc/X11/xorg.conf.d/vim 10-evdev.conf existant.

@rizumu: kludge intelligent, merci pour le partage.

Casey Jones
la source
1
Je n'ai pas de répertoire x.org.conf.d sur Linux Mint 18.2
Max N
2

Pour répondre à votre question sur l'accès à l'affichage en cours, vous pouvez exporter la variable DISPLAY appropriée dans le script, en supposant que les autorisations pour l'affichage sont correctement définies. ( man xsetpour les autorisations d'affichage.)

Dans de nombreux cas habituels, vous pouvez simplement export DISPLAY=:0utiliser la commande, car il s'agit du premier affichage sur un système mono-utilisateur. Il est probablement plus facile d'exécuter un script plutôt que xmodmap directement, car cela vous permettra d'avoir plus de contrôle sur les variables d'environnement et le reste. (Remplacez donc "/ usr / bin / xmodmap ~ / .usbXmodmap" dans votre règle par "/usr/local/bin/keyboard_plug.sh" et placez les commandes appropriées dans ce script avec la variable DISPLAY.)

Comme indiqué ci-dessus, cependant, si vous supposez DISPLAY =: 0, vous risquez de rencontrer des problèmes plus tard si vous avez plusieurs utilisateurs ou affichages. Vous pouvez écrire des scripts pour détecter l'affichage approprié, mais dans ce cas, vous êtes seul (en ce qui concerne cette réponse). :)

rust_and_moth
la source
1

Comme je n'ai pas pu obtenir les hacks pour faire fonctionner les règles udev, j'ai écrit un petit script Python à l'aide pyudevde la surveillance des événements d'entrée.

#! /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()

J'utilise ensuite ce fichier d'unité utilisateur systemd pour le faire fonctionner ( 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

La inotifywaitsolution de @ giosh94mhz est un peu plus simple et évite la dépendance pyudev. Cependant, pour une raison quelconque, j'ai trouvé que l' inotifyévénement n'était pas déclenché pendant 10 à 20 secondes après la connexion de mon clavier.

Ryan Marcus
la source