输入子系统(二)

1、程序
在上一节中介绍了Linux内核中的输入子系统的框架,在对输入子系统框架有了大概的了解之后,这一节来实际的编写代码,加深对输入子系统的理解,
在写程序之前先来梳理一下,使用输入子系统编写程序的步骤

1、最开始肯定是要注册一个代表物理硬件的input_device,这样的话,在内核成功识别之后才能对我们需要操作
	的设备进行操作,
2、提供对应的硬件操作函数	

可以看出,在使用这个框架来编写程序之后,我们需要做的事情其实就已经很少了,下面来完成使用开发板上的按键模拟键盘的效果,只写关键性的代码

//定义全局变量
struct pin_desc{
 int irq;
 char *name;
 unsigned int pin;
 unsigned int key_val;
};
struct pin_desc pins_desc[4] = {
 {IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},
 {IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},
 {IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},
 {IRQ_EINT19, "S5",  S3C2410_GPG11, KEY_LEFTSHIFT},
};
static struct input_dev *buttons_dev;
static struct pin_desc *irq_pd;
static struct timer_list buttons_timer;
//入口函数
static int buttons_init(void)
{
	 /* 1. 分配一个input_dev结构体 */
 	buttons_dev = input_allocate_device();
 	 /* 2. 设置 */
	 /* 能产生哪类事件(按键类和重复类) */
 	set_bit(EV_KEY, buttons_dev->evbit);
 	set_bit(EV_REP, buttons_dev->evbit);
 	 /* 2.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */
	 set_bit(KEY_L, buttons_dev->keybit);
	 set_bit(KEY_S, buttons_dev->keybit);
	 set_bit(KEY_ENTER, buttons_dev->keybit);
	 set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);
	  /* 3. 注册 */
	 input_register_device(buttons_dev);
 	 /* 4. 硬件相关的操作,使用定时器来消抖 */
	 init_timer(&buttons_timer);
 	buttons_timer.function = buttons_timer_function;
 	add_timer(&buttons_timer);
 	//注册中断
 	 for (i = 0; i < 4; i++)
	 {
	  request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
	 }
	 return 0;
}
//出口函数
static void buttons_exit(void)
{
	 for (i = 0; i < 4; i++)
	 {
	  free_irq(pins_desc[i].irq, &pins_desc[i]);
	 }
	  del_timer(&buttons_timer);
	 input_unregister_device(buttons_dev);
	 input_free_device(buttons_dev); 
}
//按键中断函数,在该函数里将定时器的超时时间进行延迟
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
	 /* 10ms后启动定时器 */
	 irq_pd = (struct pin_desc *)dev_id;
	 mod_timer(&buttons_timer, jiffies+HZ/100);
	 return IRQ_RETVAL(IRQ_HANDLED);
}
//真正要做的事情放在定时器的处理函数中
static void buttons_timer_function(unsigned long data)
{
	 struct pin_desc * pindesc = irq_pd;
	 unsigned int pinval;
  	if (!pindesc)
  		return;
   	pinval = s3c2410_gpio_getpin(pindesc->pin);
    if (pinval)
 	{
 	   /*
 	   	使用input_event上报事件 
 	   	松开 : 最后一个参数: 0-松开, 1-按下
 	    */
	  input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);
	  //表示这个事件已经处理完毕
	  input_sync(buttons_dev);
	}
	else 
	{
		  /* 按下 */
		  input_event(buttons_dev, EV_KEY, pindesc->key_val, 1);
		  input_sync(buttons_dev);
	}

2、总结
和上一节分析的一样,在使用输入子系统的时候需要人为的注册input_handler和input_device,但是这里只注册了input_device,这是因为在内核里已经有了能支持按键的Input_handler了,
在这里插入图片描述
在evdev.c中注册的input_handler来看,它的id_table如上所示,表示可以匹配所有的设备,那么,我们注册的按键类设备肯定可以被它所匹配到,匹配成功之后调用evdev.connect函数创建设备,可以在开发板上ls /dev/evevt * 命令来查看,在加载驱动模块之前,该目录下只有一个输入设备,加载完驱动之后,目录下又多了一个设备,之后就可以进行测试了,好了,今天的程序就写到这里。

发布了33 篇原创文章 · 获赞 2 · 访问量 1015

猜你喜欢

转载自blog.csdn.net/weixin_41791581/article/details/103543354
今日推荐