感谢支持
我们一直在努力

让你的Thinkpad在SUSE下工作得更好更完美

前言:
以下内容目的是为了让部分SUSE或其他发行版的新手可以有一份统一的教程step by step地调教自己的linux让系统更完美地兼容thinkpad系列laptop,欢迎高手拍砖,请轻点.


本文是以本人的实际实验结果为主,当中参考了很多网上的资料,包括thinkwiki, linuxquestions等等,未能一一尽列
本文希望能把自己解决linux问题的整个过程和思考方法写出来给有需要的新人参考,希望能让入门的朋友学习到解决linux问题的方法,而不是仅仅会按本宣科地解决问题

well, Google ROCKs!


注意:
各位阅读本文后要动手改造的话,请做好各种备份,意外准备,本人不负责任何风险
本文以thinkpad x61为例子,其他机型请适当做变通灵活处理
本人实验过2.6.16.xx, 2.6.27.xx内核,其他版本内核请适当变通,理论上2.6.16~27都可以成功
由于本人是以suse系列做实验,其他发行版变通处理,不保证成功

附件的patch是根据suse11.1 2.6.27.25内核制作的,可以直接使用

内容以操作难度易到难顺序排列

准备工作
首先,要安装必备的开发包,没有安装的话进入yast2 -> software management, 把kernel, C/C++, Python, QT, gnome/kde等一古脑相关的开发包装上.


win key毫无用处?
win key在windows下可以唤出开始菜单, 在linux很多发行版上一般也可以唤出gnome/kde panel menu,但为什么opensuse上不行呢,gnome keyboard shortcut里面也设置不了. 先google一下,很快找到提示,原来win key默认已经被映射成叫作Super_L的键,在gconf-editor里面可以设置metacity的keybinding,所以我打开gconf-editor -> app -> metacity -> global_keybindings -> panel_main_menu,直接输入Super_L.退出,试一下,成功了~~


单独按Fn键会变成鼠标右键功能?很烦耶
注:其实这个问题的实际原因是在于我把keyboard的模型选成IBM thinkpad T60,只要选择其他键盘模型就不会有这个问题了,如果有人碰到和我一样的问题可以参考.
真不方便,因为控制Fn+Fx时候很容易就变成鼠标右键功能了.究竟怎么回事呢?为了解决这个问题,我先google一下”linux thinkpad Fn hot key”, 它带领我去到thinkwiki.org这个网站.
thinkwiki内有搜索功能,用hot key搜索,

http://www.thinkwiki.org/wiki/How_to_get_special_keys_to_work

把出来的内容看了一遍,可惜里面没有描述到这个问题,但其中提到过系统可以用xmodmap来管理hot key功能映射的.根据这个提示和介绍,在terminal输入xev这个命令.这个命令可以检测键盘,鼠标的输入,将信息输出.
启动xev后,按Fn,输出以下信息:

KeyRelease event, serial 33, synthetic NO, window 0x3800001,
root 0x7c, subw 0x0, time 8672029, (251,340), root:(259,415),
state 0x0, keycode 227 (keysym 0x0, Menu), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False


结合thinkwiki上面的介绍,我大概猜猜这个信息的意思: keycode 227表示键盘中断给出的Fn 键代码, Menu代表被xmodmap映射后的功能. Menu指的就是鼠标右键功能.
好了,既然这样,我只要将keycode 227到Menu的映射去掉就可以了.为了实现这步,根据thinkwiki的描述可以用xmodmap命令的remove实现,可是怎样都不成功, man xmodmap信息和例子很少, google的信息也不太多.后来我想,系统肯定是根据某个config文件来设置的.用grep keycode * -R命令分别在/etc, /usr/share目录下寻找相关设置文件,最终找到/usr/share/X11/xcb目录,查看一下里面的文件格式,应该就是这里了,于是在grep 227 * -R一次,终于在xfree86里面找到:

// IBM ThinkPad 60 series
xkb_keycodes “thinkpad60” {
include “xfree86(xfree86)”
<MENU> = 227;
};


谁写下的啊….真多此一举阿…..把这句干掉.重启系统….这世界清静了

think vantage键空着不爽……
让每电脑每部分的硬件都发挥作用多好阿…偏偏thinkpad多了这个标准没有的键,就这样空着很无聊啊.想想能让它发挥点作用多完美.于是我便动手了.根据thinkwiki的介绍,这个功能早就实现了,只要内核带有thinkpad_acpi(前身是ibm_acpi)模块.但怎样控制呢,通过google,线索指向/etc/acpi.进去看一看,里面有个thinkpad文件:

event=ibm/.*
action=/usr/lib/acpid/thinkpad_handler “%e”


原来event指的是/proc/acpi/下各种事件(硬件以文件方式表示事件), action就是根据这个事件而发生的动作
根据上面描述,找到thinkpad_handler这个文件:

#!/bin/bash

HOTKEY=$1
set $HOTKEY
EVENT=$1 # “ibm/hotkey”
ACPI=$2 # “HOTK”
WHAT=$3 # “00000080”
SERIAL=$4 # “0000100c” Fn+F12
# bluetooth
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001005” ]; then
ACTION=”disable”
grep -q “disabled” “/proc/acpi/ibm/bluetooth” && ACTION=”enable”
echo $ACTION > “/proc/acpi/ibm/bluetooth”
fi


看来这个脚本只处理了蓝牙,其他热键则在内核其他地方处理了.不管了,在这照葫芦自己写一下一段

# thinkvantage
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001018” ]; then
ACTION=”vantage”
yast2 &
echo “start yast2” >>/var/log/usr_local.log
fi


我把thinkvantage功能做成调用yast,真是和SUSE绝配的想法….恩,但怎么不行呢…..经过调试和google, 是 X 协议的问题,这个问题很难解决最后用了个粗暴的方法直接 xhost +后可以运行了.最终我将脚本改成这样:

#!/bin/bash

HOTKEY=$1
set $HOTKEY
EVENT=$1 # “ibm/hotkey”
ACPI=$2 # “HOTK”
WHAT=$3 # “00000080”
SERIAL=$4 # “0000100c” Fn+F12

echo “thinkpad_acpi_events $EVENT $ACPI $WHAT $SERIAL” >>/var/log/usr_local.log

# based on /etc/acpi/screenblank.sh (Ubuntu 7.10)
# . /usr/share/acpi-support/power-funcs # for getXuser
getXuser() {
user=`finger| grep -m1 “:$displaynum ” | awk ‘{print $1}’`
if [ x”$user” = x”” ]; then
user=`finger| grep -m1 “:$displaynum” | awk ‘{print $1}’`
fi
if [ x”$user” != x”” ]; then
userhome=`getent passwd $user | cut -d: -f6`
export XAUTHORITY=$userhome/.Xauthority
else
export XAUTHORITY=””
fi
}

# end of getXuser from /usr/share/acpi-support/power-funcs
#
for x in /tmp/.X11-unix/*; do
displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
getXuser;
export DISPLAY=”:$displaynum”
done

# bluetooth
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001005” ]; then
ACTION=”disable”
grep -q “disabled” “/proc/acpi/ibm/bluetooth” && ACTION=”enable”
echo $ACTION > “/proc/acpi/ibm/bluetooth”
echo “bluetooth switch” >>/var/log/usr_local.log
fi

# thinkvantage
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001018” ]; then
ACTION=”vantage”
su $user -c “gnomesu -c /sbin/yast2” &
echo “start yast2” >>/var/log/usr_local.log
fi

# Fn+F3
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001003” ]; then
ACTION=”off screen”
su $user -c “xset dpms force off” &
echo “turn off screen” >>/var/log/usr_local.log
fi

# Fn+F7
#if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001007” ]; then
# ACTION=”switch screen”
# echo video_switch > /proc/acpi/ibm/video
# echo “swith screen” >>/var/log/usr_local.log
#fi

# Fn+F9
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001009” ]; then
ACTION=”eject cdrom”
eject /dev/cdrom &
echo “eject cdrom” >>/var/log/usr_local.log
fi

# Fn+Space
if [ “$WHAT” = “00000080” -a “$SERIAL” = “00001014” ]; then
ACTION=”terminal”
su $user -c “gnome-terminal” &
echo “run a terminal” >>/var/log/usr_local.log
fi

unset DISPLAY
unset XAUTHORITY


里面我将一些suse本来不支持的热键也增加了:
其中Fn+F3本来在suse gnome中关闭screen safer后就失效,我增加后就一直可以使用了.
Fn+Space设置成打开gnome-terminal,这下方便我了
Fn+F9用来*出光驱
每个热键的键码在/usr/src/linux-2.6.xxxx/Documentation/laptop/thinkpad-acpi.txt文面找到.最后,在gnome-session中添加一个autostartup “xhost +”让用户每次登录后自动执行害怕电池充放电太多
thinkpad在windows下支持的电池充放电上下限管理是一大特色, 据说有效地保护电池延长寿命呢…
根据thinkwiki的介绍

http://www.thinkwiki.org/wiki/Tp_smapi

我需要的是tp_smapi,去下载tp_smapi的源代码包.有很多版本,我在2.6.16版本内核上最高只可以使用0.31把本, 在 2.6.27版本上可以用0.40版本.大家可以根据自己的内核版本多试试不同的版本,在解压后的目录下运行(root):

make load HDAPS=1
或者 make load HDAPS=1 FORCE_IO=1 (针对T400/T500等新机型)

首先在SUSE上会报错找不到aio_abi.h文件, 这个文件在/usr/src/linux/include/linux里,报错是因为在/usr/src/linux-obj里面没有
把它copy到linux-obj里面相应的include/linux里面,继续

不成功的话换一个版本, 成功的话接着

make install HDAPS=1

好了,已经安装好,但系统不会自动加载,要做到这点,在yast2 -> /etc/sysconfig editor -> system -> kernel -> modules_loaded_on_boot中加入hdaps tp_smapi.
保存,重启电脑后, 运行 dmesg > a, 打开a文件,搜索hdaps, tp_smapi,看到没有报错信息就ok了. 在2.6.16 kernel + 0.31 tp_smapi情况下,看到hdaps报错,说找不到thinkpad model.看来是机型和原来的设计不匹配, x61对 0.31来说太新了.于是我打开tp_smapi里面的hdaps.c文件,看到有段:

struct dmi_system_id hdaps_whitelist[] = {
HDAPS_DMI_MATCH_INVERT(“IBM”,”ThinkPad R50p”),
HDAPS_DMI_MATCH_INVERT(“IBM”,”ThinkPad T41p”),
HDAPS_DMI_MATCH_INVERT(“IBM”,”ThinkPad T42p”),
HDAPS_DMI_MATCH_INVERT(“LENOVO”,”ThinkPad T60″),
HDAPS_DMI_MATCH_INVERT(“LENOVO”,”ThinkPad X60″),
{ .ident = NULL }
};


直接把X60改成X61,重新安装一次, okay了~~现在执行

echo 15 > /sys/devices/platform/smapi/BAT0/inhibit_charge_minutes
echo 20 > /sys/devices/platform/smapi/BAT0/start_charge_thresh
echo 100 > /sys/devices/platform/smapi/BAT0/stop_charge_thresh


好了,电池设置好了, start_charge_thresh是开始充电的阈值, stop_charge_thresh是停止充电的阈值,运行一次后设置就保存了,只要不拆下电池设置就不会丢失.

来啦, 监视电脑震动
thinkpad X/T系列都带有3D硬盘保护功能, 就是检测电脑的移动保护硬盘. linux kernel已经把监视移动的功能集成进去了,就是前面提到的hdaps模块.在前面已经可以成功加载hdaps后,就可以用程序实时监视了. 首先根据thinkwiki上的连接下载到hdaps-gl-0.0.5,编译,中途报错缺少GL/glut.h,google一下原来是opengl相干的东西, 就去安装opengl相关的devel包,yast中搜索opengl, 把相关的devel包装好, 搞掂.
编译成功后,cp hdaps-gl /usr/bin, 运行hdaps-gl, 移动电脑,成功了~~
还可以把监视集成在gnome/kde panel里面,分别是tilt-0.0.2和plasmoid-hdaps-monitor-0.3-1.22(openSUSE官网上有),其中tilt不能自动添加到gnome panel里面,所以把它在session里做成一个autostartup,运行后会出现一个坐标值,参照附件图片


让你的Thinkpad在SUSE下工作得更好更完美



到了这份上,怎么说也要把硬盘保护功能弄出来吧….
到目前为止呢,都是小打小闹,要实现这功能可要冒点 当机 的风险了.因为这回要对内核打补丁,重新编译内核…..
而且, disk protect的patch不是每个版本的内核都有,除了要大胆,还要有运气,当然最重要还是行动.
根据圣经的指示,我在

http://www.thinkwiki.org/wiki/HDAPS
http://www.thinkwiki.org/wiki/How_to_protect_the_harddisk_through_APS

下载了所有版本的补丁备用

实现硬盘保护的功能是这样的:
首先对硬盘的移动进行检测 — 即上面的hdaps module已经实现了, 此module集成在kernel hwmon目录下
然后根据移动的数据进行判断要不要进行保护, 此需要一个守护程序, 即 hdapsd,需要安装
当hdapsd判断需要保护,就要指示内核对硬盘进行磁头 park的动作, 此功能在大多数内核版本上没有实现, 据说在2.6.28以后的版本集成了

首先,要查看自己内核的版本:

uname -r

然后找一个针对此版本的补丁, 如果没有,则找个版本最接近的,同时去ftp.kernel.org下载和这版本对应的kernel原代码下来备用

用编辑器打开patch文件,先了解一下patch文件格式,这很有必要~~:

diff -urN linux-2.6.16.original/block/ll_rw_blk.c linux-2.6.16.hdaps/block/ll_rw_blk.c
— linux-2.6.16.original/block/ll_rw_blk.c 2006-03-20 05:53:29.000000000 +0000
+++ linux-2.6.16.hdaps/block/ll_rw_blk.c 2006-03-28 20:39:03.000000000 +0100
@@ -39,6 +39,8 @@
static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
static void init_request_from_bio(struct request *req, struct bio *bio);
static int __make_request(request_queue_t *q, struct bio *bio);
+static int blk_protect_register(request_queue_t *q);
+static void blk_protect_unregister(request_queue_t *q);


patch文件以 diff xxxxxx 开头分段,每段代表对一个文件要进行修改的内容, block/ll_rw_blk.c代表linux-2.xxxxx/block/ll_rw_blk.c文件, “+”开头代表是在原文件中增加的内容, “-“开头代表在源文件删去的内容, ” “开头代表原文件不动的地方,即进行匹配用的上下文

好,开始动手

首先建一个工作目录,确保分区有足够的硬盘空间,大概需要4G的空间:
mkdir tp_kernel

进入工作目录,然后cp kernel source过来并重命名
cp -rf /usr/src/linux-2.6.xx.xxx linux-2.6.xx.xxx-tp (具体版本请根据上面的结果)

进入这个目录, cp 内核编译配置文件过来
cp /boot/config-xxxxxxx .config

打开配置文件,修改版本号, 这步很重要,不然编译安装后就会覆盖原来的内核了
CONFIG_LOCALVERSION=”-0.1″ -> CONFIG_LOCALVERSION=”-0.1-tp”


然后把patch文件copy过来,运行
patch -p1 < xxxxxx.patch

运气好,直接成功,运气不好,会报Failed
这时别怕,要亲自动手了, Fail有2种情况:
一种是文件匹配不上,这出现在内核版本和patch对应版本差别比较大或者发行版对此进行过修改的情况下
另一种是报找不到对应文件,这是因为有可能在某些发行版或版本中某些文件改变了存放的目录

对第一种情况,如果只报了一两处fail的话,我们就进入所在文件的目录, 例如如果libata.h报告fail,进入include/linux/,这里面会有3个文件:
libata.h , libata.rej , libata.h.orig
首先rm libata.h,因为这个文件已经是被错误的patch了,基本没有利用价值, libata.rej也可以删了
然后编辑libata.h.orig, 同时打开patch文件, 找到libata.h文件所在的patch段,根据上面的介绍的理解方法,找到需要修改的地方,即 “+”, “-“开头的行,
然后根据此行的上下文在libata.h.orig文件中寻找此段内容的位置,找到后按照patch文件里面的指示,把”-“开头的行删掉或者把”+”开头的行加入在相应地方,如此这般,把整个patch内容手动修改完
最后 mv libata.h.orig libata.h

如果第一种情况下报错比较多,则建议全部文件手工打patch重来,因为已经有可能在那些报告成功的文件上其实也没有正确地打上patch,方法和上面的一样.

如果第二种情况报错,首先要找到对应的文件所在:
find ./ -name *libata*

然后人手修改所有文件,因为出现此情况一般而言kernel和patch的版本已经差别比较大,安全起见以人手修改最好

把全部文件patch好,先把整个source目录打包备份一下

现在可以开始编译了,在source目录下运行
make 2>./make_err

然后开始漫长的等待


~~~~~~~~~~真的很长~~~~~~~~~~

结束后,看看make_err里面有没有error,如果没有则成功了,如果patch的版本和kernel的版本很接近的情况下基本都是成功了
如果上面打补丁时需要比较多的人手修改,则很有可能报错,其实就是patch版本和kernel版本差太远了,不要灰心,还是有可能成功的

这时看看报错信息,一般来说是报告某些函数/变量没有声明,这有可能是include文件没有被patch上.

现在把整个目录删掉,把刚才打包好的备份解出来,再进行额外的修改工作
根据出错信息,找到出错的文件,然后在之前准备好和patch版本对应的标准kernel source里找到相对应的文件

仔细比较2个文件,根据报错指示的函数或变量搜索
看看在标准版本里有没有多出来的声明,定义,或函数体等,有的话cp这部分代码到我们要修改的文件上
如果没有找到,则很有可能在某些include文件中, 在标准source里用grep命令找出这个定义/声明所在的xxxx.h文件,然后在要修改的版本里相应的文件里加上相应的东西,最后检查这个头文件有没有被出错的c文件include,没有的话加上.

如此这般,修改–>make–>修改–>…..直到最后没有报错
最后还是要检查一下make_err,看看里面有没有一些warning是跟我们修改过的文件有关的,如果有一些什么not found之类warning最好还是再检查一下代码

make成功后,恭喜恭喜,接近完成任务了,接下来继续:

make modules_install

然后

make install

然后, 重启电脑

在grub菜单上会多出一个 tp-openSUSE xxxxxxxxxx, 这就是我们重新编译过的版本, 选择它进入linux

没有黑屏啥的话基本说明已经okay了. 先检查一下各项普通操作有没有问题.没有问题的话,重新安装tp_smapi一次!再次重启后,电池和位置监视功能回来了
如果电脑是nvidia, ati的显卡,请再安装一次相关驱动,另外vmware, virtualbox之类都有可能需要重新安装,总之有软件不能使用就重新安装吧现在开始安装hdapsd这个守护程序了,去openSUSE官网上搜索hdaps,下载hdapsd-20090401-7.1.x86_64.rpm
然后 rpm -Uvh hdapsd-20090401-7.1.x86_64.rpm
以root运行 hdapsd -d sda -s 10 -a -v
这时会不停输出位置信息,移动电脑,会看到 xxxxxx parking的信息闪过,代表保护功能成功了~~~~~可以中断程序
好了, 进去/etc/init.d/

运行chkconfig –del hdaps

然后修改hdaps,将HDAPS_ARGS修改为以下内容
HDAPS_ARGS=”-d sda -s 10 -a -b -l”
如果是比较旧的thinkpad用的是ide硬盘的话将sda改成hda

mv hdaps hdaps_deamon

最后chkconfig –add hdaps_deamon

重启电脑, 然后移动几下电脑, 接着查看/var/log/messages,如果里面有xxxx parking 或 unparking之类,则代表一切都完美了:
以root运行 cat /var/log/messages | grep park
输出:

Aug 15 14:24:59 FroX61 hdapsd[2401]: un-parking
Aug 15 14:28:41 FroX61 hdapsd[2401]: parking
Aug 15 14:28:42 FroX61 hdapsd[2401]: un-parking
Aug 15 14:31:48 FroX61 hdapsd[2401]: parking
Aug 15 14:31:50 FroX61 hdapsd[2401]: un-parking
Aug 15 14:31:51 FroX61 hdapsd[2401]: parking
Aug 15 14:31:54 FroX61 hdapsd[2401]: un-parking
Aug 15 14:32:29 FroX61 hdapsd[2401]: parking
Aug 15 14:32:30 FroX61 hdapsd[2401]: un-parking
Aug 15 14:34:17 FroX61 hdapsd[2401]: parking
Aug 15 14:34:18 FroX61 hdapsd[2401]: un-parking
Aug 15 14:36:52 FroX61 hdapsd[2401]: parking
Aug 15 14:36:53 FroX61 hdapsd[2401]: un-parking


注意:
据说,硬盘磁头parking功能不一定所有硬盘都支持,thinkpad原装的x/t系列肯定支持,但如果是自己更换过的硬盘即使软件一切如常仍无法确保了. 大家可以在成功把所有东西装好用耳朵听一听验证一下,在移动电脑的时候靠近硬盘位置听听有没有轻微的”啪”一声,这是磁头parking的声音

最后的工作:
重启电脑,进入原来的内核,即默认那个
进入/usr/src, 删除linux这个符号链接,重新建立一个链接到新的内核
rm linux
ln -s /home/sysbackup/2.6.27.25-0.1-X61/linux-2.6.27.25-0.1-X61/ linux (这是我的,大家根据自己情况相应修改)

如果想把编译好的内核移动到其他地方,移动后,要在/lib/modules/里面相应的版本里面把source, build的链接修改到相应的地方

最后, yast2 -> bootloader ,把默认进入的内核改为编译过的

大功告成!

还想更完美吗?
openSUSE11.1的2.6.27内核中的thinkpad_acpi版本是0.21的,最新的是0.23版本,还有一个基于0.23版本的第2风扇patch.例如X61中的第二个风扇要完美支持就必须升级thinkpad_acpi了.
首先去下载:
thinkpad-acpi-0.23-20090606_v2.6.27.24.patch.gz
fix-two-fan-support.patch

打补丁的方法就按上面的方法一样,先打上thinkpad-acpi的patch再打上fix-two-fan的patch
但是还有一个问题,搜索这段:
/* there’s a limit of 19 chars + NULL before 2.6.26 */
“tpacpi:ower”,
“tpacpi:orange:batt”,
“tpacpi:green:batt”,
…….
…….

按上面的注释内容, 这个问题不应该在opensuse11.1上出现,但实际上仍有问题,所以应该将这段的内容每行改成19个字符以下的长度
然后再次编译内核就成功了
在/etc/modprobe.d/thinkpad_acpi中加入brightness_enable=1 fan_control=1

重启后
cat /sys/devices/platform/thinkpad_hwmon/fan*
3255
7425

输出的就是2个风扇的转速


附件 thinkpad-suse-2.6.27.25-0.1.patch.tar.gz  下载

赞(0) 打赏
转载请注明出处:服务器评测 » 让你的Thinkpad在SUSE下工作得更好更完美
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏