input子系统一

参考资料:
正点原子Linux设备驱动
韦东山第二期
 
input子系统框架图:
 
0
用户空间:用户空间可直接访问驱动节点,/dev/input/event0,1,2,也可以通过1tslib/libinput库来使用输入设备
输入系统事件层:处理核心层上报的输入事件,给用户层提供访问接口
输入系统核心层:承上启下,接收来自底层的输入事件,转发给上层的handler
输入系统驱动层:硬件相关的驱动,从硬件获得数据,转换为标准得输入事件,向上汇报
 
假设应用程序直接访问/dev/input/event0设备节点,或者使用tslib访问设备节点,数据得流程如下:
1、APP发起读操作,若无数据则休眠
2、用户操作设备,硬件上产生中断
3、输入系统驱动层对应的驱动程序处理中断
读取到数据,转换为标准的输入事件,向核心层汇报
所谓输入事件就是一个“struct input_event”结构体
4、核心层可以决定把输入事件转发给上面那个handler处理:
从handler的名字来看,就是用来处理输入操作的,多种handler,如evdev_handler、khd_handler、joydev_handler等等
最常用的是evdev_handler:它只是把input_event结构体保存在内核buffer等
当APP正在等待数据时,evdev_handler会把它唤醒,这样APP就可以处理返回数据
5、APP对输入事件的处理:
APP获取数据的方法有两种:直接访问设备节点(比如/dev/input/event0,1,2,,,),或者通过tslib、libinput这类库来间接访问设备节点
 
驱动程序上报的数据含义三项重要内容:
type:哪类?比如EV_KEY,按键类
在include/uapi/linux/input.h 中,如下:
 #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)
code:哪个?比如KEY_A
value:值,比如0表示松开,1表示按下,2表示长按
 
举个例子:
触摸屏上的触点怎么表示:type是EV_ABS,第一项code表示x方向的位置ABS_X为0,value可以0-1024等。第二项type仍然是EV_ABS,code表示y的坐标ABS_Y,value可以0-1024等
 
应用层得到一系列的输入事件,就是一个个"struct input_event",定义如下:
struct input_event {
    struct timeval time;
    __u16 type;
    u16 code;
    __s32 value;
};

struct timeval {
    __kernel_time_t tv_sec;
    __kernel_susecondes_t tv_usec;
};
每个输入事件Input_event中都含有发生时间,timeval表示的是“子系统启动以来过了多长时间”,它是一个结构体,含有“tv_sec、tv_usev”两项(即秒,微妙)。
 
驱动上报完一系列数据后,会上报一个“同步事件”,表示数据上报完毕,APP读到“同步事件”时,就知道已经读完了当前的数据
同步事件也是一个input_event结构体,它的type、code、value三项都是0
 
root@ATK-IMX6U:~# hexdump /dev/input/event1
0000000 06e2 6107 a4db 0008 0003 0039 0000 0000
0000010 06e2 6107 a4db 0008 0003 0035 013f 0000
0000020 06e2 6107 a4db 0008 0003 0036 010c 0000
0000030 06e2 6107 a4db 0008 0003 0030 0038 0000
0000040 06e2 6107 a4db 0008 0003 0032 0038 0000
0000050 06e2 6107 a4db 0008 0000 0000 0000 0000            // 全0的同步事件,前面表示构成了一整个输入事件
0000060 06e2 6107 37ee 0009 0003 0039 ffff ffff
------  --------  --------  ---  ---   --------
 序号     秒        微妙    type  code   value
 
如何确认设备信息?
输入设备的设备节点名为/dev/input/eventX。查看设备节点,可执行以下命令:
ls /dev/input/* -l
或
ls /dev/event* -l
如何确认这些设备节点对应什么硬件呢?可以执行:
cat /proc/bus/input/devices
IMX6ULL的执行结果如下:
root@ATK-IMX6U:~# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0000 Product=0000 Version=0000                    // 与input_dev的id进行对应
N: Name="20cc000.snvs:snvs-powerkey"                            // 与input_dev的name进行对应
P: Phys=snvs-pwrkey/input0                                        // 与input_dev的phys进行对应
S: Sysfs=/devices/platform/soc/2000000.aips-bus/20cc000.snvs/20cc000.snvs:snvs-powerkey/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=100000 0 0 0

I: Bus=0018 Vendor=dead Product=beef Version=28bb
N: Name="goodix-ts"
P: Phys=input/ts
S: Sysfs=/devices/virtual/input/input2
U: Uniq=
H: Handlers=event1
B: PROP=3
B: EV=b                            // 0x1011,意味设备支持EV_SYN 0号事件,EV_KEY 1号事件,EV_ABS 3号事件
B: KEY=e520 0 0 0 0 0 0 0 0 0 0
B: ABS=2658000 3                // 哪一些绝对位移的事件呢?两个都是unsigned,265800000000003,每一位都代表一个abs事件,即支持0号、1号abs事件,即ABS_X和ABS_Y等等
    还有47/48/50/53/54号事件,即:0x0/0x1/0x2f/0x30/0x32/0x35/0x36
    0x2f:ABS_MT_SLOT 多点触摸屏
    0x35:ABS_MT_POSITION_X 多点触摸屏的X位移
    0x36:ABS_MT_POSITION_Y 多点触摸屏的y位移 
    0x39:ABS_MT_TRACKING_ID 多点触摸ID,表示哪一个手指

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="gpio_keys@0"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/gpio_keys@0/input/input3
U: Uniq=
H: Handlers=kbd event2
B: PROP=0
B: EV=100003
B: KEY=40000 0 0 0
 
内核如何描述一个输入设备:
使用Input_dev结构体来表示输入设备,内容如下:
 // include/linux/input.h
  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)];        // 支持哪类事件?ABS绝对位移事件,KEY按键类事件,REL相对位移事件
         unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];    // 支持按键类事件的话,支持哪些按键
         unsigned long relbit[BITS_TO_LONGS(REL_CNT)];    // 支持相对位移事件的话,支持哪些
         unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];    // 支持绝对位移事件的话,支持哪些,例如x方向,y方向,压力方向
         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)];

 

input子系统支持完整的API操作
支持以下机制:阻塞、非阻塞、POLL/SELECT、异步通知
机制可参考:

 

 
posted @ 2024-03-31 15:13  lethe1203  阅读(19)  评论(0编辑  收藏  举报