GPIO按键属于是系统的一种设备,挂载到platform总线上,其原理请参考Android学习之platform开发流程,以下直接介绍其在imx53qsb上的应用。
1 Button设备的定义和注册
1.1 Button设备的定义
Kernel-imx\arch\arm\mach-mx5\Mx53_loco.c#L690
#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), //edit by havery for menu key
GPIO_BUTTON(USER_UI2, KEY_HOME, 1, "menu", 0), //key 与。code有关,与。desc无关
};
static struct gpio_keys_platform_data loco_button_data = {
.buttons = loco_buttons,
.nbuttons = ARRAY_SIZE(loco_buttons),
};
static struct platform_device loco_button_device = {
.name = "gpio-keys",
.id = -1,
.num_resources = 0,
.dev = {
.platform_data = &loco_button_data,
}
};
1.2 Button设备的注册
Kernel-imx\arch\arm\mach-mx5\Mx53_loco.c#L713
static void __init loco_add_device_buttons(void)
{
platform_device_register(&loco_button_device);
}
loco_add_device_buttons()其在mxc_board_init()调用。
2 Button 驱动的定义和注册
2.1 Button驱动的定义
Kernel-imx\drivers\input\keyboard\Gpio_keys.c#L589
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &gpio_keys_pm_ops,
#endif
}
};
2.2 Button驱动的注册
Kernel-imx\drivers\input\keyboard\Gpio_keys.c#L601
static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver);
}
module_init(gpio_keys_init);
platform_driver_register之后,将调用.probe函数:
Kernel-imx\drivers\input\keyboard\Gpio_keys.c#L417
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata;
struct device *dev = &pdev->dev;
struct input_dev *input;
int i, error;
int wakeup = 0;
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
pdata->nbuttons * sizeof(struct gpio_button_data),
GFP_KERNEL);
input = input_allocate_device();
if (!ddata || !input) {
dev_err(dev, "failed to allocate state\n");
error = -ENOMEM;
goto fail1;
}
ddata->input = input;
ddata->n_buttons = pdata->nbuttons;
mutex_init(&ddata->disable_lock);</