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。