平台:MX53_QSB开发板
MX53_QSB开发板上一起有四个按键,分别为RESET,POWER,USER1,USER2。其中RESET为纯硬件复位按键,无须软件控制。POWER,USER1,USER2三个按键均需要程序控制。默认BSP包中将三个按钮全设置为上升和下降沿触发,当系统起来后,按下POWER键,进入睡眠状态,这时再按下POWER键唤醒时,系统系统被唤醒,但是一旦手松下,又触发了POWER键的中断,系统又睡下去了。在进入睡眠状态后,只有按USER1和USER2这两个键,才能正常唤醒。因此,这里有BUG需修复。
按键驱动有两个,一个为矩阵键盘驱动,路径为:
\drivers\input\keyboard\mxc_keyb.c
一个为GPIO接口的键盘驱动,路径为:
\drivers\input\keyboard\gpio_keys.c
前者用于多按键的情况,如果按键比较少,后者就可以了,一般情况下,android系统只需几个按键就可以了,所以大多数情况下,都是使用的gpio_keys.c。下面我们将详细分析该驱动的工作流程。
在module_init函数中,在总线上注册名为gpio-keys的驱动,这时将夫在总线上查找是否存在同名的设备。系统初始化时,mx53_loco.c中,mxc_board_init函数已调用了按键初始化函数loco_add_device_buttons(),同时pdev的数据结构体中定义了按键的相关信息如下:
#define GPIO_BUTTON(gpio_num, ev_code, act_low,descr, wake) \
{ \
.gpio = gpio_num, \
.type = EV_KEY, \
.code = ev_code, \
.active_low = act_low, \
.desc = "btn " descr, \
.wakeup = wake, \
}
static struct gpio_keys_button loco_buttons[] = {
GPIO_BUTTON(MX53_nONKEY,KEY_POWER, 1, "power", 0),
GPIO_BUTTON(USER_UI1,KEY_BACK, 1, "back", 0),
GPIO_BUTTON(USER_UI2,KEY_HOME, 1, "home", 0),
};
static struct gpio_keys_platform_dataloco_button_data = {
.buttons = loco_buttons,
.nbuttons = ARRAY_SIZE(loco_buttons),
};
可见,结构体定义了三个GPIO,分别为power,back以及home。注意GPIO_BUTTON函数中的实参,第一个为对应的GPIO,纯硬件特性,第二个为按键的键值,在linux/input.h中定义:
#defineKEY_POWER 116
#defineKEY_HOME 102
#defineKEY_BACK 158
第三个参数为1,表明按下去为1,抬起为0;第四个参数为按键名称描述,无关紧要;第5个参数为wakeup,看名称好像与休眠唤醒有关,实际测试修改为1后,没有发现有什么异常。这几个参数是后续添加新的按键,或者更改按键功能的关键。
再回到gpio-keys.c中,找到同名设备后,探测函数gpio_keys_probe得到执行,调用input_allocate_device函数创建一个input设备,再通过一个for循环,调用gpio_keys_setup_key和input_set_capability函数,设置上表中列出的三个IO口的中断函数以及按键功能。后面用到了sysfs_create_group函数创建了基于sys系统的文件属性组,具体可以在?sys/devices/platform/gpio-keys目录下找到gpio_keys_attr_group结构体中attrs组对应的gpio_keys_attrs结构体中的几个属性文件,gpio_keys_attrs结构体描述如下:
static struct attribute *gpio_keys_attrs[] = {
&dev_attr_keys.attr,
&dev_attr_switches.attr,
&dev_attr_disabled_keys.attr,
&dev_attr_disabled_switches.attr,
NULL,
};
dev_attr_disabled_keys和dev_attr_disabled_switches在前面做了如下声明:
static DEVICE_ATTR(disabled_keys, S_IWUSR |S_IRUGO,
gpio_keys_show_disabled_keys,
gpio_keys_store_disabled_keys);
static DEVICE_ATTR(disabled_switches, S_IWUSR |S_IRUGO,
gpio_keys_show_disabled_switches,
gpio_keys_store_disabled_switche