Re: [問題] 2.4G 無線滑鼠鍵盤憑甚麼關我筆電?
上一篇我所提的問題, 有了部份解答, 回文整理一下
我講的瑣碎一點, 大家比較容易發現我的盲點
以後有碰到類似問題的人也可以省下一點時間
搞不好, 最常跑來回顧細節的, 就是我自己
因為我們會游走在 "kernel 邊緣" (我現在是 5.10.28)
所以我們所討論的這些, 基本上 *應該要* 適用所有人
先大致複習一下有點複雜的問題
我有個無線滑鼠直鍵盤, 稱為 空中飛鼠
它身上長了一個電源鍵, 但是按下去會同時
1. 透過 IR LED 關掉電視 2. 透過 USB 關掉筆電
但是我不要它關我筆電...
前情提要: (抄過來)
> 1. 它憑啥關我筆電?甚麼管道?我自己都還要 sudo, 它誰?
> 2. 如何告訴我的系統,不准接受 hid 來的 shutdown 命令
===============================================
我們從第二個問題開始, 再回到第一個問題
===============================================
實務上, 會有不少人碰到類似的問題, 例如
USB 鍵盤右上角長了一顆電源鍵, 因為很接近常用鍵
動不動就會無意間按到, 導致無預警關機, 例如:
https://i.stack.imgur.com/9EgBZ.jpg
也有人用的 USB HID 長的像這樣
https://www.orbsmart.de/wp-content/uploads/2018/09/orbsmart-WA-1_1-1.jpg
這比較像我這支所謂的 "空中飛鼠", 大概因為它有陀螺儀,
可以像玩 Wii 那樣在空中揮舞, 就帶動螢幕上的鼠標
https://i.imgur.com/7mJwOoi.jpg
另外, 要是有一天, 你突然發現機器是關機狀態,
不要排除是你家的貓, 這時也會想要 disable 那個鍵
或是, 有時會需要把 sleep/suspend/hibernate 鍵停用
https://i.stack.imgur.com/524Oj.jpg
最簡單的方法就是修改 /etc/systemd/logind.conf
把 HandlePowerKey=poweroff 改為 =ignore
或是把 HandleLidSwitch 改為 =ignore
(...)
(至於 /etc/acpi/.... 我到現在還是一頭霧水,
這中間大概也夾雜了一些過渡性的 kernel 問題
還有我的筆電硬體特別的狀況... 所以不想再去想了)
這是 Bencrie 一開始就想到的, 但是他也沒忘記有個前提
就是 *如果你用 systemd 的話*, 換句話說,
並不是所有人, 所有系統, 都可以從這邊著手
而且改 logind.conf 的話, 只能讓所有的電源鍵都失效.
因為它在很上層, 應該無法分辨 interrupt 是來自哪個電源鍵.
我的情形是, 最好只停用 "空中飛鼠" 的電源鍵 (不含 IR LED),
保留筆電上面電源鍵的功能.
我所能找到的是:
方法一, Vojtech Pavlik 寫的 evtest(1) 是個好朋友.
**************************************************
(不是 xev(1), xinput(1), showkey(1)... 等, 選對工具是關鍵)
$ sudo apt-get install evtest
$ sudo evtest --grab # 需要 root, 要記得 --grab
/dev/input/event0: AT Translated Set 2 keyboard
(...)
/dev/input/event12: Power Button <== 這兩個是筆電的電源鍵
/dev/input/event13: Power Button <== 但不知為何有兩個一樣的
(...)
/dev/input/event18: FREEWAY TECHNOLOGY RFIC-MOUSE Keyboard
/dev/input/event19: FREEWAY TECHNOLOGY RFIC-MOUSE Consumer Control
/dev/input/event20: FREEWAY TECHNOLOGY RFIC-MOUSE System Control
/dev/input/event21: FREEWAY TECHNOLOGY RFIC-MOUSE
/dev/input/event22: FREEWAY TECHNOLOGY RFIC-MOUSE
(...)
Select the device event number [0-27]:
先確定想要停用的是哪一行的, 我要的是 "event20 ... System Control"
所以就打 "20", 然後那個電原鍵就已經沒用了... (直到 Ctrl-C)
下一個畫面如下:
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x25a7 product 0x2402 version 0x101
Input device name: "FREEWAY TECHNOLOGY RFIC-MOUSE System Control"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 116 (KEY_POWER) <==== 這個才是標的
Event code 139 (KEY_MENU) <---+
Event code 142 (KEY_SLEEP) <---+ 這三個我不懂, 沒反應...
Event code 143 (KEY_WAKEUP) <---+
Event type 4 (EV_MSC)
Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit) <-- 敲 Ctrl-C 結束
試按一下紅色 [電源鍵]
Event: time 1617615928.788579, type 4 (EV_MSC), code 4 (MSC_SCAN), value 10081
Event: time 1617615928.788579, type 1 (EV_KEY), code 116 (KEY_POWER), value 1
Event: time 1617615928.788579, -------------- SYN_REPORT ------------
Event: time 1617615928.900571, type 4 (EV_MSC), code 4 (MSC_SCAN), value 10081
Event: time 1617615928.900571, type 1 (EV_KEY), code 116 (KEY_POWER), value 0
Event: time 1617615928.900571, -------------- SYN_REPORT ------------
^C $
按 Ctrl-C 出來之後就不要再按電源鍵了, 會關機的.
那~~~ 我是怎麼確定是 event20 的呢?是一個一個試出來的!
用 sudo evtest --grab 測試其實很方便, 因為 --grab 就是叫
evtest 把接到的 input event "據為己有", 或是換句話說,
讓這個 interrupt "到此為止", 不再傳播下去, 或"上去"
所以其它的 handlers 都不會知到發生過這個按鍵的動作.
所以, "空中飛鼠" 來的 poweroff event 就被攔截在一個很低的位階
不涉及 X, 或 WM, 或 desktop.
NB 1: 最好不要去 --grab 那個 event0, 因為會不能打 Ctrl-C
只能由外面 ssh 進來 killall evtest.
NB 2: 這時, 筆電跟空中飛鼠上其它所有的鍵似乎都沒受到影響.
NB 3. 不能直接去移除不想要的 /dev/nput/event20, 沒有用的
因為它是 opened 的, 如果在另外一個 terminal 做
$ sudo fuser -v /dev/input/event20
會看到:
USER PID ACCESS COMMAND
/dev/input/event20: root 1 F.... systemd
root 264 F.... systemd-logind
我 2860 F.... Xorg
root 8679 f.... evtest
如果用另一個 evtest 的 instance, 會看到:
$ sudo evtest /dev/input/event20
(...)
***********************************************
This device is grabbed by another process.
No events are available to evtest while the
other grab is active.
In most cases, this is caused by an X driver,
try VT-switching and re-run evtest again.
Run the following command to see processes with
an open fd on this device
"fuser -v /dev/input/event20"
***********************************************
(...)
所以問題初步解決! 但是必須讓 evtest(1) 一直跑下去
讓它抓住這個按鍵 event, 丟到垃圾筒:
$ sudo evtest --grab /dev/input/event20 >/dev/null
所以, 寫了一個小 script 來幫忙找到那個對的 device.
想試試看的人, 只要改一下 KEY 跟 NAME:
----- begin 我把它叫做 disable-airmouse-powerbtn -----
PROG=`basename -- "$0"`
KEY="FREEWAY TECHNOLOGY RFIC-MOUSE System Control"
NAME="KEY_POWER/空中飛鼠"
FILE="/proc/bus/input/devices"
EV=`grep -B1 -A7 "$KEY" "$FILE" | \
sed -ne 's/^H: .*\(\<[a-z0-9]*\).*$/\1/p'`
if [ "$EV" ]
then
echo "# $PROG: got \"$EV\" from $FILE"
else
echo "*** $PROG: device of $NAME not found"
exit 157
fi
EVDEV="/dev/input/$EV"
if [ "$1" = "do" ]
then
echo "# $PROG: sudo evtest --grab $EVDEV >/dev/null"
sudo evtest --grab "$EVDEV" >/dev/null
else
echo "# $PROG: $NAME found as $EVDEV"
echo "# $PROG: append \"do\" as argv1 to actually disable it"
fi
--- end of disable-airmouse-powerbtn ---
然後執行看看
$ disable-airmouse-powerbtn
# disable-airmouse-powerbtn: got "event20" from /proc/bus/input/devices
# disable-airmouse-powerbtn: KEY_POWER/空中飛鼠 found as /dev/input/event20
# disable-airmouse-powerbtn: append "do" as argv1 to actually disable it
或是直接特讓它到背景執行 (這是幾乎不消耗資源的):
$ setsid disable-airmouse-powerbtn do
我不曉得有沒有必要 detach, 反正我是這麼做了
反正, 斬斷一切的牽連, 免得被循著 cgroup 追殺...
後來, 我又把它放到 crontab 裡
@reboot /我家/sh/disable-airmouse-powerbtn do &
感興趣的人, 我推薦下載 Vojtech Pavlik 的原始碼看看,
$ apt-get source evtest
它只有一個單一的 .c 檔, 連個 .h 都沒有
$ gcc evtest.c # 確認 ok 之後意就隨你怎麼玩了
關鍵在
ioctl(fd, EVIOCGRAB, (void*)1);
我把必要的幾行盡量節省空間地濃縮為, 感興趣可直接 gcc:
(credit --> Vojtech Pavlik)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char* argv[])
{
struct input_event ev;
char *device, name[256];
int fd_evdev, n_bytes;
if ( NULL != argv[1] ) device = argv[1];
else {
fprintf(stderr, "usage: %s </dev/input/eventX>\n", *argv);
return EXIT_FAILURE; }
if ( -1 == ( fd_evdev = open(device, O_RDONLY) ) ) {
fprintf(stderr, "failed opening \"%s\": ", device); perror("");
return EXIT_FAILURE; }
(void) ioctl(fd_evdev, EVIOCGNAME(sizeof(name)), name);
printf("ioctl(fd_evdev, EVIOCGRAB, (void*)1)... ");
if ( 0 == ioctl(fd_evdev, EVIOCGRAB, (void*)1) ) printf("SUCCESS\n");
else { printf("FAILURE\n"); return EXIT_FAILURE; }
printf("grabbing \"%s\" at %s, Ctrl-C to quit\n", name, device);
while (1) if ((n_bytes = read(fd_evdev, &ev, sizeof ev)) < sizeof ev) break;
return EXIT_SUCCESS;
}
另一方面, 從一開始, 我就一直有個沒說出來的願望
是一個模模糊糊, 長得大概像這樣的願望:
方法二, # echo "咒術" > "/sys/迴戰/../的/../路徑/unbind"
*********************************************************
就是, 徹底跟 "那一個" 按鍵解約的辦法
只是一直沒找到 (還是沒耐心找到), 但幾天前試了一下
只是, 結果很容易忘記, 要寫個 script 記錄下來
就像我們在寫 Makefile 當作是在做 documentation 一樣
因為 script 有點大, 我把他的輸出 paste 過來就好
裡面已經吐露了足夠多的細節 (這次以 Lid Switch 為例)
$ unbind Lid
# unbind: given keyword "Lid"
# unbind: inspecting "/proc/bus/input/devices"...
# unbind: unbinding "/dev/input/event10"
# unbind: with full name "Lid Switch"
# unbind: via "/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/driver/unbind"
# unbind: agenda: echo -n "PNP0C0D:00" | sudo tee "/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/driver/unbind"
# unbind: append "do" in the comamnd line to carry it out
# unbind: sudo fuser -v /dev/input/10
USER PID ACCESS COMMAND
/dev/input/event10: root 261 F.... systemd-logind
或直接 $ unbind Lid do 之後, 面板開開關關就沒有效用了.
這樣, 我就不需要 logind.conf 改 logind.conf 了
因為, 那個檔案在更新的時候常會被"更新", 就又要寫個 script...
這樣, 是不是很美好....? 不, 發生了一個意外...
那就是, 雖然對於 "Lid Switch", 或是筆電上的電源鍵來說很好用
但是對我那支 "空中飛鼠" 不行!
因為它的好幾個 event handler 是綁在一起的, 我把它 unbind 掉
就會連 "空中飛鼠" 的其它按鍵都解約了.... :(
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.115.221.229 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/Linux/M.1617989996.A.946.html
推
04/10 07:00,
3年前
, 1F
04/10 07:00, 1F
→
04/10 09:36,
3年前
, 2F
04/10 09:36, 2F
→
04/10 10:41,
3年前
, 3F
04/10 10:41, 3F
→
04/10 10:41,
3年前
, 4F
04/10 10:41, 4F
推
04/10 12:45,
3年前
, 5F
04/10 12:45, 5F
→
04/10 12:46,
3年前
, 6F
04/10 12:46, 6F
→
04/10 12:46,
3年前
, 7F
04/10 12:46, 7F
推
04/10 19:15,
3年前
, 8F
04/10 19:15, 8F
推
04/11 09:14,
3年前
, 9F
04/11 09:14, 9F
推
04/11 11:13,
3年前
, 10F
04/11 11:13, 10F
推
04/16 05:18,
3年前
, 11F
04/16 05:18, 11F
討論串 (同標題文章)
Linux 近期熱門文章
23
129
PTT數位生活區 即時熱門文章