一、input子系统的分层结构
linux系统实现了很多子系统架构,每个子系统都是分层的;input子系统也不例外,主要分为三层:
(1) 硬件驱动层:与硬件相关,是驱动开发的部分。
(2) 系统核心层:是连接其他两层的纽带,对应的代码为drivers/input/input.c、input-mt.c等。
(3) 事件处理层:真正的事件处理部分,为应用程序提供读写接口;对应的代码为drivers/input/evdev.c、mousedev.c等。
二、主要数据结构
struct input_value { __u16 type; __u16 code; __s32 value; };
input设备report数据最终调用的函数是void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);这个函数的参数最终会填到上述结构中。
struct input_dev { const char *name; const char *phys; const char *uniq; struct input_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)]; 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; struct list_head node; unsigned int num_vals; unsigned int max_vals; struct input_value *vals; bool devres_managed; };
input_dev代表一个输入设备,每个输入设备的驱动文件中都能找到它,h_list用于挂handle,node用于挂自己到全局的list上。
struct input_id { __u16 bustype; __u16 vendor; __u16 product; __u16 version; };
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; struct list_head h_list; struct list_head node; };
input_handler是一个事件处理,包含各种事件处理方法。h_list用于挂handle,node用于挂自己到全局的list上。
struct input_handle { void *private; int open; const char *name; struct input_dev *dev; struct input_handler *handler; struct list_head d_node; struct list_head h_node; };
input_handle是连接handler和dev的纽带。d_node用于挂dev,h_node用于挂handler。
在dev和handler匹配成功时,connect的时候会创建evdev->handle结构,handle会分别挂在已经匹配的dev和handler结构中。
struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; };
struct evdev { int open; struct input_handle handle; wait_queue_head_t wait; struct evdev_client __rcu *grab; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; struct cdev cdev; bool exist; };
struct evdev_client { unsigned int head; unsigned int tail; unsigned int packet_head; /* [future] position of the first element of next packet */ spinlock_t buffer_lock; /* protects access to buffer, head and tail */ struct wake_lock wake_lock; bool use_wake_lock; char name[28]; struct fasync_struct *fasync; struct evdev *evdev; struct list_head node; int clkid; unsigned int bufsize; struct input_event buffer[]; };