linux驱动——input输入子系统(1)—输入子系统核心层(Input C

1、

上图是input输入子系统框架,输入子系统由输入子系统核心层( Input Core ),驱动层和事件处理层(EventHandler)三部份组成。一个输入事件,如鼠标移动,键盘按键按下,joystick的移动等等通过 input driver -> Input core ->Event handler -> userspace 到达用户空间传给应用程序。

2、先来说下Input Core输入子系统核心层。在Linux中,输入子系统作为一个模块存在,向上,为用户层提供接口函数,向下,为驱动层程序提供统一的接口函数。主要在Input.c (linux2.6.28\drivers\input)文件中:

subsys_initcall(input_init);module_exit(input_exit);

static int __init input_init(void){int err;err = class_register(&input_class);注册一个名为input的类

其中有:

struct class input_class = {.name= "input",};if (err) {printk(KERN_ERR "input: unable to register input_dev class\n");return err;}err = input_proc_init();if (err)goto fail1;err = register_chrdev(INPUT_MAJOR, "input", &input_fops);注册了主设备号为INPUT_MAJOR的字符设备,操作函数集是:input_fops,如下所示:

static const struct file_operations input_fops = {.owner = THIS_MODULE,.open = input_open_file,};if (err) {printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);goto fail2;}return 0;fail2:input_proc_exit();fail1:class_unregister(&input_class);return err;}static void __exit input_exit(void) 做和input_init函数做相反的工作{input_proc_exit();unregister_chrdev(INPUT_MAJOR, "input");class_unregister(&input_class);}

2.1、接着看下input_open_file函数,源码如下:

static int input_open_file(struct inode *inode, struct file *file){struct input_handler *handler;const struct file_operations *old_fops, *new_fops = NULL;int err;lock_kernel();/* No load-on-demand here? */handler = input_table[iminor(inode) >> 5];

其中iminor(inode)为打开文件所对应的次设备号。input_table是一个struct input_handler全局数组,只有8个元素,其定义为:static struct input_handler *input_table[8];

首先将设备结点的次设备号右移5位做为索引值到input_table中取对应项,从这里也可以看到,一个handler代表 32(1<<5)个设备结点,也就是一个handler最多可以处理32个设备结点。因为在input_table中取值是以次备号右移5位为索引的,即第5位相同的次备号对应的是同一个索引。在input_register_handler()函数中 input_table[handler->minor >> 5] = handler,其将handler赋给了input_table数组,所使用的规则也是右移5位。

其中input_handler结构体如下所示:

/*** struct input_handler – implements one of interfaces for input devices* @private: driver-specific data* @event: event handler. This method is being called by input core with*interrupts disabled and dev->event_lock spinlock held and so*it may not sleep* @connect: called when attaching a handler to an input device* @disconnect: disconnects a handler from input device* @start: starts handler for given handle. This function is called by*input core right after connect() method and also when a process*that "grabbed" a device releases it* @fops: file operations this driver implements* @minor: beginning of range of 32 minors for devices this driver*can provide* @name: name of the handler, to be shown in /proc/bus/input/handlers* @id_table: pointer to a table of input_device_ids this driver can*handle* @blacklist: pointer to a table of input_device_ids this driver should*ignore even if they match @id_table* @h_list: list of input handles associated with the handler* @node: for placing the driver onto input_handler_list** Input handlers attach to input devices and create input handles. There* are likely several handlers attached to any given input device at the* same time. All of them will get their copy of input event generated by* the device.** Note that input core serializes calls to connect() and disconnect()* methods.*/struct input_handler {void *private;void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);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);const struct file_operations *fops;int minor;const char *name;const struct input_device_id *id_table;const struct input_device_id *blacklist;struct list_headh_list;struct list_headnode;};

if (!handler || !(new_fops = fops_get(handler->fops))) { 检查handler是否存在err = -ENODEV;goto out;}/** That’s _really_ odd. Usually NULL ->open means "nothing special",* not "no device". Oh, well…*/if (!new_fops->open) { 判断new_fops->open是否存在fops_put(new_fops);err = -ENODEV;goto out;}old_fops = file->f_op;file->f_op = new_fops;err = new_fops->open(inode, file); 使用新的open函数重新打开设备if (err) {fops_put(file->f_op);file->f_op = fops_get(old_fops);}fops_put(old_fops);out:unlock_kernel();return err;}linux驱动——input输入子系统(2)——handler的地址链接linux驱动——input输入子系统(3)——evdev的地址链接

要克服生活的焦虑和沮丧,得先学会做自己的主人

linux驱动——input输入子系统(1)—输入子系统核心层(Input C

相关文章:

你感兴趣的文章:

标签云: