Linux驱动之input子系统

一、何为输入子系统,有什么作用

1.input子系统

linux内核中已经实现了一个子系统,它在内核驱动的实现是:

  1. 注册了主设备(13已经被它占用了),分配了1024个次设备号
  2. 它注册了class类,实现了里面的fops功能
  3. 但是就是没有注册device也就是节点(一个也没有)这就是留给驱动工程师要做的。(注册的device在/dev/input下自己判断是哪一个)
struct class input_class = {
	.name = "input",
	.devnode = input_devnode,
};
.....
.....
err = class_register(&input_class);

err = input_proc_init();

err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),INPUT_MAX_CHAR_DEVICES, "input");//INPUT_MAX_CHAR_DEVICES=1024

2.功能

它内核实现了各种fops,只需要驱动层发送指定的信号,然后应用层可以直接read struct input_event结构体,然后用户就可以在应用空间用switch判断是哪种输入,又对应哪个,是什么值等信息,然后进行处理。

这大大减轻了驱动工程师的工作,复杂的各种信号分情况处理就变得很简单了。

二、编写流程

//注册
    struct input_dev *inputdev;	
    //1.申请一个input_dev
    inputdev = input_allocate_device();
    //2.自己初始化
    inputdev->name = "inputdev0";
    inputdev->evbit[0] = BIT_MASK(EV_KEY);//设置为按键类输入
    input_set_capability(inputdev, EV_KEY, KEY_0);//设置按键类中的key0
    //3.注册inputdev
    input_register_device(inputdev);
//发送数据
    input_event(inputdev, EV_KEY, KEY_0, value);
    //同步停止发送
    input_sync(inputdev);
//注销与释放
    /* 释放 input_dev */
    input_unregister_device(inputdev);//注销
    input_free_device(inputdev);//释放

三、程序

1.driver

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/of.h>
#include <linux/timer.h>

#include <linux/input.h>

//不借助硬件
//1.使用 input_allocate_device 函数申请一个 input_dev。
//2.初始化 input_dev 的事件类型以及事件值。
//3.使用 input_register_device 函数向 Linux 系统注册前面初始化好的 input_dev。

struct input_dev *inputdev;
static int timeperiod;
//定义一个内核定时器变量
struct timer_list timer;
int value=0;

void timer_function(struct timer_list *t)
{
	printk("timer_function runing!\n");
	//按照一定时间重启定时器
	mod_timer(&timer, jiffies+msecs_to_jiffies(timeperiod));//msecs_to_jiffies将ms换成节拍
	//发送KEY_0=1的事件给对应字设备
	input_event(inputdev, EV_KEY, KEY_0, value);
	//同步停止发送
	input_sync(inputdev);
	value = !value;
}

void Timer_init(void)
{
	//初始化定时器变量
	timer_setup(&timer,timer_function,0);//4.14内核之后
    //设置定时器初始时间
	timeperiod = 5000;//单位ms
	//mod_timer与add_timer都可以激活定时器,对应del_timer
}


static __init int my_input_init(void)
{
	//1.申请一个input_dev
	inputdev = input_allocate_device();
	//2.自己初始化
	inputdev->name = "inputdev0";
	inputdev->evbit[0] = BIT_MASK(EV_KEY);//设置为按键类输入
	input_set_capability(inputdev, EV_KEY, KEY_0);//设置按键类中的key0
	//3.注册inputdev
	input_register_device(inputdev);

	//初始化定时器,每5s发送一次input信号给对应设备节点
	Timer_init();
	//开启定时器
	mod_timer(&timer, jiffies+msecs_to_jiffies(timeperiod));
	return 0;
}
static __exit void my_input_exit(void)
{
	del_timer_sync(&timer);//注销定时器
	/* 释放 input_dev */
	input_unregister_device(inputdev);//注销
	input_free_device(inputdev);//释放
}

module_init(my_input_init);
module_exit(my_input_exit);
MODULE_LICENSE("GPL");

2.test.c

#include <linux/input.h>
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/ioctl.h"
#include "fcntl.h"


static struct input_event inputevent;

int main(int argc,char **argv)
{
	int err;
	int fd;
	if(argc!=2)
	{
		printf("./test /dev/xx\n");
		return -1;
	}
	fd = open(argv[1],O_RDWR);
	if(fd<0)
	{
		printf("open error\n");
		return -1;
	}
	while(1)
	{
		err = read(fd, &inputevent, sizeof(inputevent));
		if(err>0)
		{
			switch (inputevent.type)
			{
				case EV_KEY:
					if(inputevent.code==KEY_0)
					{
						printf("KEY_0 value is %d\n",inputevent.value);
					}
					break;
				/* 其他类型的事件,自行处理 */
				case EV_REL:
					break;
				case EV_ABS:
					break;
				case EV_MSC:
					break;
				case EV_SW:
				 	break;
			}
		}
	}
	close(fd);
}

程序讲解

加载模块后,定时器开始,5s发送一次key_0信号,轮流数0/1(1表示按下)

然后在应用打印出发送的key_0还是1

有趣现象

在key_0是1时,命令行不断打印 “00000000000000000000000000000000”

我怀疑时这个input子系统的发送信号是针对所有input下的节点的,他们都能接收到这个信号,所以有关键盘的应用程序调用获取到这个"欺骗信号"时以为时key_0按下了就不停打印0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值