linux输入子系统

来源:互联网 发布:linux 不能创建目录 编辑:程序博客网 时间:2024/05/20 15:12

输入子系统有三个层次:

1.核心层input.c;

2.中间设备类型层(自己起的名字)mousedev.c, joydev.c等

3.具体设备,对应于具体硬件型号的驱动程序。


输入子系统核心是drivers/input/input.c,从input.c的init部分input_init开始分析


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];if (!handler || !(new_fops = fops_get(handler->fops))) {err = -ENODEV;goto out;}/* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */if (!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);if (err) {fops_put(file->f_op);file->f_op = fops_get(old_fops);}fops_put(old_fops);out:unlock_kernel();return err;}
主要关注handler; old_fops, new_fops

handler是input_table数组中的一项,在input.c中,定义了static struct input_handler *input_table[8]; input_handler 结构体如下,struct file_operations *fops;new_fops指向了handler->fops, new_fops->open(inode, file) , 对input_open_file()的调用实际是对handler->fops里的open的调用。


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;};



iput_table数组在input.c中仅做了定义,并没有初始化,input_table是谁初始化的?搜索可知input_register_handler函数注册了input_table数组项,并且将handler加入input_handler_list链表,然后遍历链表,调用input_attach_handler


int input_register_handler(struct input_handler *handler){struct input_dev *dev;int retval;retval = mutex_lock_interruptible(&input_mutex);if (retval)return retval;INIT_LIST_HEAD(&handler->h_list);if (handler->fops != NULL) {if (input_table[handler->minor >> 5]) {retval = -EBUSY;goto out;}input_table[handler->minor >> 5] = handler;}list_add_tail(&handler->node, &input_handler_list);list_for_each_entry(dev, &input_dev_list, node)input_attach_handler(dev, handler);input_wakeup_procfs_readers(); out:mutex_unlock(&input_mutex);return retval;}

input_attach_handler 将dev与handler->id_table进行比较,如果handler支持dev(具体的硬件设备型号),则将handler与dev建立连接 connect:

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler){const struct input_device_id *id;int error;if (handler->blacklist && input_match_device(handler->blacklist, dev))return -ENODEV;id = input_match_device(handler->id_table, dev);if (!id)return -ENODEV;error = handler->connect(handler, dev, id);if (error && error != -ENODEV)printk(KERN_ERR"input: failed to attach handler %s to device %s, ""error: %d\n",handler->name, kobject_name(&dev->dev.kobj), error);return error;}

input_register_device:list_add_tail将dev加入链表,调用input_attach_handler


int input_register_device(struct input_dev *dev){static atomic_t input_no = ATOMIC_INIT(0);struct input_handler *handler;const char *path;int error;__set_bit(EV_SYN, dev->evbit);/* * If delay and period are pre-set by the driver, then autorepeating * is handled by the driver itself and we don't do it in input.c. */init_timer(&dev->timer);if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {dev->timer.data = (long) dev;dev->timer.function = input_repeat_key;dev->rep[REP_DELAY] = 250;dev->rep[REP_PERIOD] = 33;}if (!dev->getkeycode)dev->getkeycode = input_default_getkeycode;if (!dev->setkeycode)dev->setkeycode = input_default_setkeycode;dev_set_name(&dev->dev, "input%ld",     (unsigned long) atomic_inc_return(&input_no) - 1);error = device_add(&dev->dev);if (error)return error;path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);printk(KERN_INFO "input: %s as %s\n",dev->name ? dev->name : "Unspecified device", path ? path : "N/A");kfree(path);error = mutex_lock_interruptible(&input_mutex);if (error) {device_del(&dev->dev);return error;}list_add_tail(&dev->node, &input_dev_list);list_for_each_entry(handler, &input_handler_list, node)input_attach_handler(dev, handler);input_wakeup_procfs_readers();mutex_unlock(&input_mutex);return 0;}EXPORT_SYMBOL(input_register_device);






ds





sd





ss


0 0