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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章