紛失ゼロ!充電アダプタを PC 本体にテザーする DIY ハック
ノート PC 充電アダプタを、本体に繋げて留め付けたい
一昔前のノート PC の充電端子って、USB-C じゃなかったりするでしょ。僕の使ってる Asus Zenbook UX430UN-8550 の充電も 4.5 × 1.35 mm 端子というやつで、素のままだと純製の (巨大な!) 充電器を持ち歩く手間がある。この手間を解消すべく、僕は USB-C アダプタを使ってる (参考: 過去記事)。
しかしアダプタの持ち運びや管理も、これはこれで面倒な課題だ。挿しっぱなしで運用すると思わぬときに意図せずスルッと抜けちゃって紛失のリスクがあるし、一方でいちいちアダプタを着脱したり不使用時には仕舞ったりするのも億劫だ。そこで、アダプタを本体にテザーするハックを考案した。

やり方は簡単。輪の付いたダストプラグを買って、それにアダプタを結ぶだけ。これでアダプタを PC 本体にテザーできるから、別管理する必要が無くなるのだ!もちろん PC 本体にストラップ穴があるなら、そこにアダプタを結べばいい。けど穴の無い機種も多いと思う (この PC もそう)。

本体/アダプタの一体管理は、期待以上の利便性!充電時のアダプタ着脱の手間は減るし、アダプタを失くさないよう管理に神経をすり減らす必要もない。ダストプラグのハメ込みは意外と硬いので、意図せずスルッと抜ける事態も起きてない。

電池駆動時 (つまり非充電時) も邪魔になりにくいし、何より管理の手間が無いのは大きい。着脱したり持ち運んだりするのに想像以上に疲弊していたことに、楽になって初めて気づいた気がする😁

音を出すには?pactl で出力先をスピーカーに!
問題があるとすると 1 点、ダストプラグを挿すとスピーカーから音が鳴らないこと。でも大丈夫、Linux ならコマンド 1 発で修正できる。
# スピーカーに切り替え
pactl set-sink-port @DEFAULT_SINK@ analog-output-speaker
# ヘッドフォンに切り替え
pactl set-sink-port @DEFAULT_SINK@ analog-output-headphones
Code language: Bash (bash)
たぶん Fedora なら pactl は標準装備だと思う。もし GUI でやりたければ pavucontrol も使える。[Output Deives] タブの [Port] で Speakers を選ぶと、ダストプラグを挿しててもスピーカーから音を鳴らせる。

pavucontrol で出力先 (Port) を Speakers にするときどき選択肢が Speakers (unavailable) になることがある。しかし実際にはこれでも音が鳴るので、気にせずこの設定を適用すれば良い (らしい)。でもこの状態だと Firefox の音が一時的に鳴らなかったりして、対処が要るような要らないような、良く分かっていない…😅

Speakers (unavailable) の表示Calude Code 追記: ダミープラグ挿入時に音が完全に出なくなる問題の恒久対策
前回の記事では pactl set-sink-port でスピーカー出力に切り替える方法だけを紹介したが、これだけでは不十分だった。ダミープラグを一度でも抜き差しすると、Firefoxに限らずシステム全体で音が完全に出なくなるという致命的な問題が別に存在していたため、その原因と恒久対策を追記する。
症状の切り分け方(診断コマンド)
pactl list sinks # ポートが "not available" になっていないか確認
wpctl status # Sinks に "*"(デフォルト印)が付いているか確認
pw-metadata -n default # default.audio.sink キー自体が消えていないか確認
pw-play test.wav # "no target node available" エラーが出るか確認
journalctl --user | grep cubeb # Firefox側の症状 (OpenCubeb() failed to init cubeb)
Code language: Bash (bash)
根本原因
- ダミープラグは電気的な接続がなくても、ジャックの物理検出ピン(この機種ではALC294コーデックのNID
0x21)を機械的に刺激し、「本物のヘッドホンが挿さっている」と誤認識させる - 内蔵スピーカー側のピンは元々
NO_PRESENCE(検出なし)扱いなのに対し、ヘッドホン側だけUnsolicited: enabled=1(挿抜割り込み有効)になっている非対称性が原因 - ジャック検出が「オン」のまま固定されると、WirePlumberが「利用可能な出力ポートがない」と判断し、
default.audio.sinkごと消してしまう(単なる誤ルーティングではなく、システム全体の無音化)
恒久対策: コーデックのピン設定を書き換えて検出自体を無効化
対象ピンの特定(機種ごとに 0x21 は変わりうるので、Jack かつ Unsolicited: enabled=1 のノードを探す):
cat /proc/asound/card0/codec#0 | grep -B5 -A8 "Unsolicited: tag=.*enabled=1"
Code language: Bash (bash)
Pin Default 書き換え(Misc に NO_PRESENCE ビットを立てる。元値・新値は機種依存):
# 元: 0x03211020 → 新: 0x03211120 (Misc bit0 = NO_PRESENCE)
sudo hda-verb /dev/snd/hwC0D0 0x21 0x71c 0x20
sudo hda-verb /dev/snd/hwC0D0 0x21 0x71d 0x11
sudo hda-verb /dev/snd/hwC0D0 0x21 0x71e 0x21
sudo hda-verb /dev/snd/hwC0D0 0x21 0x71f 0x03
sudo hda-verb /dev/snd/hwC0D0 0x21 SET_UNSOLICITED_ENABLE 0x0
Code language: Bash (bash)
hda-verb は alsa-tools パッケージに含まれる。
変更を即座に反映させる(ここが一番ハマったポイント)
echo 1 > /sys/class/sound/hwC0D0/reconfigは、PipeWireがPCMを掴んでいるとDevice or resource busyで失敗する- PipeWire/WirePlumberを完全停止(
.serviceと.socket両方)しても、なぜかreconfig自体が拒否され続けるケースがある(カーネル側の実装都合と思われる) - 確実な代替策: PCIデバイスのunbind/bindでドライバを再アタッチする
echo "0000:00:1f.3" | sudo tee /sys/bus/pci/drivers/snd_hda_intel/unbind
sleep 1
echo "0000:00:1f.3" | sudo tee /sys/bus/pci/drivers/snd_hda_intel/bind
Code language: Bash (bash)
成功の確認方法: amixer -c0 controls | grep Jack で対象ピンが「〜Jack」から「〜Phantom Jack」に変わっていればOK。
再起動後も自動適用させる(udevルール)
生レジスタの書き換えは、電源断を伴わないunbind/bindや再起動程度では保持されるが、恒久化のため起動毎に自動再適用するudevルールを設置しておく。
/usr/local/bin/fix-headphone-jack-detect.sh:
#!/bin/bash
DEV=/dev/snd/hwC0D0
NID=0x21
[ -e "$DEV" ] || exit 0
hda-verb "$DEV" $NID 0x71c 0x20
hda-verb "$DEV" $NID 0x71d 0x11
hda-verb "$DEV" $NID 0x71e 0x21
hda-verb "$DEV" $NID 0x71f 0x03
hda-verb "$DEV" $NID SET_UNSOLICITED_ENABLE 0x0
echo 1 > /sys/class/sound/hwC0D0/reconfig
Code language: Bash (bash)
sudo chmod 755 /usr/local/bin/fix-headphone-jack-detect.sh
Code language: Bash (bash)
/etc/udev/rules.d/99-hda-jack-override.rules:
ACTION=="add", SUBSYSTEM=="sound", KERNEL=="hwC0D0", RUN+="/usr/local/bin/fix-headphone-jack-detect.sh"
Code language: Bash (bash)
sudo udevadm control --reload
Code language: Bash (bash)
常駐デーモンは不要。サウンドカードがudevに認識された瞬間に一度だけ実行される、イベント駆動のワンショット処理。
トレードオフ(重要な注意書き)
- この恒久対策を適用すると、本物のイヤホンを挿しても自動切り替えされなくなる
- 手動で切り替えたい場合は引き続き以下が使える(前回記事の
audio-headphone相当):
pactl set-sink-port @DEFAULT_SINK@ analog-output-headphones
Code language: Bash (bash)
- NIDやPin Default値は機種・コーデック依存。他機種でそのまま数値をコピペしないこと
環境情報
- コーデック: Realtek ALC294(
aplay -lで確認) - 使用ツール:
amixer,pactl,wpctl,pw-metadata,pw-play,hda-verb(alsa-tools)
