Tiny210v2底板上面有八个按键,但是官方只提供了该按钮的驱动,并没有实现输入子系统,使得板上的八个按钮没有任何作用。这里就通过向内核添加该buttons的输入子系统驱动,使该八个按钮实现如普通键盘的键值功能,实现能上下左右,以及确认等功能,就像手机的音量键、关机键一样。
内核:采用友善提供的linux-3.0.8
编译环境:ubuntu 13.10
个人原创,转载请注明原文链接:
http://www.embbnux.com/2013/11/20/tiny210_kernel_button_input_system/
参考:
http://blog.csdn.net/girlkoo/article/details/8736243
一、首先搞清楚该8个按键的对应引脚和中断
查得为:
S5PV210_GPH2(0) ; EINT16
S5PV210_GPH2(1) ; EINT17
S5PV210_GPH2(2) ; EINT18
S5PV210_GPH2(3) ; EINT19
S5PV210_GPH3(0) ; EINT24
S5PV210_GPH3(1) ; EINT25
S5PV210_GPH3(2) ; EINT26
S5PV210_GPH3(3) ; EINT27
规定键值依次为: UP ; DOWM ; LEFT ; RIGHT ; SPACE ; i ; ESC ; ENTER ;
二、内核修改
首先在
/drivers/input/keyboard/ 下新建button210_key.c
#include <linux/types.h> #include <linux/module.h> #include <linux/input.h> #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/gpio.h> static struct input_dev *buttons_dev; static struct timer_list timer; struct button_desc* button_desc = NULL; struct button_desc{ char* name; unsigned int pin; unsigned int irq; unsigned int val; }; static struct button_desc buttons_desc[8] = { [0] = { .name = "S1", .pin = S5PV210_GPH2(0), .irq = IRQ_EINT(16), .val = KEY_UP, }, [1] = { .name = "S2", .pin = S5PV210_GPH2(1), .irq = IRQ_EINT(17), .val = KEY_DOWN, }, [2] = { .name = "S3", .pin = S5PV210_GPH2(2), .irq = IRQ_EINT(18), .val = KEY_LEFT, }, [3] = { .name = "S4", .pin = S5PV210_GPH2(3), .irq = IRQ_EINT(19), .val = KEY_RIGHT, }, [4] = { .name = "S5", .pin = S5PV210_GPH3(0), .irq = IRQ_EINT(24), .val = KEY_SPACE, }, [5] = { .name = "S6", .pin = S5PV210_GPH3(1), .irq = IRQ_EINT(25), .val = KEY_I, }, [6] = { .name = "S7", .pin = S5PV210_GPH3(2), .irq = IRQ_EINT(26), .val = KEY_ESC, }, [7] = { .name = "S8", .pin = S5PV210_GPH3(4), .irq = IRQ_EINT(27), .val = KEY_ENTER, }, }; static void timer_function(unsigned long data){ if(button_desc == NULL) return; if(gpio_get_value(button_desc->pin)){ input_event(buttons_dev, EV_KEY, button_desc->val, 0); } else{ input_event(buttons_dev, EV_KEY, button_desc->val, 1); } input_sync(buttons_dev); } static irqreturn_t irq_handler(int irq, void *devid){ button_desc = (struct button_desc*)devid; mod_timer(&timer, jiffies + HZ/100); return IRQ_RETVAL(IRQ_HANDLED); } static int buttons_init(void){ int i; buttons_dev = input_allocate_device(); if(buttons_dev == NULL){ printk(KERN_ERR "Error: allocate input device failed!n"); return -ENOMEM; } __set_bit(EV_KEY, buttons_dev->evbit); __set_bit(EV_REP, buttons_dev->evbit); __set_bit(KEY_UP, buttons_dev->keybit); __set_bit(KEY_DOWN, buttons_dev->keybit); __set_bit(KEY_LEFT, buttons_dev->keybit); __set_bit(KEY_RIGHT, buttons_dev->keybit); __set_bit(KEY_SPACE, buttons_dev->keybit); __set_bit(KEY_I, buttons_dev->keybit); __set_bit(KEY_ESC, buttons_dev->keybit); __set_bit(KEY_ENTER, buttons_dev->keybit); printk("1n"); if(input_register_device(buttons_dev)){ goto error_1; } printk("2n"); init_timer(&timer); timer.function = timer_function; add_timer(&timer); printk("3n"); for(i = 0; i != 8; ++i){ if(request_irq(buttons_desc[i].irq, irq_handler, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, buttons_desc[i].name, &buttons_desc[i])){ goto error_2; } } printk("4n"); return 0; error_2: for(--i; i >= 0; --i){ free_irq(buttons_desc[i].irq, &buttons_desc[i]); } input_unregister_device(buttons_dev); error_1: input_free_device(buttons_dev); return -EBUSY; } static void buttons_exit(void){ int i; for(i = 0; i != 8; ++i){ free_irq(buttons_desc[i].irq, &buttons_desc[i]); } input_unregister_device(buttons_dev); input_free_device(buttons_dev); } module_init(buttons_init); module_exit(buttons_exit); MODULE_LICENSE("GPL");
修改该目录下的Kconfig文件,添加
config KEYBOARD_BUTTON210 tristate "Buttons on TINY210 board" help UP ; DOWM ; LEFT ; RIGHT ; SPACE ; i ; ESC ; ENTER ;
修改该目录的Makefile文件,添加
obj-$(CONFIG_KEYBOARD_BUTTON210) += button210_key.o