web-dev-qa-db-ja.com

xsetwacomがudevから機能しないのはなぜですか?

WacomBambooタブレットを180度回転させるスクリプトを作成しました。自分(ユーザー)またはrootとして実行すると正常に機能しますが、udevから開始した場合(つまり、タブレットをusbポートに接続した場合)は機能しません。

devルール

SUBSYSTEMS=="usb", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="00d1", ATTRS{manufacturer}=="Wacom Co.,Ltd.", RUN+="/usr/local/bin/red-wacom-bamboo.sh"

Wacomスクリプト/usr/local/bin/red-wacom-bamboo.sh

#!/usr/bin/env bash

exec > /tmp/red-wacom.log
exec 2>&1

# I had to do this otherwise xsetwacom would say:
# "Failed to open Display ."
# Is there a way to do this without using my username?
export XAUTHORITY=/home/redsandro/.Xauthority
export DISPLAY=:0

/usr/bin/xsetwacom set "Wacom Bamboo 2FG 4x5 Pen stylus" Rotate half
/usr/bin/xsetwacom set "Wacom Bamboo 2FG 4x5 Finger touch" Rotate half

結果は/tmp/red-wacom.logになります

Cannot find device 'Wacom Bamboo 2FG 4x5 Pen stylus'.
Cannot find device 'Wacom Bamboo 2FG 4x5 Finger touch'.

(ログのエラーは、udevルール自体に問題がないことを意味することに注意してください。)

スクリプトでsleepを設定してみましたが、数ミリ秒かかる場合があります。しかし、それは役に立ちません。

  • udevから直接呼び出されたときにこのスクリプトが機能しないのはなぜですか?
    • これを修正するにはどうすればよいですか?
  • udevから特定のユーザーとしてスクリプトを呼び出すことはできますか? (例:sync /home外部バックアップドライブへ-/ home /はそのユーザーにのみ表示されます)
8
Redsandro

かなり簡単な回避策があります。次のようなものをxorg.conf(または私が行ったようにxorg.conf.d内のファイル)に追加できます。

anthony@Watt:/etc/X11/xorg.conf.d$ cat 55-local-wacom.conf 
Section "InputClass"
       Identifier "Wacom Left Handed"
       MatchDriver "wacom"
       Option "Rotate" "half"
EndSection

設定できるすべてのオプションの詳細については、 wacom(4)manpage を確認してください。

(理論的には、MatchProductを使用してタッチパッド、ペン、イレーサーなどを個別に構成できますが、しばらく前に試してみると、Xorgがセグメンテーション違反を起こしました。フロートしようとした場合も同じです。しかしあなたはそれを何もしていません...そして多分バグは今修正されています。)

3
derobert

デバイスを接続するとき:

  1. Linuxはデバイスを検出し、udevルールに基づいてデバイスエントリを作成します。
  2. Xサーバーがデバイスを検出します。

ステージ2の前にxsetwacomを実行することはできません。Xがまだデバイスを認識していないステージ1でスクリプトを実行しているため、スクリプトは失敗します。

gnome-settings-daemon でいくつかの設定を行うことができます。 D-Bus を通じて新しいデバイスの通知を受け取ると思いますが、D-Busイベントがどのように見えるかわかりません。 dbus-monitorでバスをスパイしてみてください。

これは、2つのファイルを作成する場合に機能します。1つのラッパースクリプトはudevによって呼び出され、udevはバックグラウンドで実際の構成スクリプトを呼び出します。 X11がその仕事をする時間があるように、構成スクリプトは少しの間スリープする必要があります。これが私が使用するセットアップです:

dev(/usr/local/bin/setupwacom.sh)によって呼び出されるラッパースクリプト:

#!/usr/bin/env bash
/usr/local/bin/setupwacom-post-X11.sh &

ラッパースクリプトによって呼び出される構成スクリプト(/usr/local/bin/setupwacom-post-X11.sh):

#!/usr/bin/env bash
sleep 2
export XAUTHORITY=/home/adrian/.Xauthority
export DISPLAY=:0
# Put your xsetwacom commands here, for example: 
xsetwacom --set "Wacom Intuos S Pad pad" Button 1 "key +ctrl +shift e"
2
Adrian

ここでの答えはどれもうまくいきませんでした。また、設定したいオプションをxorg.confで指定できませんでした。

$ xsetwacom -x get 'Wacom Intuos PT S Pad pad' button 1 
Button: Actions are not supported by xorg.conf. Try Shell format (-s) instead.

結局、udevルールによってトリガーされるsystemdサービスでスクリプトを開始する必要がありました。

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

ベンダーとモデルIDは、デバイスが接続された状態でlsusbを実行していることがわかります。

Udevルールをリロードするには:

$ udevadm control --reload-rules
$ udevadm trigger

TAG+="systemd"は、他のsystemdサービス(システムまたはユーザー)がデバイスに依存できるようにします(デバイスユニットとして登録します。man systemd.deviceを参照)。デバイスユニットの名前を見つけるには、udevadm monitorを実行し、タブレットを接続します。私は得る

UDEV  [2918.098423] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3 (usb)
...

Systemdがそれをピックアップしていることを確認するには

$ systemctl status /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/
● sys-devices-pci0000:00-0000:00:1d.0-usb2-2\x2d1-2\x2d1.3.device - CTH-480 [Intuos Pen & Touch (S)]
   Loaded: loaded
   Active: active (plugged) since Mon 2016-06-20 11:14:20 UYT; 29min ago
   Device: /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3

したがって、デバイスユニットはsys-devices-pci0000:00-0000:00:1d.0-usb2-2\x2d1-2\x2d1.3.deviceであり、systemdサービスユニットで使用できます。

 $ cat .config/systemd/user/wacom.service    
[Service]
Type=forking
Restart=no
ExecStart=/path/to/wacom-pad-button-setup

[Install]
WantedBy=default.target
WantedBy=sys-devices-pci0000:00-0000:00:1d.0-usb2-2\x2d1-2\x2d1.1.device
WantedBy=sys-devices-pci0000:00-0000:00:1d.0-usb2-2\x2d1-2\x2d1.2.device
WantedBy=sys-devices-pci0000:00-0000:00:1d.0-usb2-2\x2d1-2\x2d1.3.device

USBポートごとに1つのデバイスユニットがあります。

次に、ユニットを有効にして、systemctl --user enable wacom.serviceおよびsystemctl --user daemon-reloadでリロードします。

Xsetwacomがデバイスを見つけ、$DISPLAY$XAUTHORITYを設定するために、スクリプトはまだ少しスリープする必要があります。 Type=oneshotはプラグインすると正常に動作しますが、コンピューターの起動時にデバイスが既にプラグインされている場合は実行されません。そのため、システムではなくユーザーサービスを使用する必要があり、ユニットにもWantedBy=default.targetがあります。ワンショットの問題は、startxをブロックしていたことです。 Type=forkingおよびRestart=noは、スクリプトのフォークされたプロセスが終了するのを待たないようにsystemdに指示します。これにより、スクリプトはバックグラウンドでスリープしてXorgの開始を待つことができます。

$ cat bin/wacom-pad-button-setup
#!/bin/rc
{
    sleep 2

    if (~ $DISPLAY ()) {
        DISPLAY=:0
        XAUTHORITY=/home/spelufo/.Xauthority
    }

    xsetwacom set 'Wacom Intuos PT S Pad pad' button 9 'button +3 -3'
    xsetwacom set 'Wacom Intuos PT S Pad pad' button 8 'button +4 -4'
    xsetwacom set 'Wacom Intuos PT S Pad pad' button 3 'button +1 -1'
    xsetwacom set 'Wacom Intuos PT S Pad pad' button 1 'button +2 -2'
} &
1
spelufo

Derobertによる回避策は、すべての状況に適しているわけではありません(xorg.confを使用できない場合)。

エイドリアンによって提案されたラップとsleepソリューションはどういうわけか私にはうまくいきません(ubuntu16.04)。

これをxsetwacomスクリプトの先頭に追加する場合:

exec > /tmp/debug-my-script.txt 2>&1
xinput --list

出力から、xinputがwacomを認識する前に、xsetwacomスクリプトが何らかの形で実行されていることがわかります。どれだけ長く眠っても。

ここで提案するのは、小さなプログラムを使用した別の解決策/回避策です at これはspelufoによる解決策(私は試していません)よりも簡単ですが、atプログラムをインストールするだけで済みます。 (Sudo apt install at debianユーザーの場合)。

次に、ラッパースクリプト(エイドリアンの回答)を次のように変更します。

#!/usr/bin/env bash
at now -f /usr/local/bin/setupwacom-post-X11.sh

atは通常、コマンドを1回スケジュールするために使用されます。たとえば、at now +1 hours -f yourscript.shで1時間先にスケジュールできます。ただし、追加できるのは分/時間/日/週のみなので、追加せずにnowを使用しましたが、xsetwacomスクリプト内のスリープに依存しています。

1
Sebastian