标签:toc put dba copy his csdn func 根据 any
本文转载自:http://blog.csdn.net/jscese/article/details/42099381
在前文 Linux/Android——usb触摸屏驱动 - usbtouchscreen (一) 中记录了如何在kernel中添加input device 类型为touchscreen的驱动,
这在整个输入体系中是最下层的设备驱动部分,往上一层就是linux内核的管理驱动input系统,kernel中的源码位置:/kernel/drivers/input/input.c
撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42099381
到目前已经完全调通,可以正常使用了,现在记录一下这段时间接触到的Android 输入input 系统,先看一张网上的层次图,蛮不错的:
上一篇博客里面的 usbtouchscreen 就是对应上图的I2c module的位置,而在kernel中input的核心就是input.c .
input_dev:
这个结构体表述的是一个输入设备的相关信息,在usbtouchscreen 驱动中的 usbtouch_probe 会初始化input_dev,作为usbtouch设备的一部分.
会对 input_dev 做一系列的初始化,设置参数之类的,具体可参考之前博客
input_dev 结构原型如下,/kernel/include/linux/input.h中定义:
我解释可能还会误导,源码上面的注释是最好的解释,都是描述一个input 设备的相关信息.
每一个input设备,都需要初始化一个这样的input_dev结构来描述记录此设备的一些特性,然后通过input_register_device 注册到设备总线上以供后续使用
可以到系统运行目录的/proc/bus/input下 cat devices 查看总线上的已经注册上的input device
input_event:
设备驱动部分往上传递的就是触发的event事件了,还以usbtouchscreen的为例,回调函数为:
- static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
- unsigned charchar *pkt, int len)
- {
- struct usbtouch_device_info *type = usbtouch->type;
-
- if (!type->read_data(usbtouch, pkt))
- return;
-
- input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
-
- if (swap_xy) {
- input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
- input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
- } else {
- input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
- input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
- }
- if (type->max_press)
- input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
- input_sync(usbtouch->input);
- }
可以看到通过 input_report_* 上报事件到input.c中,这也就是上面层次图中的箭头 9 ,初始在/kernel/include/linux/input.h:
- static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_KEY, code, !!value);
- }
-
- static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_REL, code, value);
- }
-
- static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
- {
- input_event(dev, EV_ABS, code, value);
- }
可以看到不同的report 都调用进了input_event,只是传参不同,接下来的事就全交由input.c 来做了!
- void input_event(struct input_dev *dev,
- unsigned int type, unsigned int code, int value)
- {
- unsigned long flags;
-
- if (is_event_supported(type, dev->evbit, EV_MAX)) {
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- add_input_randomness(type, code, value);
- input_handle_event(dev, type, code, value);
- spin_unlock_irqrestore(&dev->event_lock, flags);
- }
- }
可以看到在这里首先就是过滤了事件类型,这个也是在usbtouchscreen中的probe中初始化过的!
类型有如下几种:
-
- #define EV_SYN 0x00
- #define EV_KEY 0x01
- #define EV_REL 0x02
- #define EV_ABS 0x03
- #define EV_MSC 0x04
- #define EV_SW 0x05
- #define EV_LED 0x11
- #define EV_SND 0x12
- #define EV_REP 0x14
- #define EV_FF 0x15
- #define EV_PWR 0x16
- #define EV_FF_STATUS 0x17
- #define EV_MAX 0x1f
- #define EV_CNT (EV_MAX+1)
input_handle_event:
由上面的input_event 调入进这个handle处理。这里会根据type进行分类处理:
- static void input_handle_event(struct input_dev *dev,
- unsigned int type, unsigned int code, int value)
- {
- int disposition = INPUT_IGNORE_EVENT;
-
- switch (type) {
-
- case EV_SYN:
- switch (code) {
- case SYN_CONFIG:
- disposition = INPUT_PASS_TO_ALL;
- break;
-
- case SYN_REPORT:
- if (!dev->sync) {
- dev->sync = true;
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
-
- ...
-
- case EV_KEY:
-
- if (is_event_supported(code, dev->keybit, KEY_MAX) &&
- !!test_bit(code, dev->key) != value) {
-
- if (value != 2) {
- __change_bit(code, dev->key);
- if (value)
- input_start_autorepeat(dev, code);
- else
- input_stop_autorepeat(dev);
- }
-
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
-
- ...
-
- case EV_ABS:
- if (is_event_supported(code, dev->absbit, ABS_MAX))
- disposition = input_handle_abs_event(dev, code, &value);
- break;
-
- ...
-
- }
-
- if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
- dev->sync = false;
-
- if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
- dev->event(dev, type, code, value);
-
- if (disposition & INPUT_PASS_TO_HANDLERS)
- input_pass_event(dev, type, code, value);
-
- }
这里先记录整个输入系统从设备驱动到上层的关系,以及从kernel中的驱动调用到input系统中的传递过程,虽然看到调用了input.c中的一些函数传递,但是对input核心还是没多少概念,
下篇解析记录一下input这个核心模块~
Linux/Android——输入子系统input_event传递 (二)【转】
标签:toc put dba copy his csdn func 根据 any
原文地址:http://www.cnblogs.com/zzb-Dream-90Time/p/7808406.html