在Input子系统三层框架对应3个结构体,现在由下到上对三个层次的主要结构体进行分析。文本以触摸设备为例进行重点分析。
1.驱动层中表示硬件的结构体struct input_dev.
- struct input_dev {
- const char *name;
- const char *phys;
- const char *uniq;
- struct input_id id;//与handler进行匹配时,将此结构体与handler中的id_table和blacklist进行对比,对于触摸设备这个结构体设置无关紧要,其他设备的设置比较重要。
- unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//输入设备支持的事件,对于一个事件有三种属性,分别为type、code、value。此位掩码的数组用于设置设备支持的类型。触摸屏设备需要设置
- 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)];//LED事件支持的事件码
- 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 keycodemax;
- unsigned int keycodesize;
- void *keycode;
- int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
- int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
- struct ff_device *ff;
- unsigned int repeat_key;
- struct timer_list timer;
- int sync;
- int abs[ABS_MAX + 1];
- int rep[REP_MAX + 1];
- unsigned long key[BITS_TO_LONGS(KEY_CNT)];//按键事件的事件值
- unsigned long led[BITS_TO_LONGS(LED_CNT)];//LED事件的事件值
- unsigned long snd[BITS_TO_LONGS(SND_CNT)];//声音事件的事件值
- unsigned long sw[BITS_TO_LONGS(SW_CNT)];//开关事件的事件值
- int absmax[ABS_MAX + 1];//绝对坐标事件的最大事件值,上报坐标时触摸屏设备设置
- int absmin[ABS_MAX + 1];];//绝对坐标事件的最大事件值,上报坐标时触摸屏设备设置
- int absfuzz[ABS_MAX + 1];];//绝对坐标事件的噪声值,上报坐标时触摸屏设备设置
- int absflat[ABS_MAX + 1];];//绝对坐标事件的中间平面位置值,joydev需要设置
- int absres[ABS_MAX + 1];];
- int (*open)(struct input_dev *dev);//上层调用input_open_device()时,底层调用此函数打开设备
- void (*close)(struct input_dev *dev););//上层调用input_close_device()时,底层调用此函数关闭设备
- int (*flush)(struct input_dev *dev, struct file *file);//清空设备。
- int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);//由上层handler传给底层需要处理的事件。
- struct input_handle *grab;//绑定的handle
- spinlock_t event_lock;
- struct mutex mutex;
- unsigned int users;
- bool going_away;
- struct device dev;//设备的抽象结构体,表示是一个设备
- struct list_head h_list;//与此设备相关的handle列表
- struct list_head node;// 在input_dev_list(全局结构体)中的节点
- };
1.1在发生输入事件时,向子系统报告事件
用于报告EV_KEY、EV_REL、EV_ABS等事件的函数有:
- void input_report_key(struct input_dev *dev, unsigned int code, int value)
- void input_report_rel(struct input_dev *dev, unsigned int code, int value)
- void input_report_abs(struct input_dev *dev, unsigned int code, int value)
触摸屏设备使用函数void input_report_abs(struct input_dev *dev, unsigned int code, int value)进行上报事件。
比如,触摸屏驱动中是这样调用:
- input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0); //这个是设置ad转换的x坐标
- input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0); //这个是设置ad转换的y坐标
- input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0); //这个是设置触摸屏是否按下的标志
1.2、分配、注册、注销input设备
- struct input_dev *input_allocate_device(void)
- int input_register_device(struct input_dev *dev)
- void input_unregister_device(struct input_dev *dev)
2.核心层表示连接杆的结构体struct input_handle.
- struct input_handle {
- void *private; //handle指定的私有数据,触摸设备为evdev
- int open; //打开与否的标志
- const char *name;
- struct input_dev *dev; //指向相关的底层设备
- struct input_handler *handler; //指向相关的上层时间处理器
- struct list_head d_node; //作为节点连接到input_dev的h_list链表上
- struct list_head h_node; //作为节点连接到handler的h_list链表上
- };
结构体input_handle作为输入子系统的核心层体现在其成员的表示上。俩个节点d_node和h_node可以对下层和上层索引,俩个指针dev和handler表示指向相关的下层设备和上层事件处理设备。这样通过链表可以由上层找到底层,上层的open,close函数就要进行此类查找;底层要上报事件也是通过链表将事件传递给上层。
3.事件处理层表示事件处理器的结构体struct input_handler.
- struct input_handler {
- void *private;//驱动指定的私有数据
- void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);//对handle传来的事件处理
- int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);//当handler与底层input_dev建立连接时调用
- void (*disconnect)(struct input_handle *handle);//handler与底层input_dev解除连接时调用
- void (*start)(struct input_handle *handle);//当建立连接后对于给定的handle启动handler
- const struct file_operations *fops;//文件操作实现,open、read、write等
- int minor;//次设备号
- const char *name;
- const struct input_device_id *id_table;//支持的设备表
- const struct input_device_id *blacklist;//不支持是设备表
- struct list_head h_list;//相关的handle的链表
- struct list_head node;//作为节点,连接到input_handler_list(全局链表)链表上
- };
3.1对于触摸设备需要struct input_handler evdev_handler.定义在evdev.c中
- static struct input_handler evdev_handler = {
- .event = evdev_event,
- .connect = evdev_connect,
- .disconnect = evdev_disconnect,
- .fops = &evdev_fops,
- .minor = EVDEV_MINOR_BASE,
- .name = "evdev",
- .id_table = evdev_ids,
- };
- static const struct file_operations evdev_fops = {
- .owner = THIS_MODULE,
- .read = evdev_read,
- .write = evdev_write,
- .poll = evdev_poll,
- .open = evdev_open,
- .release = evdev_release,
- .unlocked_ioctl = evdev_ioctl,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = evdev_ioctl_compat,
- #endif
- .fasync = evdev_fasync,
- .flush = evdev_flush
- };
在注册handler时调用:
input_register_handler(&evdev_handler);
此函数调用evdev_connect函数生产struct evdev类型的设备,将其保持在evdev_table全局数组中,以次设备号为数组索引,open,read,write函数以此找到创建的设备。
3.2对于触摸设备创建struct evdev类型的设备,用于设备模型的管理
- struct evdev {
- int exist;
- int open;
- int minor;
- struct input_handle handle;//内嵌的handle
- wait_queue_head_t wait;
- struct evdev_client *grab;
- struct list_head client_list;//连接的client,表示需要处理的事件队列
- spinlock_t client_lock; /* protects client_list */
- struct mutex mutex;
- struct device dev;//表示是一个设备
- };
- struct evdev_client {
- struct input_event buffer[EVDEV_BUFFER_SIZE];//事件缓冲区
- int head;
- int tail;
- spinlock_t buffer_lock; /* protects access to buffer, head and tail */
- struct fasync_struct *fasync;
- struct evdev *evdev;
- struct list_head node;//作为节点连接到client_list链表中
- struct wake_lock wake_lock;
- char name[28];
- };
- struct input_event {
- struct timeval time;
- __u16 type;//事件类型
- __u16 code;//事件码
- __s32 value;//事件码
- };
注:基于linux-kernel2.6.32
参考:linux内核input子系统解析.
linux输入子系统分析一.http://blog.chinaunix.net/uid-26620753-id-3132688.html
阅读(2365) | 评论(0) | 转发(0) |