linux驱动之输入子系统概念

以前的博文介绍linux驱动程序的时候一直遵循以下步骤:
  1. 确定主设备号
  2. 定义一个file_operation结构,填充函数如:open  write  read poll等
  3. 设备注册
  4. 入口函数
  5. 出口函数

以上即是字符设备的框架。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

目的:使用input子系统

说明:输入子系统是内核写好的,我们之需要弄清楚它,将我们自己的程序融合进这个子系统。

分析:输入子系统框架:

函数调用结构:






/drivers/input/input.c
	input_init > err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

static const struct file_operations input_fops = {
    .owner = THIS_MODULE,
    .open = input_open_file,
};

注册input_handler:
input_register_handler
	//放入数组
	input_table[handler->minor >> 5] = handler;
	//放入链表
	list_add_tail(&handler->node, &input_handler_list);
	//对于每一个input_device调用input_attach_handler
	list_for_each_entry(dev, &input_dev_list, node)
		input_attach_handler(dev, handler);//根据input的id_table 判断能否支持这个input_device


注册输入设备:
input_register_device(struct input_dev *dev)
	//放入链表
	list_add_tail(&dev->node, &input_dev_list);
	
	//对于每一个input_handler,都调用input_attach_handler
	list_for_each_entry(handler, &input_handler_list, node)
		input_attach_handler(dev, handler);//根据input的id_table 判断能否支持这个input_device

input_attach_handler
	id = input_match_device(handler->id_table, dev);

	error = handler->connect(handler, dev, id);
注册input_dev或input_handler时,会两两比较左边的input_dev和右边的input_handler
根据input_handler的id_table判断这个input_handler能否支持这个input_dev
如果能支持,则调用input_handler的connect函数建立“连接”


怎么建立连接?:
1、分配一个input_handle结构题
2、
	input_handle.dev = input_dev;//指向左边的input_dev结构体
	input_handle.handler = input_handler;//指向右边的input_handler结构体
3、注册
	input_handle->h_list = &input_handle;
	input_dev->h_list    = &input_handle;
	

evdev_connect
	evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);//分配一个input_handle结构
	// 设置
	evdev->handle.dev = input_get_device(dev);//指向左边的input_dev结构体
	evdev->handle.name = evdev->name;//
	evdev->handle.handler = handler;//指向右边的input_handler结构体
	evdev->handle.private = evdev;

	//注册
	error = input_register_handle(&evdev->handle);

怎么读按键?
app:read()
-----------------------------------
	..........
	evdev_read
		// 无数据并且是非阻塞方式打开,则立即返回
		if (client->head == client->tail && evdev->exist &&(file->f_flags & O_NONBLOCK))
			return -EAGAIN;

		//休眠
		retval = wait_event_interruptible(evdev->wait,
		client->head != client->tail || !evdev->exist);
谁来唤醒?
evdev_event
	wake_up_interruptible(&evdev->wait);

evdev_event被谁调用?
猜:应该是硬件相关的代码,input_dev那层调用的
在设备的中断服务程序里,确定事件是什么,然后调用相应的input_handler的event的处理函数
gpio_keys_isr
	gpio_keys_report_event
		//上报事件
		input_event(input, type, button->code, !!state);//右边的event函数将会倍调用
		input_sync(input);



下篇博文详细介绍如何写一个驱动。

1、分配一个input_dev结构体

2、 设置

3、注册

4、硬件相关代码:中断服务程序里的上报事件





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值