#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <asm-generic/errno-base.h>
#include <linux/input.h>
#include <linux/of_irq.h>
//描述按键信息的数据结构
struct key_resource {
char *name;
int irq;
int gpio;
int code;
};
//保存按键的硬件信息,全局化
static struct key_resource *pKeyData = NULL;
//定义一个按键去抖动的定时器
static struct timer_list key_timer;
//新建一个输入子系统的设备结构
static struct input_dev *keys_input;
//定义初始化按键硬件信息的对象
static struct key_resource key_info[] = {
{
.name = "KEY_ENTER",
//.irq = IRQ_EXT0,
.gpio = NUC970_PG14,
.code = KEY_ENTER
},
{
.name = "KEY_CANCEL",
//.irq = IRQ_EXT0,
.gpio = NUC970_PG13,
.code = KEY_CANCEL
},
{
.name = "KEY_UP",
//.irq = IRQ_EXT0,
.gpio = NUC970_PG12,
.code = KEY_UP
},
{
.name = "KEY_DOWN",
//.irq = IRQ_EXT0,
.gpio = NUC970_PG11,
.code = KEY_DOWN
},
};
//中断处理函数
static irqreturn_t key_isr(int irq, void *dev)
{
//获取按键信息
pKeyData = (struct key_resource *)dev;
//启动定时器
mod_timer(&key_timer, msecs_to_jiffies(10));
return IRQ_HANDLED;
}
//定时器的超时处理函数
static void key_timer_function(unsigned long data)
{
unsigned int pin_val;
if (NULL == pKeyData) {
return;
} else {
printk("key:%s\n", pKeyData->name);
pin_val = gpio_get_value(pKeyData->gpio);
if (!pin_val) {
input_event(keys_input, EV_KEY, pKeyData->code, 0);
input_sync(keys_input);
}
}
}
static int key_init(void)
{
int i,ret,irqno, cnt;
//分配一个keys_input结构体
keys_input = input_allocate_device();
if (!keys_input)
{
printk("%s %s LINE: %d alloc input failed!!!\n",__FILE__, __FUNCTION__, __LINE__);
return -ENOMEM;
}
//设置输入事件类型
set_bit(EV_KEY, keys_input->evbit);
set_bit(EV_REP, keys_input->evbit);
//输入事件类型的哪一种
set_bit(KEY_ENTER, keys_input->keybit);
set_bit(KEY_CANCEL, keys_input->keybit);
set_bit(KEY_UP, keys_input->keybit);
set_bit(KEY_DOWN, keys_input->keybit);
//注册
ret = input_register_device(keys_input);
if (ret) {
printk("%s %s LINE:%d failed to register input device\n",__FILE__, __FUNCTION__, __LINE__);
return -1;
}
cnt = 0;
for (i=0; i < ARRAY_SIZE(key_info); i++) {
ret = gpio_request(key_info[i].gpio, key_info[i].name);
if (ret) {
printk("Request GPIO = %d failed, ret = %d\n", key_info[i].gpio, ret);
goto fail;
}
irqno = gpio_to_irq(key_info[i].gpio);
key_info[i].irq = irqno;
ret = request_irq(key_info[i].irq, key_isr, IRQF_TRIGGER_FALLING,
key_info[i].name, &key_info[i]);
if (ret) {
printk("GPIO = %d, request irq failed, ret = %d\n", key_info[i].gpio, ret);
goto fail;
}
cnt++;
}
init_timer(&key_timer);
key_timer.function = key_timer_function;
printk("Add ZKS Key SUCCESSS!!!");
return 0;
fail:
input_free_device(keys_input);
for (i =0; i < cnt; i++) {
gpio_free(key_info[i].gpio);
free_irq(key_info[i].irq, &key_info[i]);
}
return ret;
}
static void key_exit(void)
{
int i;
input_free_device(keys_input);
for (i = 0; i < ARRAY_SIZE(key_info); i++) {
gpio_free(key_info[i].gpio);
free_irq(key_info[i].irq, &key_info[i]);
}
}
module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");