#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");