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