Linux 板


LINE

上一篇我所提的问题, 有了部份解答, 回文整理一下 我讲的琐碎一点, 大家比较容易发现我的盲点 以後有碰到类似问题的人也可以省下一点时间 搞不好, 最常跑来回顾细节的, 就是我自己 因为我们会游走在 "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://webptt.com/cn.aspx?n=bbs/Linux/M.1617989996.A.946.html
1F:推 in09: 感谢 04/10 07:00
2F:→ OrzOGC: 好硬核啊... 04/10 09:36
3F:→ tomsawyer: 看起来是南桥帮你注册input fd,kernel也随之生成相关 04/10 10:41
4F:→ tomsawyer: event 04/10 10:41
5F:推 Bencrie: 应该是算 systemd 设计上的不足,毕竟都它在处理的 04/10 12:45
6F:→ Bencrie: config 没办法个别设定要不要反应 power button 04/10 12:46
7F:→ Bencrie: 至於遮断 event20 我想应该可以用 udev rule 去处理 04/10 12:46
8F:推 LinBuoRen: 推解决方案 04/10 19:15
9F:推 ptrpan: 推 04/11 09:14
10F:推 goldie: 推 04/11 11:13
11F:推 H2b2t: 推 04/16 05:18







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Soft_Job站内搜寻

TOP