顯示具有 linux 標籤的文章。 顯示所有文章
顯示具有 linux 標籤的文章。 顯示所有文章

2011年2月24日 星期四

開關touchpad的熱鍵在udev中已經標準化


commit a1ca5f60e0770299c5c5f21bd371f5823802412b
Author: Bastien Nocera
Date: Thu Nov 4 23:58:56 2010 +0000

extras/keymap: Make touchpad buttons consistent

We'll need to standardise on the Touchpad related keys in udev, kernel, and
X.org. I selected F21 for XF86TouchpadToggle, F22 for XF86TouchpadOn and F23
for XF86TouchpadOff.

See:
https://bugs.freedesktop.org/show_bug.cgi?id=31333

Signed-off-by: Martin Pitt


參考 Touchpad toggle mess

Bug 31333 - Standardise Touchpad toggling keys

2010年10月13日 星期三

Ubuntu切換外接video的hotkey作法

首先evdev driver必須從kernel input event得到正確的keycode,在/usr/include/linux/input.h定義為:
#define KEY_SWITCHVIDEOMODE     227


然後在xkb-data套件中定義了kernel keycode到X keycode的mapping:在/usr/share/X11/xkb/keycodes/evdev裡:
<I235> = 235;   // #define KEY_SWITCHVIDEOMODE     227


在/usr/share/X11/xkb/symbols/inet裡:
key <I235>   {      [ XF86Display           ]       };


於是當切換外接video的hotkey按下後,也就是scancode產生時,kernel input event會產生出值為227的keycode,evdev讀到之後,Xserver再依據xkbdata的設定轉換為XF86Display。

接下來gnome-settings-daemon會filter這個X key,如gnome-settings-daemon-2.32.0/plugins/xrandr/gsd-xrandr-manager.c:

if (xev->xany.type == KeyPress) {
if (xev->xkey.keycode == manager->priv->switch_video_mode_keycode)
handle_fn_f7 (manager, xev->xkey.time);
else if (xev->xkey.keycode == manager->priv->rotate_windows_keycode)
handle_rotate_windows (manager, xev->xkey.time);


g-s-d每收到一個XF86Display key時,會呼叫gnome-rr-* 相關的函式(請見libgnomeui/gnome-rr.h),透過RandR API切換螢幕顯示的設定,便會切換到如外接投影機等顯示設備。

參考:http://live.gnome.org/RandR

2010年10月6日 星期三

Kernel: 不列入git log的changelog

對Linux kernel或LKML來說,git log是十分正式的紀錄。不過還是有些時候,我們只想寫一些對於這個patch的意見、或是給subsystem maintainer的一些參考說明,這些東西就不是那麼適合列入正式的git log中。

一個常見的情況是maintainer對於你的patch會有不同意見,此時可能會有patch v2, v3...的出現,而這些版本之間如果可以有簡單的說明的話,對於patch review會有很大的幫助。

像是這些「非正式性」的log,可以被紀錄在diffstat之後,如:

From 1709e3f1b68a12ce05039a52182288d0f4e21c7a Mon Sep 17 00:00:00 2001
From: Keng-Yu Lin <keng-yu.lin@canonical.com>
Date: Tue, 28 Sep 2010 11:11:57 +0800
Subject: [PATCH v5] dell-laptop: Add debugfs support

Export the status of RF killswitch through debugfs.

The killswitch status is obtained by the SMI to BIOS. Exporting this status
through debugfs can help identify the issue with the misbehaving firmware.

Signed-off-by: Keng-Yu Lin <keng-yu.lin@canonical.com>
---
drivers/platform/x86/dell-laptop.c | 77 ++++++++++++++++++++++++++++++++++++
1 files changed, 77 insertions(+), 0 deletions(-)

V5 fixed operator precedence mess-up of hwswitch_state, and prints the
bit number so that this debug info is complete for hardare manufacturers.


diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 4413975..cf8a89a 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
(下略)
Patchwork: https://patchwork.kernel.org/patch/213982/

而在Linux Documentation/SubmittingPatches Section 1.15中也有說明:
Other comments relevant only to the moment or the maintainer, not suitable for the permanent changelog, should also go here. A good example of such comments might be "patch changelogs" which describe what has changed between the v1 and v2 version of the patch.

2010年9月12日 星期日

DKMS和KERNELRELEASE變數

當 Makefile 是從 kernel build system 被呼叫執行時,KERNELRELEASE 變數會被 kbuild 定義。

這是一個常見的 Makefile 小技巧,判斷 KERNELRELEASE 是否定義來執行不同的設定。

如下列是compat-wireless的Makefile,就用到這樣的技巧:

  1. (SKIP)

  2. ifneq ($(KERNELRELEASE),)

  3. NOSTDINC_FLAGS := -I$(M)/include/ \
  4. -include $(M)/include/linux/compat-2.6.h \
  5. $(CFLAGS)

  6. obj-y := compat/

  7. obj-$(CONFIG_COMPAT_RFKILL) += net/rfkill/

  8. ifeq ($(BT),)
  9. obj-$(CONFIG_COMPAT_WIRELESS) += net/wireless/ net/mac80211/
  10. obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/


  11. endif


  12. else

  13. export PWD := $(shell pwd)
  14. CFLAGS += \
  15. -DCOMPAT_BASE_TREE="\"$(shell cat compat_base_tree)\"" \
  16. -DCOMPAT_BASE_TREE_VERSION="\"$(shell cat compat_base_tree_version)\"" \
  17. -DCOMPAT_PROJECT="\"Compat-wireless\"" \
  18. -DCOMPAT_VERSION="\"$(shell cat compat_version)\""

  19. # These exported as they are used by the scripts
  20. # to check config and compat autoconf
  21. export COMPAT_CONFIG=config.mk
  22. export CONFIG_CHECK=.$(COMPAT_CONFIG)_md5sum.txt
  23. export COMPAT_AUTOCONF=include/linux/compat_autoconf.h
  24. export CREL=$(shell cat $(PWD)/compat_version)
  25. export CREL_PRE:=.compat_autoconf_
  26. export CREL_CHECK:=$(CREL_PRE)$(CREL)

  27. include $(PWD)/$(COMPAT_CONFIG)

  28. all: modules

  29. modules: $(CREL_CHECK)
  30. @./scripts/check_config.sh
  31. $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules
  32. @touch $@

  33. (SKIP)

  34. endif


當從 shell 執行 make 時,因為 KERNELRELEASE 沒有定義,所以第23行到第39行之間的一些變數和 CFLAGS 會被設定,然後第45行會呼叫 kbuild 的 Makefile:
$(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules

之後 compat-wireless 的 Makefile 又會被呼叫一次,此時 KERNELRELEASE 已經被 kbuild 所定義,所以第5行到第18行會被執行。而做的事情就如同一般的 module Makefile 將 driver 的路徑加入 obj-$CONFIG_* 中,如第15行:
obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/


※

不過,DKMS 在 build module 時會自己傳入 KERNELRELEASE 這個參數,如在 /usr/sbin/dkms:function do_build():
local the_make_command=`echo $make_command | sed "s/^make/make KERNELRELEASE=${kernelver_array[0]}/"`


我們可以看到,在 compat-wireless 的 Makefile 中,當 KERNELRELEASE 變數已被設值時,並沒有 target 可以 build,必須是經由 kbuild 的 Makefile 來 make 才可以。

所以一個 workaround 是在 dkms.conf 中將 MAKE[0] 寫成 make -C /lib/modules/`uname -r`/build M=`pwd` modules。但是在這個例子中我們還必須先在 CLFAGS 中加入一些 define。直接呼叫kbuild的話,這些 CFLAGS 都沒設定,這樣並無法正確的 build 出 module。

所以,一個可行的辦法是將 Makefile 拆開,然後在 dkms.conf:MAKE[0] 中自行指定 Makefile,如:
make -f dkms.mk


雖然必須更改原始的 Makefile,但是卻可讓 DKMS 正確運作。

CONFIG_LOCALVERSION_AUTO和git describe

最近在編譯某家大廠的BSP時,發現kernel version在正常的tag之後被加了一大串東西:
include/config/kernel.release:1:2.6.32.11+drm33.2-16040-g98cebdd

2.6.32.11+drm33.2是Ubuntu Lucid kernel的version沒錯,但是後面的-16040-g98cebdd並不是Ubuntu kernel版號的一部份,看起來是像`git describe`的結果。

執行一下,果然沒錯:

$ git describe
v2.6.31-rc4-16040-g98cebdd

v2.6.31-rc4是某個tag,16040表示目前的HEAD是從tag v2.6.31-rc4之後第16040個commit,g98cebdd表示目前commit的git sha1前幾個值是98cebdd...。

而這個版號是因為 CONFIG_LOCALVERSION_AUTO=y 產生出來的。從LOCALVERSION_AUTO的文義有點難聯想到它的行為。

以下是完整的文件說明:


config LOCALVERSION_AUTO
bool "Automatically append version information to the version string"
default y
help
This will try to automatically determine if the current tree is a
release tree by looking for git tags that belong to the current
top of tree revision.

A string of the format -gxxxxxxxx will be added to the localversion
if a git-based tree is found. The string generated by this will be
appended after any matching localversion* files, and after the value
set in CONFIG_LOCALVERSION.

(The actual string used here is the first eight characters produced
by running the command:

$ git rev-parse --verify HEAD

which is done within the script "scripts/setlocalversion".)

Ubuntu kernel module使用的優先順序

在Ubuntu中,主要的kernel module來源大略有三種:

(1) 來自DKMS package:
會被安裝到 /lib/modules/`uname -r`/updates/

(2) Ubuntu kernel加入的driver:
會被安裝到 /lib/modules/`uname -r`/kernel/ubuntu/

(3) Linux kernel tree中原本就有的driver。

正常情況下,我們希望DKMS所安裝的kernel module在modprobe時有較高的優先順序,因為通常使用者是因為系統內建的driver無法正確工作而自行安裝DKMS的package。

而Linux Ubuntu Module是Ubuntu kernel自行加入所需的新或較新版本的driver,應該還是要比kernel tree內附的driver有較高的使用順序。

觀察 /etc/depmod.d/ubuntu.conf 便可發現這些目錄的使用順序都在這個設定檔案中被指定:

search updates ubuntu built-in

2010年3月19日 星期五

處理無release event熱鍵的新方法

Notebook的熱鍵(hotkey)常是由客製化過的EC(embedded controller) code來控制,而且沒有一個統一的標準,所以常常帶來了一些混亂。

熱鍵缺少了key release event就是很常見的情形。像是在Fujitsu Amilo和Samsung NC系列,很多型號都有這樣的問題。

因為沒有release event,所以會發生「只有第一次按有用」「只按一下降低音量的鍵,卻變成靜音」等奇怪的情況。

2.6.31之前的kernel會在AT keyboard驅動程式(atkbd.c)中加了許多DMI quirk和熱鍵的scan code,只要型號和scan code符合,atkbd會自動加入release event。

不過,在這麼一般的驅動程式中加入一堆DMI quirk,並不是一個好主意。所以在2.6.32 kernel,便在/sys下加入了一個可以由userspace控制的介面:
/sys/devices/platform/i8042/serio0/force_release


要讓某些scan code自動的產生出release event,只要把hotkey的scan code用逗號隔開,再寫入(echo + pipeline)這個檔案,之後kernel便會自動的幫這些scan code產生出release event。

對於一個distro來說,最好能夠收集這些有問題的型號和熱鍵的scan code,並且自動的偵測和設定。以Ubuntu而言,從Ubuntu Karmic之後,熱鍵便從HAL改為由udev來管理。所以在Ubuntu Lucid中,udev也加入了這個新功能:

將DMI quirk紀錄在此:
/lib/udev/rules.d/95-keyboard-force-release.rules


將熱鍵的scan code紀錄在此:
/lib/udev/keymaps/force-release/


在Ubuntu Lucid中,處理這類問題,就不須再更動、重編kernel,只要簡單的修改一些udev script即可。

2010年3月16日 星期二

top中數值的意義

us: user cpu time
sy: system cpu time
ni: user nice cpu time
id: idle cpu time
wa: io wait cpu time
hi: hardware irq (servicing hardware interrupts)
si: software irq (servicing software interrupts)
st: steal time (time in involuntary wait by virtual cpu while hypervisor is servicing another processor)

man vmstat
man mpstat

2010年3月15日 星期一

為什麼用startx啟動X-window時 suspend會失敗

When login from the console, libpam-ck-connector will create XDG_SESSION_COOKIE. While you run `startx`, In /etc/X11/Xsession.d/90consolekit, it checks the environment variable XDG_SESSION_COOKIE is already set and will not create a proper CK session.

Try to `unset XDG_SESSION_COOKIE` before `startx` to see if suspend/hibernate works.

2010年2月25日 星期四

檢查kernel coding style

在linux kernel中的scripts/checkpatch.pl不只可以用來檢查patch的coding style,也可以用來檢查c source的coding style:

scripts/checkpatch.pl --file *.c

2009年9月11日 星期五

Linux熱鍵的除錯技巧(1)

筆記型電腦的熱鍵(hotkey)應該可以名列linux的常見問題之一。這裡所謂的熱鍵指得是像Fn+F1、Fn+F2,或是有些筆記型電腦會有專門調整音量大小…等特定功能的鍵。主要因為硬體上常常是各家廠商做各家的,並沒有一套共同的標準,所以每家廠商,甚至每個型號都要特別處理。

這也造成了在linux kernel原始碼中,有著像asus-laptop.c、thinkpad_acpi.c…等,這類專為各大廠不同型號的筆記型電腦處理熱鍵的module,而每個module中又有可能要對每個型號對不同的處理。除了這些modules,甚至連atkbd.c中都有很多的quirk,來處理各種型號筆記型電腦上的熱鍵(forced release key event)。

※

一種常見的情況是:當按下熱鍵時,既收不到scancode、也收不到ACPI event,看起來就像是linux kernel完全無法從硬體收到任何訊息。但是熱鍵在Windows中是可以用的,所以硬體是正常的。這種情況真是讓人完全找不到頭緒可以從何下手來debug。

不過這樣的bug其實還是有跡可循,我們可先猜測熱鍵是由embedded controller(EC)控制的,利用下列的方法來確認:

首先先找出EC的GPE編號:
$ dmesg | grep EC
ACPI: EC: GPE = 0x11, I/O: command/status = 0x66, data = 0x62


看一下目前interrupt的數字:
$ cat /sys/firmware/acpi/interrupts/gpe11
10608 enabled


此時,按一下熱鍵,再看看interrupt的數字有無增加。如果interrupt的數字增加了,應該就可以判斷那個熱鍵是由EC控制的。

有時候EC也會送一些非熱鍵產生的interrupt,這就只能多靠眼力來觀察。

※

到這裡,我們就可以把責任歸咎於EC。因為理論上EC是必須要送出scancode或是ACPI event出來的。那麼EC又為什麼不送scancode或ACPI event出來呢?

在一些情況下,硬體製造商希望這個熱鍵的功能是必須安裝某個特定軟體才會啟動。像是某家廠牌的小筆電,必須對某個io port寫入一次,EC才會正確的送出某一個熱鍵的scancode出來。而這樣的「初始化」是寫在Windows平台上特定bundled的軟體中。Linux沒有這樣的軟體,所以熱鍵會無效。

此時我們可以回報原廠,請他們修改BIOS/EC code,讓熱鍵在Linux下也可以正常工作;如果我們知道EC初始化的方式(不過通常一般使用者不會知道),也可以在某支驅動程式中來初始化EC。而另外的作法是寫一個驅動程式,透過kernel所提供的EC的介面來偵測EC的interrupt。