Linux

Wacom 墊的 udev 規則不起作用

  • March 30, 2020

我有以下腳本來定義我的 Wacom Intuos S 2 的按鈕映射:

/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh

#!/bin/bash

export DISPLAY=:0
export XAUTHORITY=/home/scriptim/.Xauthority
/usr/bin/sleep 1 # wait for device to be ready
/usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'
/usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 3 'key +'
/usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 8 'key +Ctrl z -Ctrl'
/usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 9 'key +Ctrl +Shift z -Ctrl -Shift'

如果我手動執行此腳本,它可以正常工作。

我的目標是在插入墊時自動執行此腳本。我使用以下udev規則進行了嘗試:

/etc/udev/rules.d/10-wacom_intuos_s_2_pad.rules

ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="033b", RUN+="/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh"

但是,如果我插入墊,腳本不會映射按鈕。


我正在執行 Arch Linux ( 5.5.10-arch1-1)

$ lsusb
...
Bus 004 Device 015: ID 056a:033b Wacom Co., Ltd CTL-490 [Intuos Draw (S)]
...
$ udevadm info -a -n hidraw0
...
 looking at parent device '/devices/pci0000:00/0000:00:10.0/usb4/4-2':
   KERNELS=="4-2"
   SUBSYSTEMS=="usb"
   DRIVERS=="usb"
   ATTRS{authorized}=="1"
   ATTRS{bcdDevice}=="0100"
   ATTRS{bmAttributes}=="80"
   ATTRS{bMaxPower}=="498mA"
   ATTRS{manufacturer}=="Wacom Co.,Ltd."
   ATTRS{quirks}=="0x0"
   ATTRS{maxchild}=="0"
   ATTRS{bNumInterfaces}==" 3"
   ATTRS{bMaxPacketSize0}=="64"
   ATTRS{devpath}=="2"
   ATTRS{ltm_capable}=="no"
   ATTRS{busnum}=="4"
   ATTRS{devnum}=="15"
   ATTRS{tx_lanes}=="1"
   ATTRS{bDeviceSubClass}=="00"
   ATTRS{bDeviceClass}=="00"
   ATTRS{bDeviceProtocol}=="00"
   ATTRS{bNumConfigurations}=="1"
   ATTRS{speed}=="12"
   ATTRS{version}==" 2.00"
   ATTRS{product}=="Intuos PS"
   ATTRS{avoid_reset_quirk}=="0"
   ATTRS{idVendor}=="056a"
   ATTRS{configuration}==""
   ATTRS{devspec}=="(null)"
   ATTRS{urbnum}=="174"
   ATTRS{bConfigurationValue}=="1"
   ATTRS{removable}=="unknown"
   ATTRS{rx_lanes}=="1"
   ATTRS{idProduct}=="033b"
...
$ udevadm test --action="add" /devices/pci0000:00/0000:00:10.0/usb4/4-2
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /usr/lib/udev/rules.d/10-dm.rules
Reading rules file: /etc/udev/rules.d/10-wacom_intuos_s_2_pad.rules
...
Reading rules file: /usr/lib/udev/rules.d/65-libwacom.rules
...
Reading rules file: /usr/lib/udev/rules.d/wacom.rules
Invalid inotify descriptor.
DEVPATH=/devices/pci0000:00/0000:00:10.0/usb4/4-2
DEVNAME=/dev/bus/usb/004/015
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=56a/33b/100
TYPE=0/0/0
BUSNUM=004
DEVNUM=015
MAJOR=189
MINOR=398
ACTION=add
SUBSYSTEM=usb
ID_VENDOR=Wacom_Co._Ltd.
ID_VENDOR_ENC=Wacom\x20Co.\x2cLtd.
ID_VENDOR_ID=056a
ID_MODEL=Intuos_PS
ID_MODEL_ENC=Intuos\x20PS
ID_MODEL_ID=033b
ID_REVISION=0100
ID_SERIAL=Wacom_Co._Ltd._Intuos_PS
ID_BUS=usb
ID_USB_INTERFACES=:030000:030102:
ID_VENDOR_FROM_DATABASE=Wacom Co., Ltd
ID_MODEL_FROM_DATABASE=CTL-490 [Intuos Draw (S)]
ID_PATH=pci-0000:00:10.0-usb-0:2
ID_PATH_TAG=pci-0000_00_10_0-usb-0_2
USEC_INITIALIZED=4102997566
run: '/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh'
Unload module index
Unloaded link configuration context.
$ journalctl -xe
Mar 22 17:38:55 scriptim systemd-udevd[5927]: 1-1: Process '/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh' failed with exit code 255.

本質上,這是競爭條件和xsetwacom從 udev 規則執行時與從熟悉的圖形終端執行時的行為差異的組合,例如由於環境變數的差異。

問題1:環境變數。

首先解決第二個問題:這類似於shell 腳本在從 cronjob 執行時表現不同的情況。

要將您的環境與 udev 環境進行比較,請執行env``printenv

printenv > my-env.txt

從圖形終端,然後添加這個 udev 腳本:

/usr/bin/printenv > /tmp/udev-env.txt

然後你可以比較my-env.txtudev-env.txt

要推斷xsetwacom正在使用的環境變數,請安裝ltrace執行如下命令

ltrace -f -e getenv -o my-ltrace-01.log xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'

由於我沒有 Wacom 設備,因此無法執行完整的命令。

$ xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'
Cannot find device 'Wacom Intuos S 2 Pad pad'.

但是,僅根據xsetwacom它退出之前的距離,我可以告訴它使用DISPLAYand XAUTHORITY

15447 libX11.so.6->getenv("DISPLAY")             = ":0"
15447 libxcb.so.1->getenv("DISPLAY")             = ":0"
15447 libxcb.so.1->getenv("DISPLAY")             = ":0"
15447 libXau.so.6->getenv("XAUTHORITY")          = "/home/nathaniel/.Xauthority"
15447 libX11.so.6->getenv("XLIBBUFFERSIZE")      = nil
15447 libX11.so.6->getenv("XLIB_SKIP_ARGB_VISUALS") = nil
15447 libX11.so.6->getenv("XKB_DEBUG")           = nil
15447 libX11.so.6->getenv("_XKB_OPTIONS_ENABLE") = nil
15447 libX11.so.6->getenv("XKB_DISABLE")         = nil
15447 +++ exited (status 0) +++

您可以通過列印這些值來找到它們。

$ printf 'DISPLAY=%q\n' "$DISPLAY"
DISPLAY=:0
$ printf 'XAUTHORITY=%q\n' "$XAUTHORITY"
XAUTHORITY=/home/nathaniel/.Xauthority

然後在腳本頂部定義它們。

#!/bin/bash

# Just an example, yours will be different.
export DISPLAY=:0
export XAUTHORITY=/home/nathaniel/.Xauthority
sleep 1
# The rest of the script.

由於其他原因,該腳本仍然可能無法工作,但消除環境變數的差異對其他人來說似乎已經足夠了。相關問題中的另一位使用者能夠以這種方式使其在 Ubuntu 18.04 上執行:

您需要在腳本中添加兩個變數導出,一個 forDISPLAYXAUTHORITY. 這些用於辨識和訪問正確的 X 會話。env您可以通過在以普通使用者身份登錄時執行來獲取適當的值。

問題 2:競爭條件。

現在是競爭條件:該xsetwacom命令依賴於 X 伺服器辨識硬體,因此在它準備好之前執行它會導致它失敗。一次顯然是足夠的sleep 1,但不再是。(有時人們使用sleep 2, sleep 3, or sleep 4,沒有特別的原因。廣義地說,它sleep 1甚至是必要的,這讓我很困擾。)

插入設備時:

  1. Linux 檢測設備並根據 udev 規則創建設備條目。
  2. X 伺服器檢測到設備。

您不能xsetwacom在第 2 階段之前執行。您的腳本失敗是因為您在第 1 階段執行它,此時 X 還不知道設備。

Gilles ‘停止作惡’https://unix.stackexchange.com/a/65792/30049

這一切都很好,但是當人們嘗試這個時,它就不再起作用了:

我贊成您對詳細資訊的回答,但由於以下原因,我不確定這是否正確:我嘗試使用sleep幾秒鐘。插入電源後,平板電腦會在不到一秒的時間內工作,因此在執行命令時,設備已經被檢測到並被X. 但是還是不行?

由於我沒有您的硬體或作業系統,我無法複製您的問題。但這是我從其他執行緒中收集到的:sleep延遲本身是不夠的。有些人有解決方法,例如:

也許我見過的最徹底的解決方案是在使用 systemd 服務文件的連結執行緒中:

我最終不得不使用由 udev 規則觸發的 systemd 服務啟動腳本:

$ cat /etc/udev/rules.d/99-wacom.rules
SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="056a", ENV{ID_MODEL_ID}=="0302", TAG+="systemd"

$$ … $$ 這TAG+="systemd"使其他 systemd 服務(系統或使用者)能夠依賴於設備(將其註冊為設備單元,請參閱 man systemd.device)。

引用自:https://unix.stackexchange.com/questions/574258