linux 2.6 輸入子系統之鍵盤驅動的實現


2.6內核採用"input sub system" 的概念.將輸入驅動分成三塊: driver,input coreEvent handler.

比如:"一個輸入事件,如鼠標移動,鍵盤按鍵按下等等通過 Driver -> InputCore -> Eventhandler -> userspace的順序到達用戶空間傳給應用程序。"


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.cinput_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;


 

發佈了14 篇原創文章 · 獲贊 5 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章