Linux中Input的设备驱动框架结构

先看框架图:

Linux中Input的设备驱动框架结构_第1张图片

再看看代码中的结构:

Linux中Input的设备驱动框架结构_第2张图片

分析 一下Input_dev结构(include/linux/input.h):

struct input_dev {
	const char *name; //设备名
	const char *phys; //设备系统层的物理路径
	const char *uniq;
	struct input_id id; //输入设备ID 总线类型;厂商编号,产品ID,产品版本

	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];

	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];   //事件类型标志位
	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; //键盘事件标志位
	unsigned long relbit[BITS_TO_LONGS(REL_CNT)]; //相对位移事件标志位
	unsigned long absbit[BITS_TO_LONGS(ABS_CNT)]; //绝对位移事件标志位
	unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)]; //杂项事件标志位
	unsigned long ledbit[BITS_TO_LONGS(LED_CNT)]; //led指示灯标志位
	unsigned long sndbit[BITS_TO_LONGS(SND_CNT)]; //声音事件
	unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];   //强制反馈事件
	unsigned long swbit[BITS_TO_LONGS(SW_CNT)];   //开关事件标志位

	unsigned int hint_events_per_packet;

	unsigned int keycodemax;  //键盘码表大小
	unsigned int keycodesize; //键盘码大小
	void *keycode;        //键盘码表指针

	int (*setkeycode)(struct input_dev *dev,
			  const struct input_keymap_entry *ke,
			  unsigned int *old_keycode); //设置键盘码
	int (*getkeycode)(struct input_dev *dev,
			  struct input_keymap_entry *ke); //获取键盘码

	struct ff_device *ff; //强制反馈设备

	unsigned int repeat_key; //重复按键标志位
	struct timer_list timer; //定时器

	int rep[REP_CNT]; //重复次数

	struct input_mt *mt;

	struct input_absinfo *absinfo;

	unsigned long key[BITS_TO_LONGS(KEY_CNT)];
	unsigned long led[BITS_TO_LONGS(LED_CNT)];
	unsigned long snd[BITS_TO_LONGS(SND_CNT)];
	unsigned long sw[BITS_TO_LONGS(SW_CNT)];

	int (*open)(struct input_dev *dev);
	void (*close)(struct input_dev *dev);
	int (*flush)(struct input_dev *dev, struct file *file);
	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);

	struct input_handle __rcu *grab;

	spinlock_t event_lock;
	struct mutex mutex;

	unsigned int users;
	bool going_away;

	struct device dev; //设备文件

	struct list_head	h_list; //input_handler 处理器链表头
	struct list_head	node;   //input_device 设备链表头

	unsigned int num_vals;
	unsigned int max_vals;
	struct input_value *vals;

	bool devres_managed;
};

Input_handler结构:

struct input_handler {

	void *private; //私有数据

	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); //事件处理
	void (*events)(struct input_handle *handle,
		       const struct input_value *vals, unsigned int count);
	bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); //过滤器
	bool (*match)(struct input_handler *handler, struct input_dev *dev); //设备匹配
	int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); //设备连接
	void (*disconnect)(struct input_handle *handle); //设备断开连接
	void (*start)(struct input_handle *handle);

	bool legacy_minors;
	int minor; //次设备号
	const char *name; //设备名

	const struct input_device_id *id_table; //输入设备ID表

	struct list_head	h_list; //input_handler处理器链表头
	struct list_head	node; //input_device设备链表头
};

Input的初始化:

static int __init input_init(void)
{
	int err;

	err = class_register(&input_class); //类的注册
	if (err) {
		pr_err("unable to register input_dev class\n");
		return err;
	}

	err = input_proc_init(); //在proc中初始化
	if (err)
		goto fail1;

	err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
				     INPUT_MAX_CHAR_DEVICES, "input"); //设备号的注册
	if (err) {
		pr_err("unable to register char major %d", INPUT_MAJOR);
		goto fail2;
	}

	return 0;

 fail2:	input_proc_exit();
 fail1:	class_unregister(&input_class);
	return err;
}

input_class:

static char *input_devnode(struct device *dev, umode_t *mode)
{
	return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
}

struct class input_class = {
	.name		= "input",
	.devnode	= input_devnode,
};
EXPORT_SYMBOL_GPL(input_class);

以下可以看到都注册到input目录下。

input_proc_init:

static int __init input_proc_init(void)
{
	struct proc_dir_entry *entry;

	proc_bus_input_dir = proc_mkdir("bus/input", NULL);
	if (!proc_bus_input_dir)
		return -ENOMEM;

	entry = proc_create("devices", 0, proc_bus_input_dir,
			    &input_devices_fileops);
	if (!entry)
		goto fail1;

	entry = proc_create("handlers", 0, proc_bus_input_dir,
			    &input_handlers_fileops);
	if (!entry)
		goto fail2;

	return 0;

 fail2:	remove_proc_entry("devices", proc_bus_input_dir);
 fail1: remove_proc_entry("bus/input", NULL);
	return -ENOMEM;
}

以下可以看出,从上面的input_proc_init中在bus下创建imput目录,并在input下创建devices与handlers两个proc的虚拟文件节点。

其中input_devices_fileops:

static const struct seq_operations input_devices_seq_ops = {
	.start	= input_devices_seq_start,
	.next	= input_devices_seq_next,
	.stop	= input_seq_stop,
	.show	= input_devices_seq_show,
};

static int input_proc_devices_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &input_devices_seq_ops);
}

static const struct file_operations input_devices_fileops = {
	.owner		= THIS_MODULE,
	.open		= input_proc_devices_open,
	.poll		= input_proc_devices_poll,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

input_handlers_fileops:

static const struct seq_operations input_handlers_seq_ops = {
	.start	= input_handlers_seq_start,
	.next	= input_handlers_seq_next,
	.stop	= input_seq_stop,
	.show	= input_handlers_seq_show,
};

static int input_proc_handlers_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &input_handlers_seq_ops);
}

static const struct file_operations input_handlers_fileops = {
	.owner		= THIS_MODULE,
	.open		= input_proc_handlers_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

剩下的就是文件相关操作与事件上报过程。下次再分析。

 

 

你可能感兴趣的:(Linux学习总结,Android总结,Linux驱动总结)