您尚未登录。

#1 2012-02-06 14:46:26

sigma
会员
注册时间: 2012-01-03
帖子: 183

驱动小黑T61hotkey手记

寒假回家决定换台电脑,于是开始给T61装arch。说到T61我要跑题一下,很多人都认为T43是IBM最后的绝唱,但其实T60/T61还可以算是IBM的嫡系产品,在联想刚并购IBM的时期,生产线和供应商都还未发生变化,所以T61从设计至出厂的整套流程还是和IBM时期无区别的,只是在logo上多了一个恶心的lenovo标志,所以我一直自欺欺人的把T61看成是IBM水准的产品 :em06
好吧,回归主题。系统装完之后我发现静音键和音量升音量降都没有用,Fn+F*的组合键也只有几个起作用,分别是Fn+PgUp(屏幕灯),Fn+F5(无线网卡,只能关不能开),其他都无效。。。于是我开始了艰苦卓绝的google之旅。。。
看了几篇文档之后,对于组合功能键我大概明白了一个方法,就是通过xmodmap将这几个按键的键值映射为一些虚拟键,比如F20之类的,然后在WM中将F20绑定程序即可达到目的,原理似乎没有问题,但是实际操作中还是无效,而且我发现了一个无比诡异的情况。那就是用xev查看按键键值和用showkey来查看的键值竟然不一样!我囧。。。这个问题我至今还没找到原因,但显然这条路走不通了。
而对于静音键无效,网上说要给内核添加一个acpi_osi="linux"的启动参数,于是vi /boot/grub/menu.lst在kernel行的最后加上这个参数,重启依然无效。。。直觉告诉我,不管是静音键还是组合功能键,解决问题的方法应该是一样的。
再次经过一阵google之后,我发现起作用的键都是由主板bios通过acpi事件直接驱动的,换句话说他们和按下电源键是同一类事件,网上基本都说要加载一个名为thinkpad_acpi的模块,这个模块就是专门用来识别thinkpad特有功能键的。于是如果安装了acpid这个包的话,那么modprobe thinkpad_acpi,然后/etc/rc.d/acpid start,此时运行acpi_listen再去按那几个特殊键,发现他们全都被捕捉到了,这时候屏上看到的事件都变为了button/battery,button/wlan,button/sleep,button/lockscreen之类的事件,这说明thinpad_acpi这个模块将按键信号截获并转化成了系统的button事件而不再是主板的acpi事件了。
到了这一步,可以说成功了一半,剩下要做的就是驱动这些按键了。到此网上又给出了两种办法,一是安装一个叫tpb的包,它可以很方便的驱动这些事件而且还能在屏幕上显示音量啊亮度啊什么的信息。抱着试一试的心态我yaourt tpb,装好后vi /etc/tpbrc,配置里面注释很全,都能看懂,但是它只提供了ThinkVantage,PowerButton这两个键的事件驱动,还有一些A系列和S系列的特殊键。。。你他妈在坑爹吗!而且网上tpb的文档也不知道在哪,想自己添加都不会写,也只好放弃了,卸了它!
所以我只剩最后一条路了,也就是方法二:自己写脚本来驱动!在/etc/acpi/下有一个脚本叫handler.sh,这个脚本就是acpi默认的处理所有事件的脚本,打开能够看到PowerButton,button/sleep等几个键的事件处理方法,那么现在开始自己添加。首先再次运行acpi_listen,按下Fn+F2,记录屏幕上捕捉到的事件为button/screenlock SCRNLCK,前面是按键名,后面是参数名,那么仿照现有的写法先用case匹配按键名然后再匹配参数名,事件对应的程序,就用xlock好了,不要忘记为了逻辑严谨要对不匹配的情况做出处理。同样的Fn+F4是button/sleep SBTN,处理事件的命令是echo -n mem > /sys/power/stat,将内存换页到swap中去。然后Fn+F9,button/f24 F24,这个是弹出光驱那个键,用eject来处理事件就好。合上笔记本的事件是button/lid,如果愿意可以把它跟F4一样做挂起处理。静音键button/mute MUTE,要用到命令行的amixer来处理,需要自己写一个判断语句,如果是静音状态则取消静音,如果是非静音则启用静音,命令为amixer -q set Master mute,同样的音量升和音量降分别是button/volumeup VOLUP,button/volumedown VOLDN,同样用命令amixer set Master 10%+,amixer set Master 10%-来处理。
这样的话基本上需要用到的特殊键都驱动好了,唯一有一个问题就是Fn+F8快速开关小红点和触摸板在acpi_listen中捕获不到事件,这个我会继续想办法,如果有高人知道求不吝赐教~
目前我对于F8的解决办法是自己写了一个简单脚本在musca中绑定为Mod4+F8,脚本中判断执行synclient TouchPadOff=1或0
下面把我的/etc/acpi/handler.sh贴出,大家见笑了
#!/bin/sh
# Default acpi script that takes an entry for all actions

minspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`
maxspeed=`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`
setspeed="/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"

set $*

case "$1" in
    button/mute)
        #mute
        case "$2" in
            MUTE)       
                status=`amixer get Master | sed -n '5,1p' | awk '{print substr($6,2,2)}'`
                if [ $status = on ]; then
                    amixer -q set Master mute
                elif [ $status = of ];then
                    amixer -q set Master unmute
                else
                    exit 0
                fi
                ;;
            *)          logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/volumedown)
        #volumn down
        case "$2" in
            VOLDN)      amixer -q set Master 5%- ;;
            *)          logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/volumeup)
        #volumn up
        case "$2" in
            VOLUP)      amixer -q set Master 5%+ ;;
            *)          logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/screenlock)
        #lock screen
        case "$2" in
            SCRNLCK)    xlock ;;
            *)          logger "ACPI action undefined: $2" ;;
        esac
        ;;
    video/switchmode)
        #switch video
        case "$2" in
            VMOD)   
                if [ "$(xrandr -q | grep "VGA connected")" ]; then
                    if [ "$(xrandr -q | grep "VGA connected [0-9]")" ]; then
                        xrandr --output VGA --off
                    else
                        xrandr --output VGA --auto
                    fi
                else
                    xrandr --output VGA --off
                fi
                ;;
            *)      logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/f24)
        #eject
        case "$2" in
            F24)    eject ;;
            *)      logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/power)
        #echo "PowerButton pressed!">/dev/tty5
        case "$2" in
            PBTN|PWRF)  logger "PowerButton pressed: $2" ;;
            *)          logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/sleep)
        case "$2" in
            SBTN)   echo -n mem >/sys/power/state ;;
            *)      logger "ACPI action undefined: $2" ;;
        esac
        ;;
    ac_adapter)
        case "$2" in
            AC|ACAD|ADP0)
                case "$4" in
                    00000000)
                        echo -n $minspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode start
                    ;;
                    00000001)
                        echo -n $maxspeed >$setspeed
                        #/etc/laptop-mode/laptop-mode stop
                    ;;
                esac
                ;;
            *)  logger "ACPI action undefined: $2" ;;
        esac
        ;;
    battery)
        case "$2" in
            BAT0)
                case "$4" in
                    00000000)   #echo "offline" >/dev/tty5
                    ;;
                    00000001)   #echo "online"  >/dev/tty5
                    ;;
                esac
                ;;
            CPU0)   
                ;;
            *)  logger "ACPI action undefined: $2" ;;
        esac
        ;;
    button/lid)
           case "$3" in
        close)
        #echo "LID closed!">/dev/tty5
        ;;
        open)
        #echo "LID opened!">/dev/tty5
            ;;
    esac
    ;;

    *)
        logger "ACPI group/action undefined: $1 / $2"
        ;;
esac


辛苦手打,谢谢大家捧场
                           sigma


riverrun, past Eve and Adam's.

离线

#2 2012-02-06 16:09:46

phoenixlzx
晩ご飯だよー
注册时间: 2011-08-19
帖子: 1,789
个人网站

Re: 驱动小黑T61hotkey手记

支持一下,说的我的T420跟劣质产品似的。。。不过方法基本上算是通用的,ThinkPad系列的应该都可以用。

离线

页脚