ct(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id) { struct evdev *evdev; struct class_device *cdev; dev_t devt; int minor; int error;
for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); if (minor == EVDEV_MINORS) { printk(KERN_ERR "evdev: no more free evdev devices\n"); return -ENFILE; }
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);//为每个匹配evdev_handler的设备创建一个evdev。 if (!evdev) return -ENOMEM;
INIT_LIST_HEAD(&evdev->client_list); init_waitqueue_head(&evdev->wait);
evdev->exist = 1; evdev->minor = minor; evdev->handle.dev = dev; evdev->handle.name = evdev->name; evdev->handle.handler = handler; evdev->handle.private = evdev; sprintf(evdev->name, "event%d", minor);
evdev_table[minor] = evdev;//记录evdev的位置,字符设备/dev/input/evnetx访问时根据次设备号及EVDEV_MINOR_BASE最终在evdev_open中找到对应的evdev devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), cdev = class_device_create(&input_class, &dev->cdev, devt,dev->cdev.dev, evdev->name);//创建了event字符设备节点 …… }
4、input字符设备的打开过程
static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler = input_table[iminor(inode) >> 5]; //得到对应的input_handler const struct file_operations *old_fops, *new_fops = NULL; int err; if (!handler || !(new_fops = fops_get(handler->fops))) //取出对应input_handler的file_operations return -ENODEV; if (!new_fops->open) { fops_put(new_fops); return -ENODEV; } 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); return err; }
5、input字符设备的其它操作
由于在open阶段已经把设备文件的操作操作方法重定位了到了具体的input_handler,所以其它接口操作(read、write、ioctl等),由各个input_handler的fops方法决定。如evdev.c中的:evdev_fops。
|