struct input_handler {void*private;void (*event)(struct input_handle *handle,unsignedint type,unsignedint code,int value);bool (*filter)(struct input_handle *handle,unsignedint type,unsignedint code,int value);bool (*match)(struct input_handler *handler,struct input_dev *dev);int (*connect)(struct input_handler *handler,struct input_dev *dev,conststruct input_device_id *id);void (*disconnect)(struct input_handle *handle);void (*start)(struct input_handle *handle);conststruct file_operations *fops;int minor;constchar*name;conststruct input_device_id *id_table;struct list_head h_list; // handle_list 连接它的handle会挂载于这里struct list_head node; // 挂载到全局驱动表上};/** * struct input_handle - links input device with an input handler * @private: handler-specific data * @open: counter showing whether the handle is 'open', i.e. should deliver * events from its device * @name: name given to the handle by handler that created it * @dev: input device the handle is attached to * @handler: handler that works with the device through this handle * @d_node: used to put the handle on device's list of attached handles * @h_node: used to put the handle on handler's list of handles from which * it gets events */struct input_handle {void*private;int open;constchar*name;struct input_dev *dev;struct input_handler *handler;struct list_head d_node;struct list_head h_node;};
/* * Create new evdev device. Note that input core serializes calls * to connect and disconnect so we don't need to lock evdev_table here. */staticintevdev_connect(struct input_handler *handler,struct input_dev *dev,conststruct input_device_id *id){struct evdev *evdev;int minor;int error;for (minor =0; minor < EVDEV_MINORS; minor++)if (!evdev_table[minor])break; evdev =kzalloc(sizeof(struct evdev), GFP_KERNEL); ...dev_set_name(&evdev->dev,"event%d", minor);evdev->exist =true;evdev->minor = minor;evdev->handle.dev =input_get_device(dev);evdev->handle.name =dev_name(&evdev->dev);evdev->handle.handler = handler;evdev->handle.private = evdev;evdev->dev.devt =MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);evdev->dev.class =&input_class;evdev->dev.parent =&dev->dev;evdev->dev.release = evdev_free;device_initialize(&evdev->dev); error =input_register_handle(&evdev->handle); error =evdev_install_chrdev(evdev); error =device_add(&evdev->dev); ...return0;}
也是省略了部分出错的判断,我们来看看关键的几个地方
首先,自己计算一个minor,在自己管理的32个minor的基础上
分配一个新的,evdev结构,初始化(包括了设备初始化)
注册一个新的 handle注意不是handler
存储 evdev,就是放在一个数组中,方便索引
intinput_register_handle(struct input_handle *handle){struct input_handler *handler =handle->handler;struct input_dev *dev =handle->dev;int error; /* * We take dev->mutex here to prevent race with * input_release_device(). */ error =mutex_lock_interruptible(&dev->mutex); /* * Filters go to the head of the list, normal handlers * to the tail. */if (handler->filter)list_add_rcu(&handle->d_node,&dev->h_list);elselist_add_tail_rcu(&handle->d_node,&dev->h_list);mutex_unlock(&dev->mutex); /* * Since we are supposed to be called from ->connect() * which is mutually exclusive with ->disconnect() * we can't be racing with input_unregister_handle() * and so separate lock is not needed here. */list_add_tail_rcu(&handle->h_node,&handler->h_list);if (handler->start)handler->start(handle);return0;}
/* * Pass event first through all filters and then, if event has not been * filtered out, through all open handles. This function is called with * dev->event_lock held and interrupts disabled. */staticvoidinput_pass_event(struct input_dev *dev,unsignedint type,unsignedint code,int value){struct input_handler *handler;struct input_handle *handle;rcu_read_lock(); handle =rcu_dereference(dev->grab);if (handle)handle->handler->event(handle, type, code, value);else {bool filtered =false;list_for_each_entry_rcu(handle,&dev->h_list, d_node) {if (!handle->open)continue; handler =handle->handler;if (!handler->filter) {if (filtered)break;handler->event(handle, type, code, value); } elseif (handler->filter(handle, type, code, value)) filtered =true; } }rcu_read_unlock();}
这里读者知道,刚才再说 usb 键盘驱动那里我们卖了一关子,usb 设备对 input 设备注册了自己 open 函数,但是没说哪里调用。
/** * input_open_device - open input device * @handle: handle through which device is being accessed * * This function should be called by input handlers when they * want to start receive events from given input device. */intinput_open_device(struct input_handle *handle){struct input_dev *dev =handle->dev;int retval; ...handle->open++;if (!dev->users++&&dev->open) retval =dev->open(dev);// 就在这里调用了 .... out:mutex_unlock(&dev->mutex);return retval;}
这里设备的 open 函数,以 刚才 usb 键盘为例,就会来到 usb_kbd_open 了,这里与 USB 子系统有关,就不继续分析了。
evdev 的handler 最终调用了 input device 的 open 函数,其实内核的代码注释里面也说了,这里直接引用吧。
"
/**
* input_open_device - open input device
* @handle: handle through which device is being accessed
*
* This function should be called by input handlers when they
* want to start receive events from given input device.
*/