arch/arm/mach-s5pv210/button-x210.c
static int __init s3c_button_init(void) { platform_device_register(&s3c_device_button); return platform_driver_register(&s3c_button_device_driver); } static void __exit s3c_button_exit(void) { platform_driver_unregister(&s3c_button_device_driver); platform_device_unregister(&s3c_device_button); } module_init(s3c_button_init); module_exit(s3c_button_exit);
static struct platform_driver s3c_button_device_driver = { .probe = s3c_button_probe, .remove = s3c_button_remove, .suspend = s3c_button_suspend, .resume = s3c_button_resume, .driver = { .name = "s3c-button", .owner = THIS_MODULE, } }; static struct platform_device s3c_device_button = { .name = "s3c-button", .id = -1, };
这里不做过多解释,请参考platform平台总线工作原理
s3c_button_probe
/* gph0_1 (power) */ ret = gpio_request(S5PV210_GPH0(1), "GPH0"); if(ret) printk("button-x210: request gpio GPH0(1) fail"); s3c_gpio_setpull(S5PV210_GPH0(1), S3C_GPIO_PULL_UP); s3c_gpio_cfgpin(S5PV210_GPH0(1), S3C_GPIO_SFN(0)); s3c_button_history[0] = gpio_get_value(S5PV210_GPH0(1)); ...
申请按键所对应的gpio并进行配置
input = input_allocate_device(); if(!input) return -ENOMEM;
static struct input_dev * input;
调用核心层提供的接口input_allocate_device为struct input_dev类型的变量input分配内存并进行一些泛型初始化
set_bit(EV_KEY, input->evbit); for(i = 0; i < MAX_BUTTON_CNT; i++) set_bit(s3c_Keycode[i], input->keybit);
static int s3c_Keycode[MAX_BUTTON_CNT] = {KEY_POWER, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_A, KEY_B};
设置设备所支持的事件类型EV_KEY和其对应支持的code,这里没有调用核心层分析中讲过的input_set_capability接口
input->name = "s3c-button"; input->phys = "s3c-button/input0"; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; input->keycode = s3c_Keycode;
一些成员初始化
if(input_register_device(input) != 0) { printk("s3c-button input register device fail!!\n"); input_free_device(input); return -ENODEV; }
调用核心层提供的接口input_register_device向核心层注册input device
/* Scan timer init */ init_timer(&timer); timer.function = s3cbutton_timer_handler; timer.expires = jiffies + (HZ/100); add_timer(&timer);
static struct timer_list timer;
初始化并启动一个内核定时器,该定时器到时后会去执行s3cbutton_timer_handler函数,定时时间为jiffies + (HZ/100)为10ms。
该定时器的作用主要是定时去轮训检测按键的gpio的电平是否被按下
s3cbutton_timer_handler
按键没有被按下:
input_report_key(input, s3c_Keycode[0], 0);
按键被按下:
input_report_key(input, s3c_Keycode[0], 1);
mod_timer(&timer,jiffies + HZ/100);
内核定时器为单次定时器,需要更新定时器重新设置计时时间
input_report_key
该函数定义在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); } static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value) { input_event(dev, EV_REL, code, value); } static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value) { input_event(dev, EV_ABS, code, value); } ...
类似的input_report_rel函数和input_report_abs函数等,其内部都是调用了input_event函数,只是参数不同
input_event
input_handle_event
input_pass_event
handle->handler->event