现在的位置: 首页 > 综合 > 正文

键盘驱动的原理

2013年12月07日 ⁄ 综合 ⁄ 共 2052字 ⁄ 字号 评论关闭

键盘驱动的设置

1,一般要初始化矩阵键盘的行数和列数,设置矩阵的扫描驱动线的开始gpio,设置矩阵的扫描输入线的开始gpio,利用循环分别对每个扫描驱动线的gpio初始化为输出脚,利用循环分别对每个扫描输入线的gpio初始化为输入脚。

2, 在模块加载函数中注册输入设备。

注册输入设备的函数为:

int input_register_device(struct input_dev *dev);

3,在probe函数

申请一个输入设备,告知input子系统它可以报告的事件。

设备驱动通过set_bit()告诉input子系统它支持哪些事件,如下所示:

set_bit(EV_KEY, button_dev.evbit);

初始化键盘的映射表,申请键盘中断,打开中断。

4,实现中断处理函数,中断处理函数是响应中断,读出键盘的按键缓冲区的数据,对每个比特检查,看那个按键按下,将扫描码转换为按键码通过

input_report_key() 报按键

后面跟input_sync()用于事件同步,它告知事件的接收者驱动已经发出了一个完整的报告。

 

getevent & sendevent
getevent监控当前的事件,鼠标事件,按键事件,拖动滑动等
在命令行通过pc键盘输入getevent可以监控当前的事件
# getevent
getevent
add device 1: /dev/input/event0
  name: "qwerty2"
/dev/input/event0: 0001 001e 00000001
/dev/input/event0: 0001 001e 00000000

其中/dev/input/event0是device的名字 0001是type, 001e是键码, 最后一个根据type不同而不同
比如上面的倒数第二条就是按下a键的keydown,最后一个是按下a的keyup
具体的type,code,value的定义可以在源码/frameworks/base/core/java/android/view/KeyEvent.java中找到

sendevent发送时间,格式和上面的一样,需要注意的是在get中code显示的是十六进制,而send中需要用十进制,例如

# sendevent /dev/input/event0 1 5 1
这个命令就是发送数字4的keydown消息,所以在屏幕上就会一直打印出很多个4(因为没有发送keyup)

http://linux-qcm-msm.sourcearchive.com/documentation/2.6.31-800.2/rpc__server__handset_8c-source.html

static const uint32_t hs_key_map[] = {
 KEY(HS_PWR_K, KEY_POWER),
 KEY(HS_END_K, KEY_END),
 KEY(HS_STEREO_HEADSET_K, SW_HEADPHONE_INSERT),
 KEY(HS_HEADSET_SWITCH_K, KEY_MEDIA),
 0
};

static int hs_find_key(uint32_t hscode)
{
      int i, key;

      key = KEY(hscode, 0);

      for (i = 0; hs_key_map[i] != 0; i++) {
            if ((hs_key_map[i] & 0xff000000) == key)
                  return hs_key_map[i] & 0x00ffffff;
      }
      return -1;
}

static void report_hs_key(uint32_t key_code, uint32_t key_parm)
{
 int key, temp_key_code;

 if (key_code == HS_REL_K)
  key = hs_find_key(key_parm);
 else
  key = hs_find_key(key_code);

 temp_key_code = key_code;

 if (key_parm == HS_REL_K)
  key_code = key_parm;

 switch (key) {
 case KEY_POWER:
 case KEY_END:
 case KEY_MEDIA:
  input_report_key(hs->ipdev, key, (key_code != HS_REL_K));
  break;
 case SW_HEADPHONE_INSERT:
  report_headset_switch(hs->ipdev, key, (key_code != HS_REL_K));
  break;
 case -1:
  printk(KERN_ERR "%s: No mapping for remote handset event %d/n",
     __func__, temp_key_code);
  return;
 }
 input_sync(hs->ipdev);

 

抱歉!评论已关闭.