键盘驱动的设置
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可以监控当前的事件# geteventgeteventadd 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)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);