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