USB ウェブカメラをソフト的に無効化する

OS は Debian Linux、デスクトップ環境は XFCE で、ウェブカメラを使用している。必要なときだけ USB のプラグを挿しそれ以外のときはプラグを抜くようにしていたのだが、頻繁に抜き挿しするうちに接触不良ぎみになってしまった。

挿しっぱなしにする代わりに物理的なレンズキャップをとも考えたがそれも面倒くさい。USB ポートの論理接続を切り替えることにした。物理的に取り外しのできないノート PC などにも応用できるだろう。

modprobe -r uvcvideo という方法もあるようだが、それではすべての USB カメラデバイスも同時に消えてしまう。特定のカメラだけを無効化したい。

事前情報

lsusb -t で事前にウェブカメラの番号を調べておく。

/:  Bus 003.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/4p, 480M
    |__ Port 001: Dev 002, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 002: Dev 004, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 002: Dev 004, If 1, Class=Video, Driver=uvcvideo, 480M
        |__ Port 002: Dev 004, If 2, Class=Audio, Driver=snd-usb-audio, 480M
        |__ Port 002: Dev 004, If 3, Class=Audio, Driver=snd-usb-audio, 480M

のような情報から、

  • Bus 003
  • Port 1 (外付または内部の USB ハブ)
  • Port 2 (カメラ本体)

がわかり、Linuxの sysfs 上の表記でこれは 3-1.2 という ID になる。

それがわかれば、/sys/bus/usb/devices/3-1.2/authorized に 0 を書き込めば無効化、1 を書き込めば有効化できる。

bash のコマンドラインで使うなら、エイリアス

alias cam-off="echo '0' | sudo tee /sys/bus/usb/devices/3-1.2/authorized"
alias cam-on="echo '1' | sudo tee /sys/bus/usb/devices/3-1.2/authorized"

にしておけば楽。

0 を書き込んだ後に lsusb -t で見てみると、Port 2 の項目が消えていることが確認できる。

XFCE パネルへの組み込み

さらに楽にするために、ふだん使用しているデスクトップ環境の XFCE のパネルに切り替えスイッチを設置したい。

制御スクリプトの作成

実行するたびに有効化/無効化を切り替えるメインスクリプトを /usr/local/bin/toggle_camera.sh あたりに作成する。

#!/bin/bash

# 設定: 事前に特定したカメラのパス
DEV_PATH="/sys/bus/usb/devices/3-1.2"

# 現在の状態を取得 (1=ON, 0=OFF)
CURRENT_STATUS=$(cat "$DEV_PATH/authorized")

if [ "$CURRENT_STATUS" -eq "1" ]; then
    # OFFにする
    echo 0 | sudo tee "$DEV_PATH/authorized" > /dev/null
    echo "Camera OFF"
else
    # ONにする
    echo 1 | sudo tee "$DEV_PATH/authorized" > /dev/null
    echo "Camera ON"
fi

実行権限を与えておく。chmod +x /usr/local/bin/toggle_camera.sh

sudo パスワードの回避

パネルからクリックした際に sudo のパスワード入力を求められないようにしておく。

/etc/sudoers の末尾に以下を追記する (username は実際のユーザー名)。

username   ALL=(ALL) NOPASSWD: /usr/local/bin/toggle_camera.sh

パネル表示用スクリプトの作成

XFCE のパネルプラグイン(Generic Monitor)に状態とアイコンを渡すためのスクリプトを ~/bin/cam-status.sh あたりに作成する。

#!/bin/bash

DEV_PATH="/sys/bus/usb/devices/3-1.2"
TOGGLE_SCRIPT="sudo /usr/local/bin/toggle_camera.sh"

# アイコンの設定
if [ -f "$DEV_PATH/authorized" ] && [ "$(cat "$DEV_PATH/authorized")" -eq "1" ]; then
    # ON
    #echo "<img>/usr/share/icons/Adwaita/symbolic/devices/camera-web-symbolic.svg</img>"
    echo "<icon>camera-web</icon>"
    echo "<tool>ウェブカメラは有効(クリックで無効化)</tool>"
else
    # OFF
    #echo "<img>/usr/share/icons/Adwaita/symbolic/status/camera-disabled-symbolic.svg</img>"
    echo "<icon>camera-disabled-symbolic</icon>"
    echo "<tool>ウェブカメラは無効(クリックで有効化)</tool>"
fi

# クリック時の動作
#echo "<click>$TOGGLE_SCRIPT</click>"
echo "<iconclick>$TOGGLE_SCRIPT</iconclick>"

<img> の場合はフルパスで指定、<icon> なら camera-web-symbolic のように名前で指定する。なお <img> のときは <click> にし、<icon> のときは <iconclick> にする。

実行権限を与えておく。 sudo chmod +x ~/bin/cam-status.sh

XFCE パネルへの組み込み

  1. GenMon のインストール: Debian なら sudo apt install xfce4-genmon-plugin
  2. パネルに追加: パネルを右クリック → 新しいアイテムの追加 → ジェネリックモニター
  3. 設定: 追加されたアイコンを右クリック → プロパティ
    • コマンド: cam-status.sh (またはフルパス)
    • ラベル: (チェックを外す)
    • 間隔(秒): 10 (適当に)

以上で、アイコンをクリックするだけで即座に切り替えられる。

起動時の状態

起動時に必ずウェブカメラを無効化の状態にするには、システム起動時に一度だけ authorized を 0 に書き換える設定を追加する。cron@reboot 指定を使う。

root の crontab に

@reboot echo 0 > /sys/bus/usb/devices/3-1.2/authorized

を追加する。

注意

もしポートの場所が変わってしまう可能性がある (USB の挿し口を変えたなど) 場合は、ベンダー ID で自動探索などがいいのかもしれないが、今回は決め打ちとした。

それが変わったときは、2つのスクリプトと root の crontab の計3か所の中のパスを書き換えるのを忘れずに。

ウェブ会議でホワイトボード/PDF に手書き/Debian で使うタブレット

しばらく前(2023年に入ったころ)から、いわゆるウェブ会議を使って、リモートで家庭教師のようなこと(本当は違うのだが少しフェイクを入れるのでここではそういうことにしておく)をやっている。

こちらの環境は Debian で、そもそもプロプライエタリな道具はほぼ存在しないので、いろいろと探し回ることになった。

必要な道具は、まずウェブ会議の仕組みにホワイトボード機能となる。はじめは Jitsi を使っていたのだが、そのホワイトボード機能にバグのようなもの(数十分ほど書いたり消したりしているとハングアップしたようにそれ以上の書いたり消したりができなくなる)が出現して、Whereby を使うようになった。この切り替えはもう3か月ほど前なので、現在(2023年9月末)ではもう解決しているかもしれない。

Whereby は2人(1対1)で使う分には時間無制限なので、ここでの目的では困らない。Whereby ではホワイトボードとして外部サービスの Miro の画面を共有するようになっており、この使い方では Miro にアカウントを作る必要もない。

また、ホワイトボードに PDF を背景画像のように表示させてその上に書き込むように表示させる(家庭教師的に言えば、練習問題のプリントを表示させておいて解説を書き込む)ような使い方は、Jitsi のホワイトボードではできず、バグの有無に関わらず Whereby (Miro) のほうが優れている。

やや話はずれるが、ウェブ会議とは無関係に、既存のPDFに手書きで書き込むようなアプリケーションを探してみたら、Xournal++ というものが見つかった。これはこれでたいへん優れた道具だ。

さて、そのように手書きで書き込む際、マウス(と言っても自分はトラックボールだが)ではなかなか上手く書くことができないので、ペンタブレットを用意することにした。価格が手頃で Linux での実績がありそうな XPPen の Deco Fun XS を購入。お絵描きには小さすぎるかもしれないが、ここでの目的にはちょうどいい。

表面は思いの外ツルツルで、ペンが滑りすぎると感じるので、紙(たとえば便箋)をタブレットの作業エリアに貼り付けた。これで書き味がまさに紙に書いている感じになり、すこぶるよくなった。

XPPen には Linux 用のドライバが用意されている。これがなくても機器を接続するだけで十分使えるのだが、これによってさらに便利に使うことができる。たとえば、タブレットでの作業エリアを画面上の一部領域に設定できたり、ペンのボタンに機能を割り当てたりできるようになる。

ここでは「180度回転」と設定し、タブレットそのものを上下逆さまに置くことにした。このタブレットには作業エリア以外に幅 2cm ほどの部分があり、それを手前に持ってきてちょうどパームレスト(文字を書くので実際には小指の脇か)のように使うことで、より安定して字を書けるようになった。

【以下は、2023年9月末現在の自分の環境(Debian testing)での問題である。】

ところが、ここでは Debian の testing バージョン(安定バージョンではなく、ソフトウェア(パッケージ)が少しずつ新しいものに置き換わっていく)を使用しているため、ある時の Debian の更新以降この XP-Pen 提供のドライバ(この時点で XPPen-pentablet-3.2.3.230215-1.x86_64.deb)が動かなくなってしまった。提供されているドライバは当然にも 対応は Debian 安定版としか謳っていないので文句をいう筋合いではない。

XP-Pen 提供のドライバは実際には /usr/lib/pentablet/pentablet.sh というシェルスクリプト

#!/bin/sh
appname=`basename $0 | sed s,\.sh$,,`
dirname=`dirname $0`
tmp="${dirname#?}"
if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
LD_LIBRARY_PATH=$dirname/lib
export LD_LIBRARY_PATH
$dirname/$appname "$@"

を通じて、同じディレクトリの lib/ 以下のライブラリを使いつつ、同じディレクトリの pentablet というバイナリが起動されている。OSバージョンで困らないようにわざわざ同梱されている lib/ 以下のライブラリのどれかが逆に悪さして、このドライバが動かなくなっていた。このシェルスクリプトを飛ばして(LD_LIBRARY_PATHを設定しないようにして)直接 /usr/lib/pentablet/pentablet を起動すると、問題なく使えるようになった。

$ ldd /usr/lib/pentablet/pentablet

	linux-vdso.so.1 (0x00007fff87dc2000)
	libusb-1.0.so.0 => /lib/x86_64-linux-gnu/libusb-1.0.so.0 (0x00007f4e0b29d000)
	libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f4e0b15b000)
	libXtst.so.6 => /lib/x86_64-linux-gnu/libXtst.so.6 (0x00007f4e0b153000)
	libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f4e0b13f000)
	libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f4e0b132000)
	libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f4e0b12b000)
	libQt5X11Extras.so.5 => /lib/x86_64-linux-gnu/libQt5X11Extras.so.5 (0x00007f4e0b124000)
	libQt5Widgets.so.5 => /lib/x86_64-linux-gnu/libQt5Widgets.so.5 (0x00007f4e0aa00000)
	libQt5Gui.so.5 => /lib/x86_64-linux-gnu/libQt5Gui.so.5 (0x00007f4e0a200000)
	libQt5Xml.so.5 => /lib/x86_64-linux-gnu/libQt5Xml.so.5 (0x00007f4e0b0e0000)
	libQt5Network.so.5 => /lib/x86_64-linux-gnu/libQt5Network.so.5 (0x00007f4e0a055000)
	libQt5Core.so.5 => /lib/x86_64-linux-gnu/libQt5Core.so.5 (0x00007f4e09a00000)
	libGL.so.1 => /lib/x86_64-linux-gnu/libGL.so.1 (0x00007f4e0a979000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4e0b0d9000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4e09600000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4e09f76000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4e0b0b5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4e0941e000)
	libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f4e0a947000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f4e0b2d2000)
	libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f4e0a91d000)
	libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f4e0a908000)
	libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f4e0a8fb000)
	libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f4e099ca000)
	libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4e099ab000)
	libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f4e09884000)
	libmd4c.so.0 => /lib/x86_64-linux-gnu/libmd4c.so.0 (0x00007f4e0a8e9000)
	libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f4e093cb000)
	libdouble-conversion.so.3 => /lib/x86_64-linux-gnu/libdouble-conversion.so.3 (0x00007f4e0986f000)
	libicui18n.so.72 => /lib/x86_64-linux-gnu/libicui18n.so.72 (0x00007f4e09000000)
	libicuuc.so.72 => /lib/x86_64-linux-gnu/libicuuc.so.72 (0x00007f4e08e02000)
	libpcre2-16.so.0 => /lib/x86_64-linux-gnu/libpcre2-16.so.0 (0x00007f4e0933d000)
	libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007f4e08d41000)
	libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f4e08bfb000)
	libGLdispatch.so.0 => /lib/x86_64-linux-gnu/libGLdispatch.so.0 (0x00007f4e08b42000)
	libGLX.so.0 => /lib/x86_64-linux-gnu/libGLX.so.0 (0x00007f4e08b0e000)
	libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007f4e09f6a000)
	libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f4e0b0a8000)
	libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f4e08800000)
	libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f4e08a42000)
	libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f4e08a16000)
	libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f4e08724000)
	libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f4e086f7000)
	libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f4e09869000)
	libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f4e0985b000)
	libicudata.so.72 => /lib/x86_64-linux-gnu/libicudata.so.72 (0x00007f4e06800000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f4e0865c000)
	libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f4e08647000)
	libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f4e0932a000)
	libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007f4e08a09000)
	libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f4e08640000)
	libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f4e0862f000)
	libmd.so.0 => /lib/x86_64-linux-gnu/libmd.so.0 (0x00007f4e08620000)
	libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007f4e085fd000)

Expert Mouse を買った(14年ぶり2回め)

この前の記事「HHKBを買った」から9か月も何も書いていなかったのか。しかもその時とほとんど同じような内容とは……。

Expert Mouse トラックボール(EM7) を長いこと使っています。正確に記録を残していませんでしたが、今では高校生になっている、友人の子がその当時はよちよち歩きで、膝に乗せてこのボールを触らせてあやしたことを覚えているので、購入したのは14,5年前のことです。

今でも問題なく使えているのですが、この前の HHKB と同じく、ふと壊れる前に新しくしてみようという気になりました。これまた HHKB と同じく、すっかり体に馴染んでいるので別のものに変えようという気にはなりません。現在もデザインもまったく変更なく同じものが販売されています。ありがたいことです。

新品と比べてみてみれば、古いものは何らか劣化していることに気づくかなと思ったのですが、案外そのままでした。スイッチの感触もほとんど変わりありません。見た目は確かに指の触れるところの塗装が剥げているのと、スクロールリングのギザギザがすっかり摩耗してツルツルになっているくらいでした。

ときどき掃除してきれいに使っているつもりでしたが、支持球が汚れているのか操作球が摩耗しているのか、新品のほうがはるかに滑らかにボールが動きます。この製品のスクロールリングの出来はあまり評判がよくなくて、前のは一度分解してどこか磨いたりしたような記憶がありますが、今回の新品は最初からスムーズで心地よく回ります。

自分の使い方では、本体は20年はもちそうです。HHKB 同様、この先これを買い換えることはもうないかもしれません。

EM7 とペットボトルカバーによるパーム(リスト)レスト
付属のパームレストはとうの昔にひび割れてだめになったので、試行錯誤の末、今は100円ショップで買ってきたペットボトルカバー350mL用にタオルを詰め込んで使っています。詰物をおはじきか何かと工夫しようと考えていますがまだ実現できていません。かなり高めにして、パームと言うよりは手首の上のほうを置いています。

ボタン割り当て

EM7 と右手ボタンの割り当ては自由に設定できるため、各自が自分の好みにすればいいのですが、参考までに私の例を晒しておきます。

右利きで、キーボードの右側に置いて右手で使用しています。

  • 左下ボタンを左クリック相当(親指)
  • 右下ボタンを右クリック相当(小指)
  • 右上ボタンを中クリック相当(薬指)
  • スクロールリングは時計で言うと3時の位置を薬指で、時計回りで下スクロール、半時計回りで上スクロール

ボールはだいたい人差し指と中指の2本の指先で操作しています。

HHKBを買った (22年ぶり2回め)

初代 HHKB の裏面ラベル

一つ前の型 HHKB Professional2 Type-S (PD-KB400WS) が Amazon のタイムセールで 20% OFF になっていたので、思わず購入してしまいました。現時点の最新型 Hybrid ではなく、USB 有線のみのものです。

これまで使っていたのは初代の Happy Hacking Keyboard (PD-KB01) で、裏を見ると1997年7月のものでした。

アメリカ西部のカウボーイたちは、馬が死ぬと馬はそこに残していくが、どんなに砂漠を歩こうとも、鞍は自分で担いで往く。馬は消耗品であり、鞍は自分の体に馴染んだインタフェースだからだ。

いまやパソコンは消耗品であり、キーボードは大切な、生涯使えるインタフェースであることを忘れてはいけない。

の言葉のごとく、本体は何度も替わりましたがこのキーボードを22年も使い続けてきました。

まだ壊れてしまった訳ではありません。左シフトの反応が少しおかしい (キーをいったん外して紙片を入れて押し込みの深さを調整すれば大丈夫) のと、数年前に掃除した際にスペースバーの裏のバネを1本紛失してしまったのが不都合と言えるくらいです。

1990年代、私は Sun のワークステーション (SPARCclassic) を独占してデスクトップで使えるという環境にあったのですが、純正のキーボードは確か Type5 で、かなり大きくて邪魔なものでした。「CTC 省スペースキーボード」を入手して使ってみたのですが、これはノート PC のキーボードを持ってきたようなもので、キーストロークが非常に浅く、打鍵感がどうにも不快でしかたありませんでした。

そこに Happy Hacking Keyboard が登場してきたので購入したのです。ケーブルは Sun 用と PS/2 用 があって、はじめはもちろん Sun SPARCclassic で使っていたのですが、そのうち PC がどんどん高性能・低価格になり、Debian をインストールした PC がメインになり、PS/2 で接続して使うようになっていきました (SPARCclassic は画面なしキーボードなしで、リモートログインして使うサーバーとしてしばらく存在していましたが、6,7 年で退役しました)。

新旧 HHKB

それから本当に何台も本体は入れ替わっても、キーボードはずっと生き残り続けました。しかし接続口が Sun または PS/2 では、そろそろ「馬」に合わなくなってきたようです。

新旧の二つを並べてみると、この色の違い! 新品どうしならおそらくほぼ同じ色のはずです。煙草は吸わないのですがここまで黄ばんでいたとは。毎日目にしていると案外気がつかないまま、ここまで変色していました。

新旧 HHKB を横から見る

さっそく新しいのを使ってみていますが、やはりちょっと違和感があります。写真にうまく撮れませんでしたが、本体の厚さ(高さ)がほんの数 mm ですが高くなり、それに本体断面のカーブがゆるくなっています。それから、各キーの縁が微妙に指に痛い。前のは使い込みすぎて縁が丸くなっていたのでしょうか。もちろんこれらは慣れの問題で、すぐに気にならなくなるでしょう。

今回購入したものがこの後また20年ほどもつとしたら、次のキーボードを買うことはもうないかもしれません。