我是靠谱客的博主 可爱蚂蚁,最近开发中收集的这篇文章主要介绍Linux驱动开发之input子系统(2)------- 输入子系统的分层分析分层分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 分层分析
    • 1.input核心层:input.c
    • 2.input handler层:evdev.c
    • 3.input device层:(自己写的simple_input.c)
    • 4.分层分析框架


分层分析



1.input核心层:input.c


【1】模块入口

subsys_initcall(input_init);
module_exit(input_exit);

【2】input_init主要实现的功能

  • 1.注册类,类似于class_create()
class_register(&input_class);
  • 2.在proc创建bus/input/devices handlers
input_proc_init();
  • 3.申请设备号
register_chrdev(INPUT_MAJOR, "input", &input_fops);

【3】总结

  • 1.注册了主设备号
  • 2.注册了input class

2.input handler层:evdev.c


【1】模块入口

module_init(evdev_init);
module_exit(evdev_exit);

【2】evdev_init主要实现的功能

evdev_init()
	input_register_handler(&evdev_handler);
		//初始化h_list
		INIT_LIST_HEAD(&handler->h_list);
		//将当前的handler加入到一个input_handler_list中  
		list_add_tail(&handler->node, &input_handler_list);
		//遍历链表input_dev_list
		list_for_each_entry(dev, &input_dev_list, node)
		input_attach_handler(dev, handler);
			//将当前的handler和input dev进行匹配,event handler能够匹配所有的input dev
			input_match_device(handler, dev);
			//匹配成功之后要调用handler中的connect方法
			//实际就是event handler ,实际就是调用了evdev_connect
			handler->connect(handler, dev, id);
		//将当前的handler加入到/proc/bus/input/handler
		input_wakeup_procfs_readers();

【2.1】input_register_handler(&evdev_handler);的参数 evdev_handler

static struct input_handler evdev_handler = {
	.event		= evdev_event,
	.connect	= evdev_connect,
	.disconnect	= evdev_disconnect,
	.fops		= &evdev_fops,
	.minor		= EVDEV_MINOR_BASE,   //次设备号开始值64
	.name		= "evdev",
	.id_table	= evdev_ids,
};

【3】分析evdev_handler中的connect方法-----evdev_connect

static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id)

		//找到一个没用被使用的次设备号,从64开始,65,66,67....
		for (minor = 0; minor < EVDEV_MINORS; minor++)
				if (!evdev_table[minor])
					break;
		if (minor == EVDEV_MINORS) {
				printk(KERN_ERR "evdev: no more free evdev devicesn");
				return -ENFILE;
		}
		
		//实例化一个evdev对象
		evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
		
		//初始化evdev对象
		INIT_LIST_HEAD(&evdev->client_list);
		spin_lock_init(&evdev->client_lock);
		mutex_init(&evdev->mutex);
		
		//等待队列是完成阻塞
		init_waitqueue_head(&evdev->wait);
		
		//创建设备文件/dev/event0,1,2....-------效果跟device_create是一样的
		dev_set_name(&evdev->dev, "event%d", minor);
		evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
		evdev->dev.class = &input_class;
		evdev->dev.parent = &dev->dev;
		evdev->dev.release = evdev_free;
		device_initialize(&evdev->dev);
		
		//利用handler记录input device和input handler
		evdev->handle.dev = input_get_device(dev);
		evdev->handle.name = dev_name(&evdev->dev);
		evdev->handle.handler = handler;
		//你中有我,我中有你
		evdev->handle.private = evdev;
		
		//将儿子关联到父亲(input handler)和母亲(input dev)
		input_register_handle(&evdev->handle);
		evdev_install_chrdev(evdev);
		device_add(&evdev->dev);

【3.1】input handler 和input dev 和evdev 三者的关系图

在这里插入图片描述

【3.2】evdev_connect 总结

  • 分配evdev,并初始化,记录input device 和handler的关系
  • 创建设备结点/dev/input/evevt0,1,2…
  • 注册cdev,并实现fpos
  • 关系:多个input device可以对应一个event handler;一个input device对应一个evdev,对应于一个设备结点/dev/input/evevt0,1,2…
  • 所有设备结点调用open,read…等文件io的时候实际是调用cdev中fops中各个接口,最终调用了
static const struct file_operations evdev_fops = {
	.owner		= THIS_MODULE,
	.read		= evdev_read,
	.write		= evdev_write,
	.poll		= evdev_poll,
	.open		= evdev_open,
	.release	= evdev_release,
	.unlocked_ioctl	= evdev_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl	= evdev_ioctl_compat,
#endif
	.fasync		= evdev_fasync,
	.flush		= evdev_flush
};

【4】input handler层总结

  • 1.注册了evdev_handler
  • 2.遍历input_dev_list,并进行恒匹配,匹配成功自动调用handler中的connect方法-----evdev_connect

3.input device层:(自己写的simple_input.c)


【1】模块入口

module_init(simple_input_init);
module_exit(simple_input_exit);

【2】simple_input_init

simple_input_init()
	input_register_device(inputdev);
		//将input dev加入到链表input_dev_list
		list_add_tail(&dev->node, &input_dev_list);
		//遍历input handler链表,进行匹配
		list_for_each_entry(handler, &input_handler_list, node)
		//调用跟handler层一样的匹配函数进行匹配
		input_attach_handler(dev, handler);
		//将当前的input deev加入到/proc/bus/input/input dev
		input_wakeup_procfs_readers();

4.分层分析框架


在这里插入图片描述

最后

以上就是可爱蚂蚁为你收集整理的Linux驱动开发之input子系统(2)------- 输入子系统的分层分析分层分析的全部内容,希望文章能够帮你解决Linux驱动开发之input子系统(2)------- 输入子系统的分层分析分层分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部