好久沒來了!寫點東西.關於linux 2.6下面的鍵盤驅動的實現.
2.6核心採用"input sub system" 的概念.將輸入驅動分成三塊: driver,input core和Event handler. "一個輸入事件,如滑鼠移動,鍵盤按鍵按下,joystick的移動等等通過 Driver -> InputCore -> Eventhandler -> userspace 的順序到達使用者空間傳給應用程式。"
關於輸入子系統詳細的文章有一個老兄寫了一篇:
http://blog.csdn.net/colorant/archive/2007/04/12/1561837.aspx
在這裡我膚淺得講一下如何?一個驅動.todo
本文
2.6輸入子系統使得使用者空間可以通過字元裝置介面毫無遺漏的獲得原始的輸入訊息。比如說有些智能滑鼠,除了座標滾球,三鍵,滾輪之外還有其他的輸入裝置,,比如控制系統音量的按鈕.
如何註冊裝置
/* *Input interface, not finished yet */
int key,code; button_dev = input_allocate_device(); /*static struct input_dev *button_dev defined outside*/ init_input_dev(button_dev); set_bit(EV_KEY,button_dev->evbit); //@set_bit(EV_REP,button_dev->evbit); //repeat for(key=0;key<16;key++) set_bit(keypad_keycode[key],button_dev->keybit); button_dev->name = PCA9554_DRV_NAME; button_dev->id.bustype = BUS_HOST; input_register_device(button_dev); |
如上述代碼所示,首先分配一個輸入裝置,之後對其進行初始化,然後配置參數. “set_bit(EV_KEY,button_dev->evbit);”將該輸入裝置定義為鍵盤輸入,這樣input core在分發訊息的時候會將其發送到keyboard event handler.
接著就是初始化鍵盤定義,這裡keybit是由若干個long型變數組成的數組,我所用的kernel直至最大按鍵數目為0x1ff.
for(key=0;key<16;key++) set_bit(keypad_keycode[key],button_dev->keybit); |
我的開發板上有16個按鍵,因為項目是播放器,所以我對其作了定義:
int keypad_keycode[] = { KEY_UP, KEY_DOWN, KEY_A, KEY_B, // 1 - 4 KEY_LEFT, KEY_RIGHT, KEY_C, KEY_D, // 5 - 8 KEY_PLAYPAUSE,KEY_PLAY,KEY_NEXTSONG,KEY_VOLUMEUP, // 9 - 12 KEY_CANCEL,KEY_OK,KEY_PREVIOUSSONG,KEY_VOLUMEDOWN, // 13 - 16 KEY_UNKNOWN, }; |
鍵盤定義
在input.c的input_event函數中會對keybit進行判斷,確定某個按鍵對應的位是否被開啟,否則不予上傳索引值.
case EV_KEY: printk("haigang;:%s: code:%d,value=%d/n",__FUNCTION__,code,value); if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value){ printk("haigang:%s: code too big/n",__FUNCTION__,code); return; } if (value == 2) break; change_bit(code, dev->key); if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) { dev->repeat_key = code; mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); } break; |
input_event部分代碼
如何傳送輸入索引值比較簡單,只需要使用 函數void input_event即可,該函數定義
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
在include/linux/input.h中對該函數作了封裝
static inline void input_report_key(struct input_dev *dev, unsigned int code, int value) { input_event(dev, EV_KEY, code, !!value); } |
這裡code是索引值,value應該是鍵盤狀態,按下或者釋放(僅是猜測,有待考證)
我的驅動中的建值傳輸代碼,當索引值是0x16時候,表示鬆開鍵盤事件
unsigned char key; static unsigned char oldKey=0x16; key = pca9554_readKey();
//@printk("KEY:%d/n",key); if(key!=0x16){ input_report_key(button_dev,keypad_keycode[key],1); input_sync(button_dev); }else{ input_report_key(button_dev,keypad_keycode[oldKey],0); input_sync(button_dev); }
set_irq_type(IRQ_KEYPAD,IRQT_FALLING); s3c_gpio_cfgpin(S3C_GPF4,S3C_GPF4_EINT4);/*reconfigure the GPF4 as EINT4*/
oldKey=key; |