2021年2月3日 星期三

拿電視遙控器操作電腦

HP Media Center infrared transceiver 在電腦上播影片接 hdmi 線投射到電視上的時候, 想要暫停、 倒帶、 快轉必須走到電腦前面, 很麻煩。 沒關係, VlcFreemote 這個 app 可以把手機變成遙控器。 本文要介紹的則是另一個方法: 買一個 usb 紅外線接收器接在電腦上, 直接用電視遙控器來操作電腦。 採用這個方案, 它的應用就不僅限於搭配 vlc 播影片。 例如有一些工作用電腦做很簡單很方便 (像是查天氣/公車/股票資訊), 但是老人家可能因為對電腦鍵盤有畏懼感或因為手機字太小而無法操作。 一旦把遙控器變成一個額外的無線小鍵盤, 諸如此類的事都可以用很簡單的程式甚至單純的網頁來實作, 讓使用者以為是在用電視遙控器操作電視。 很適合裝在樹莓派上, 把它當作家庭影音媒體中心兼資訊查詢站。

兩三年前就想玩電視遙控器+ 「usb 紅外線接收器」。 根據 這一篇 的建議, 買了 HP Media Center infrared transceiver (也可以發送的意思嗎?)、 確定 linux 有抓到硬體且某些情況下接得到訊號, 後來卡關就沒繼續了。 這是我唯一買到且實驗成功的硬體; 但現在可能也不太好買了。 (不要誤買成延伸器或轉發器) 接上 usb 前後, 用 lsusb 查看, 會發現多出一列類似這樣: Bus 002 Device 007: ID 1934:5168 Feature Integration Technology Inc. (Fintek) F71610A or F71612A Consumer Infrared Receiver/Transceiver

最近幾年 linux 上的紅外線驅動方式有改變。 如果查到推薦 lirc 的文章, 那是舊的, 可以直接略過不看。 不要安裝 lirc 套件。 較新的 kernel 直接支援紅外線週邊; 需要安裝的搭配套件是 ir-keytable。 但是文件超級破碎難找又難理解。 我這篇不只要教讀者如何設定, 更重要的是解釋為什麼, 以及到哪裡找更詳盡的資訊。

請先查看: ls -l /dev/input/event* 其中某一個就是遙控器的輸入。 因此需要先 sudo usermod -a -G input $USER 把自己加入 "input" 這個 group、 登出、 再重新登入, 這樣以下的 ir-keytable 指令就可以用 $USER 的身份執行, 而不需要變身成 root。 先查詢系統狀態: ir-keytable 不要任何參數, 看到類似這樣:

Found /sys/class/rc/rc0/ with:
	Name: Media Center Ed. eHome Infrared Remote Transceiver (1934:5168)
	Driver: mceusb
	Default keymap: rc-rc6-mce
	Input device: /dev/input/event13
	LIRC device: /dev/lirc0
	Attached BPF protocols: 此項操作並不被支援
	Supported kernel protocols: lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp imon rc-mm
	Enabled kernel protocols: lirc rc-6
	bus: 3, vendor/product: 1934:5168, version: 0x0001
	Repeat delay = 500 ms, repeat period = 125 ms

Name 那一列的資訊跟 lsusb 看到的一樣。 Driver 那一列說明 kernel 自動載入哪個模組 (驅動程式) 來管理這個裝置, 可以用 lsmod | grep mceusb 驗證。 Input device 那一列提及的裝置名稱, 等一下的 evtest 指令會用到。 常見的紅外線通訊協定有十幾種 protocols, 諸如 nec、 jvc、 rc-5、 rc-6 等等 (想像成十幾種紅外線方言) 上面的結果顯示目前啟用的是 lirc 跟 rc-6 這兩個 protocols。

比較囉嗦的是 keymap。 每一支電視遙控器各自會發出不同的獨特鍵盤掃描碼 (scancode), 像是 0x118、 0x115、 0x112 等等, 有些甚至會送出八位的十六進位數字作為掃描碼; 但上層的應用程式則希望不論是哪一支遙控器發出來的, 最終都看到 「KEY_UP」、 「KEY_OK」、 「KEY_VOLUMEUP」 等等一致的 key, 所以需要為每一支設定一個 keymap, 把各異的 scancode 對應到固定的 key。 安裝 ir-keytable 套件時, 會同時把很多遙控器的 keymap 定義放在 /lib/udev/rc_keymaps/*.toml 。 根據 man rc_keymap , 在 /usr/include/linux/input-event-codes.h 這裡有完整的 key 名稱列表。 那麼開機時 kernel 會採用哪一個 keymap 呢? 用 Default keymap 那一列提及的名稱進入主設定檔 /etc/rc_maps.cfg 去查: grep rc-rc6-mce /etc/rc_maps.cfg 即可發現其中這一句: * rc-rc6-mce rc6_mce.toml 表示開機時 kernel 會去找 rc6_mce.toml 這個 keymap 設定檔。 不過它優先在 /etc/rc_keymaps/ 底下找, 如果找不到才在 /lib/udev/rc_keymaps/ 底下找。

我有一支很舊的奇美電視遙控器, 不知道採用哪一種 protocol。 先執行 ir-keytable -t -p all 進入測試模式。 其中的 -p all 表示要試遍所有已知的方言去認你的遙控器。 然後開始對著接收器按遙控器, 每按一個鍵就會看到許多訊息。 得知我的遙控器採用的 protocol 是 nec。 找一個相同 protocol 的 .toml 檔, 把它 (的前幾列) 複製到 /etc/rc_keymaps/ 底下任取一個檔名, 例如我用: head /lib/udev/rc_keymaps/avermedia_rm_ks.toml > /etc/rc_keymaps/chimei.toml 再把 ir-keytable -t 所看見的 scancode 填進這個新的 .toml 檔。 最後編輯 /etc/rc_maps.cfg 把 * rc-rc6-mce rc6_mce.toml 那一列改成 * rc-rc6-mce chimei.toml , 這樣下次開機就會自動採用 /etc/rc_keymaps/chimei.toml 裡面的定義。

其實每次修改過 chimei.toml 之後, 並不需要重新開機。 先用 ir-keytable -r 查詢 kernel 目前所使用的 keymap 定義。 再用 ir-keytable -c 清除掉目前的 keymap 定義。 最後用 ir-keytable -w /etc/rc_keymaps/chimei.toml 指示 kernel 改用新的 keymap。 這個 -w 做完之後, 對 kernel 的影響立即生效 -- 如果有另一個分頁正在用 ir-keytable -t 測試, 甚至不需要按 ^C 中斷再重新啟動, 就可以發現 ir-keytable 對下一次按鍵不只印出 scancode, 也會印出 key_up 與 key_down 事件及 key 的名稱。

如果有安裝 evtest 套件, 也可以用 root 身份這樣測試: evtest /dev/input/event13 (裝置名稱是先前用 ir-keytable 查詢得來的。) 同樣地, ir-keytable -c -w /etc/rc_keymaps/chimei.toml 的效果, 在 evtest 裡面立即可見, 並不需要重啟任何服務之類的。

但是非 root 使用者所看到的訊號, 則要用 x11-utils 套件裡面的 xev 指令測試。 用普通人的身份執行 xev 或 xev -event keyboard 之後, 會出現一個白色視窗, 而原先下指令的終端機分頁只有當白色視窗取得鍵盤 focus 時才會印出遙控器的按鍵事件。 每次用 ir-keytable -c -w ... 更改 keymap 之後, 有可能需要先登出 xorg 再登入, xev 才會看得見新的設定。

比較大的問題是: 有些遙控器上常見的鍵 (例如 KEY_OK 與 KEY_VOLUMEDOWN 等等) 明明 ir-keytable -t 看得見, 但 xev (以及 xorg 視窗環境下的應用軟體) 卻看不見, 為什麼? 因為從 kernel 接收到訊號到 xorg 的一個低權限普通應用程式視窗, 一路上可能經過 xorg、 桌面環境、 視窗管理員等等層層過濾/轉換訊號。 而 xorg 會把遙控器視為普通鍵盤, 所以音量/頻道等等鍵會消失。 還好, 很多應用軟體本來就可以用實體鍵盤操作, 不妨就直接把遙控器的 scancode 轉成它認得的實體鍵盤按鍵。 例如想用遙控器操作 家庭多媒體影音平台中心 kodi, 就先去找 kodi 的鍵盤操作手冊。 所以某個 scancode 原本應該送出 KEY_OK 就改送 KEY_ENTER; 另一個 scancode 原本應該送出 KEY_VOLUMEDOWN 就改送 KEY_MINUS 等等。 至於實體鍵盤每個鍵的名字, 則可查詢 /usr/include/linux/input-event-codes.h (來自 linux-libc-dev 套件)。

耶! 現在可以用遙控器操作 kodi 看電腦上的 .mp4 影片了! 那麼... 下一步就是 用 lynx 或 w3m 或 pdmenu 找一些鍵盤可操作的 apps 或 web apps 再搭配 遙控器切換視窗、切換火狐分頁 來實作有趣的生活應用囉~

* * * * *

後記: 筆記一些沒放進正文或沒測試過但可能也有用的連結。 12 3 這三篇對我的起步幫了大忙。 若想了解更多, 大推 這篇資訊豐幅的 Orange Pi Zero 文章 以及 kernel 文件的 Remote Controller devices 章節 這篇 解釋 kernel 內建的紅外線識別模組與 lirc 之間的混用與衝突。 如果不嫌麻煩的話, 這份文件 說停用 kernel 的內建支援、 改回頭用 lirc 就可以讓 kodi 直接看到 KEY_OK 與 KEY_VOLUMEDOWN 等等遙控器特殊按鍵。 另一條可能的路或許是設定 udev hwdb: 12。 還有一條可能的路: 設定 xorg 的鍵盤 叫它從 evdev/evtest 讀資料。 ( mythtv 文件)。

沒有留言:

張貼留言

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。