regola udev per caricare automaticamente il layout della tastiera quando è collegata la tastiera USB


24

Sto provando a caricare un nuovo layout di tastiera quando collego una tastiera USB ma la mia regola udev non funziona.

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

LABEL = "usb_xmodmap_auto"
AZIONE == "aggiungi", RUN + = "/ usr / bin / xmodmap ~ / .usbXmodmap"
AZIONE == "rimuovi", ESEGUI + = "/ usr / bin / xmodmap ~ / .pndXmodmap"

Ho ricaricato le regole usando:

> sudo udevadm control --Reload-rules

e riavviando il sistema ma quando inserisco la tastiera USB la xmodmap originale è ancora caricata e quindi il layout della tastiera è sbagliato, ma se eseguo il comando nel terminale

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

funzionano bene.

spero che qualcuno possa aiutare.

Modificare:

solo per aiutare di più ho eseguito alcuni test udevadm:

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

uscite:

run_command: calling: test
udevadm_test: versione 151
Questo programma è solo per il debug, non esegue alcun programma,
specificato da un tasto RUN. Potrebbe mostrare risultati errati, perché
alcuni valori possono essere diversi o non disponibili in una corsa di simulazione.

[...]
parse_file: lettura '/etc/udev/rules.d/usb-keyboard.rules' come file delle regole
udev_rules_new: le regole usano 100572 byte token (8381 * 12 byte), 21523 byte buffer
udev_rules_new: indice temporaneo utilizzato 35380 byte (1769 * 20 byte)
udev_device_new_from_syspath: il dispositivo 0x3b4d8 ha 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 = "Tastiera conforme a 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,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'

e

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

uscite:

run_command: calling: test
udevadm_test: versione 151
Questo programma è solo per il debug, non esegue alcun programma,
specificato da un tasto RUN. Potrebbe mostrare risultati errati, perché
alcuni valori possono essere diversi o non disponibili in una corsa di simulazione.

[...]
parse_file: lettura '/etc/udev/rules.d/usb-keyboard.rules' come file delle regole
udev_rules_new: le regole usano 100572 byte token (8381 * 12 byte), 21523 byte buffer
udev_rules_new: indice temporaneo utilizzato 35380 byte (1769 * 20 byte)
udev_device_new_from_syspath: il dispositivo 0x3b4d8 ha 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 = "Tastiera conforme a 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 = rimuovi
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'

che sembra mostrare che dovrebbe funzionare, ma non spera che questo aiuti a ottenere una risposta.


Risposte:


16

Ho trovato il modo di aggirare il problema, anche se è un po 'confuso.

Oggi sono arrivato allo stesso preciso punto nel tentativo di configurare due tastiere con udev, setxkbmap e xinput --list e per farle funzionare con hotplugging USB. Sto scambiando i tasti in giro, non cambiando il layout, ma è lo stesso, una volta che hai identificato la tua tastiera su un hot plug e puoi chiamare in modo condizionale setxkbmap, allora dovresti essere in grado di impostare la lingua della sola tastiera che hai specificato . L'elenco dei layout di tastiera è disponibile qui ls -l /usr/share/kbd/keymaps/i386/ed è possibile trovare il nome del dispositivo su cui visualizzare xinput -list.

  1. Ti consigliamo di sostituire rizumucon il tuo nome utente, poiché ho scoperto che non era possibile un modo per farlo senza essere esplicito.
  2. Assicurati di grep sul yournome della tastiera.
  3. Utilizzare lsusbper scoprire l'ID hardware che è necessario impostare nella regola udev. La mia tastiera das si presenta cosìBus 002 Device 009: ID 04d9:2013 Holtek Semiconductor, Inc.

Ho prima impostato la regola udev per il rilevamento automatico della tastiera creando una regola udev:

Nel file /etc/udev/rules.d/00-usb-keyboards.rules:

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

Ho due file ~ / bin / kbd e ~ / bin / kbd_udev. Assicurati che abbiano le autorizzazioni giustechmod 755 ~/bin/kbd*

Lo ~/bin/kbd_udevscript contiene:

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

E noterai che tutto ciò che fa è chiamare ~/bin/kbdin background, in modo che udev possa completare il suo processo e attivare la tastiera. All'interno dello ~/bin/kbdscript dormiamo per un secondo, perché dobbiamo attendere fino all'attivazione della tastiera in modo da poter ottenere l'ID del dispositivo usando xinput. Per raggiungere questo ho impostato alcune variabili e li esportate, in modo xinput setxkbmap può fare burbero lavoro: DISPLAY, XAUTHORITY, HOME, e uno daskb_idper l'id del mio 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

Grazie mille per avermi aiutato a rispondere alla mia domanda è AskUbuntu: askubuntu.com/questions/337411/…
Sadi

E mi chiedo se puoi anche aiutarmi ad aggiungere un messaggio di notifica alla fine di questo script (ad es notify-send "USB Keyboard is plugged in and ready for use now." -i gtk-dialog-info -t 1000 -u normal.). Dato che non so molto sullo scripting, ho provato a inserirlo prima o dopo "fi", ma in entrambi i casi il messaggio di notifica continuava ad apparire più e più volte :-(
Sadi

Perché impostare OWNERper questo dispositivo?
Limbo Peng,

1
Cosa fa la xset r rate 200 30linea? xsetnon è disponibile sulla mia installazione di Ubuntu 17.04.
Kleinfreund,

1
Non sono in grado di eseguire xmodmap $HOME/.Xmodmapusando uno script analogo al tuo "/ home / rizumu / bin / kbd". Perché dovrebbe essere?
Geremia,

5

A seconda della tua distribuzione, potresti già avere una regola udev per le tastiere in /lib/udev/rules.d/64-xorg-xkb.rules. Su Ubuntu, questo importa / etc / default / keyboard, che ha opzioni più o meno così:

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

Per la mia configurazione, ho scoperto che questa regola integrata era in esecuzione dopo la mia regola udev personalizzata e stava ignorando le mie impostazioni. Invece ho cambiato XKBOPTIONS in / etc / default / tastiera per essere:

XKBOPTIONS="-option ctrl:nocaps"

Per ottenere il comportamento "Blocco maiuscole è controllo" volevo su tutte le tastiere.


2
Grande idea! Il mio funziona con un soloXBKOPTIONS="ctrl:nocaps"
RasmusWL

3

Se stai eseguendo GNOME, dovrai disabilitare il suo plug-in di gestione della tastiera in modo che non sovrascriva le modifiche al layout.

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

Eseguire di nuovo lo stesso comando per abilitarlo come desiderato.


sto correndo angstrom. funzionerà?
Jake Aitchison,

Stai usando GNOME su Ångström?
Ignacio Vazquez-Abrams,

no, sto usando xfce 4.6.1
Jake Aitchison,

1
Nel mio Ubuntu 13.04, questo è dconfsotto /org/gnome/settings-daemon/plugins/keyboard/active.
nh2,

1
E il comando per Ubuntu 13.04 è:gsettings set org.gnome.settings-daemon.plugins.keyboard active false
Sadi,

3

Non funziona perché udeve xmodmapnon ha accesso al display X11. In realtà, udevnon sa nemmeno se ci sono display X11 attivi.

  • Nota: display , plurale. Non può usare "il" display X11 perché può essercene più di uno. Ad esempio, se si utilizza "Cambio rapido utente".

quindi Come potrei farlo funzionare?
Jake Aitchison,

qualcuno sa come posso risolvere questo?
Jake Aitchison,

1
Ho ottenuto udev per chiamare setxkbmap. La regola udev chiama uno script che fa da sfondo a un altro script (quindi udev può essere completato). Il secondo script fa una pausa per un secondo, imposta le variabili X11 previste e attiva setxkbmap. Vedi la mia risposta alla domanda principale per maggiori dettagli.
Thomas Schreiber,

@rizumu: Ah, buona fortuna, comunque, per farlo funzionare con GDM.
Grawity

3

Penso di aver trovato un modo molto più pulito di configurarlo, che non richiede un hack X11 speciale.

L'idea alla base di ciò è che udevrileverà solo i nuovi input da tastiera e creerà un collegamento simbolico per ciascun layout, quindi inotifycercherà un nuovo layout nello spazio utente.

regole 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"

Con queste regole, ho una directory sotto dev ( /dev/input/by-layout) per controllare i cambiamenti negli script di userspace.

Script dello spazio utenti per KDE

Ad esempio, quando uso KDE ho questo script (auto) in esecuzione:

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

Per me funziona come un incantesimo. Per cambiare il layout del sistema (che non mi serve in questo momento), uno script simile che uso loadkeyspuò essere demonizzato usando uno script di inizializzazione del sistema.


Grazie, questo mi ha fatto capire che posso usare solo inotifywaitper eseguire uno script di installazione su qualsiasi modifica /dev/input, poiché lo script stesso è idempotente.
Charlie Gorichanaz,

3

Che dire della configurazione di X.Org? Da Gentoo Wiki: X.Org/Input_drivers - udev :

Esempio: se si dispone di una tastiera Logitech Access per la parte francese della Svizzera, è possibile utilizzare quanto segue:

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

Per una spiegazione approfondita, leggi:

man xorg.conf

e:

man evdev

ArchWiki dimostra di usare la stessa sintassi in xorg.conf ma nota che "al giorno d'oggi dovresti creare un file di configurazione separato, come /etc/X11/xorg.conf.d/90-keyboard-layouts.conf". Uso Arch e ho configurato la mia tastiera USB nell'attuale /etc/X11/xorg.conf.d/vim 10-evdev.conf Ha funzionato per me.

@rizumu: Clever Kludge, grazie per la condivisione.


1
Non ho una directory x.org.conf.d su Linux Mint 18.2
Max N

2

Per rispondere alla domanda sull'accesso al display in esecuzione, è possibile esportare la variabile DISPLAY appropriata nello script, presupponendo che le autorizzazioni per il display siano impostate correttamente. ( man xsetper le autorizzazioni di visualizzazione.)

In molti casi normali puoi semplicemente export DISPLAY=:0per il comando, poiché è il primo display su un singolo sistema utente. Probabilmente è più semplice eseguire uno script piuttosto che xmodmap direttamente, in quanto ciò ti consentirà di avere un maggiore controllo sulle variabili di ambiente e il resto. (Quindi sostituisci "/ usr / bin / xmodmap ~ / .usbXmodmap" nella tua regola con "/usr/local/bin/keyboard_plug.sh" e inserisci i comandi appropriati in quello script insieme alla variabile DISPLAY.)

Come notato sopra, tuttavia, se si assume DISPLAY =: 0, si potrebbero riscontrare problemi in seguito se si hanno più utenti o display. Puoi scrivere script per rilevare la visualizzazione appropriata, ma in tal caso sei da solo (per quanto riguarda questa risposta). :)


1

Dato che non riuscivo a far sì che gli hack facessero funzionare le regole di udev, ho scritto un piccolo script Python che utilizzava pyudevper monitorare gli eventi di input.

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

Quindi uso questo file di unità utente systemd per mantenerlo in esecuzione ( 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 inotifywaitsoluzione di @ giosh94mhz è un po 'più semplice ed evita la dipendenza da pyudev. Tuttavia, per qualche motivo ho scoperto che l' inotifyevento non veniva attivato per 10-20 secondi dopo che la mia tastiera era connessa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.