输入设备框架—驱动层—完整的代码工程

来源:互联网 发布:出租女友网站源码 编辑:程序博客网 时间:2024/05/16 23:36

输入设备驱动/***********所有的函数结构体定义都在linux/input.h*****************/转载请标明出处,原文地址http://blog.csdn.net/oyhb_1992/article/details/77622112#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/input.h>#include <linux/interrupt.h>#include <mach/irqs.h>#include <linux/gpio.h>#include <mach/input.h>/*测试,可以将开发板上的系统的当前终端重定向为标准输入以测试*输入命令  #exec 0</dev/tty1*/#define DEVNAME "ldm_keyinput"struct ldm_info{struct input_dev *dev;//输入设备描述结构}//自定义一个描述按键的结构体struct key_info{   const char *name;   //按键名unsigned int irqno;  //按键中断号unsigned int keybit;//键盘按键对应的编码codeunsigned key_gpio;//管脚号,来自mach/gpio.h}//按键L,S,回车,shift,将开发板上的四个按键模拟为键盘的L,S,回车,shift四个按键static struct key_info key[]={{"KEY0",IRQ_EINT(26),KEY_L,EXYNOS4_GPX3(2)},{"KEY1",IRQ_EINT(27),KEY_S,EXYNOS4_GPX3(3)},{"KEY2",IRQ_EINT(28),KEY_ENTER,EXYNOS4_GPX3(4)},{"KEY3",IRQ_EINT(29),KEY_LEFTSHIFT,EXYNOS4_GPX3(5)}}struct ldm_info ldm;//输入设备描述结构static irqreturn_t key_handler(int irqno, void *arg){struct key_info*info = (struct key_info *)(arg)//向应用层发送按键类型事件,其中input_report_key的value//参数,按下是1,抬起是0,而硬件4个按键抬起是1高电平int is_key_up = gpio_get_value(info->key_gpio);input_report_key(ldm.dev,info->keybit,!is_key_up);input__sync(ldm.dev);//哨兵事件,告诉应用层表示这个事件已经发送完成return IRQ_HANDLER;}static int test_init(void){int ret,i=0;printk("%s: %s\n",__FUNCTION__,__FILE__);//创建input_dev对象ldm.dev=input_allocate_device();if(!ldm.dev){printk(KERN_ERR"input_allocate_device failed\n");ret = -ENOMEM; //内存分配失败错误码goto err_input_allocate_device;}//填充input_dev对象ldm.dev->name= DEVNAME;//注册本设备支持的事件类型-按键,以及是否支持连发,位图操作set_bit(EV_KEY,ldm.dev->evbit);set_bit(EV_REP,ldm.dev->evbit);//按键支持连按repeat//注册本设备支持的按键码for(i=0;i<ARRAY_SIZE(key);++i){set_bit(key[i].keybit,ldm.dev->kevbit,);}//注册输入设备ret=input_register_device(ldm.dev);if(ret<0){printk(KERN_ERR"input_register_device failed\n");goto err_input_register_device;}//硬件初始化for(i=0;i<ARRAY_SIZE(key);++i){ret=request_irq(key[i].irqno,key_handler,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,key[i].name,key+i);//将中断的所有信息通过key+i传递给中断函数                 //request_irq函数用法:http://blog.csdn.net/oyhb_1992/article/details/77341782if(ret<0){printk(KERN_ERR"request_irq failed\n");goto err_request_irq;}gpio_request(key[i].key_gpio, key[i].name);//申请GPIO口,获取管脚电平状态 //将引脚设为输出//gpio_direction_output(key[i].key_gpio, 1);}return 0;//出错后反向注销err_request_irq:for(i=i-1;i>0;--i){gpio_free(key[i].key_gpio);free_irq(key[i].irqno,key+i);}input_unregister_device(ldm.dev);err_input_register_device:input_free_device(ldm.dev);err_input_allocate_device:return ret;}static void test_exit(void){printk("%s: %s\n",__FUNCTION__,__FILE__);int i = ARRAY_SIZE(key) - 1; for (; i >=0; i--) {          gpio_free(key[i].key_gpio);//释放GPIO口  free_irq(key[i].irqno,key+i);    }  //input_free_device(ldm.dev);input_unregister_device(ldm.dev);}代码测试#insmod ldm.ko#cat /proc/bus/input/devices  查看我们申请的输入设备#cat /proc/interrupts   查看我们申请的中断号输入命令,重定向后,开发板的输入就不再是标准键盘了,而是我们自定义的四个按键了L,S,shift,ENTER#exec 0</dev/tty1





阅读全文
1 0