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

输入设备驱动
/***********所有的函数结构体定义都在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;//键盘按键对应的编码code
	unsigned 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/77341782
		if(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








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值