Android底层开发入门(8)-InputSystem

硬件分析

在一个屏幕中ic一般打在软体线上,通过TX与RX进行实时通信,IC(ft5x46)会对屏幕触点进行降噪和相应的算法等等,然后ic通过iic接口(有应答)与soc进行通讯,在ft5x46的datasheet里面有相应的框架图,如下图

当然这个并不是我们关注的点·

软件分析

要对触屏进行了解,那么必须对input system进行了解,首先可以对整个的系统进行一个比较大致的了解,那么可以看到

input system有3大块组成:

  • input Driver:相当于输入设备的驱动程序,负责接受来自硬件的输入中断,并把输入中断转换成相应的输出给INPUT CORE.(关注的重点)
  • input core:linux input system中的核心代码,抽象成设备文件
  • Evrent Handler 用户空间的handlers接受输入和传值

input-event

input-event有3个元素分别是

  • type :EV_ABS
  • code :ABS_MT_POSITION_X
  • value:X1

那么如何看到这些定义呢?

可以在android源码目录下的/kernel/include/uapi/linux/input.h进行查阅,当然在后面解释这些宏一般的具体含义

Multi touch event

在MMulti touch event中定义了相当多的宏,这些宏代表的是多点触屏的基本一些定义

  • BTN_TOUCH : Indicates whether the tool is touching the device表示手指是否正在触摸设备
  • ABS_MT_TRACKING_ID : Report the tracking id of the tool报告手指的track id
  • input_mt_sync : Report SYN_MT_REPORT event after one point report end报告SYN_MT_REPORT事件结束后
  • input_sync : Tell those who receive the events that we’ve sent a complete report发送的完整报告的事件
  • ABS_MT_POSITION_X : The surface X coordinate of the center of the touching ellipse.触摸椭圆的中心的表面上X坐标。
  • ABS_MT_POSITION_Y : The surface Y coordinate of the center of the touching ellipse.触摸椭圆的中心的表面上Y坐标。
  • ABS_MT_PRESSURE : The pressure, in arbitrary units, on the contact area. May be used instead of TOUCH and WIDTH for pressure-based devices or any device with a spatial signal intensity distribution.在任意单位接触面积的压力。可以用来代替触摸和宽度为基于压力的装置或具有空间信号强度分布的任何设备。
  • ABS_MT_TOUCH_MAJOR : The length of the major axis of the contact.接触的长轴的长度
  • ABS_MT_WIDTH_MAJOR : The length, in surface units, of the major axis of the approaching tool.

可以到/kernel/Documentation/input/multi-touch-protocol.txt下面去查看相关的定义(该文详细地解释了多点触屏的协议)

至于他是如何实现的,可以去查看/kernel/drivers/input/input.c中的源码

Input device initialize

多点触屏的协议实现在/kernel/drivers/input/touchscreen/ftxxx_ts.c(这个文件在不同的手机中的源码不同)

input_dev = input_allocate_device();

input_dev->name = Focal_input_dev_name;

__set_bit(KEY_BACK, input_dev->keybit); 
__set_bit(KEY_HOME, input_dev->keybit);
__set_bit(KEY_APPSELECT, input_dev->keybit);    
__set_bit(EV_ABS, input_dev->evbit);    
__set_bit(EV_KEY, input_dev->evbit);    
__set_bit(BTN_TOUCH, input_dev->keybit);    

input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, CFG_MAX_TOUCH_POINTS, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 31, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ftxxxx_ts->x_max, 0, 0);  
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ftxxxx_ts->y_max, 0, 0);  
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0);

input_register_device(input_dev);

对于触摸屏,必须支持的事件类型有以下这么三个

__set_bit(EV_SYN, input_dev->evbit); //设备同步,每次触摸完成以后都要发送一个同步事件,来表明这次触摸已经完成

__set_bit(EV_ABS, input_dev->evbit); //绝对坐标事件,触摸屏每次发送的坐标都是绝对坐标,不同于鼠标的相对坐标

__set_bit(EV_KEY, input_dev->evbit); //按键事件,每次触摸都有一个BTN_TOUCH的按键事件

触摸屏必须支持的按键类型

__set_bit(BTN_TOUCH, input_dev->keybit);//touch类型按键

触摸屏属性设置

input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);//报告最大支持的点数

input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);//将触摸点看成一个椭圆,它的长轴长度。这个是可选项,并不影响正常使用。

input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ft5x0x_ts->x_max, 0, 0);//x坐标取值范围

input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ft5x0x_ts->y_max, 0, 0);//y坐标取值范围

A协议是不管什么tracking id直接发送出去给framwork由软件来实现对数据的处理,而B协议是要有SOLTS与tracking id在这里才能报告给上层

/*
*report the point information
*/
static void ftxxxx_report_value(struct ftxxxx_ts_data *data)
{   
    struct ts_event *event = &data->event;
    int i;
         u8 uppoint=0;  //已经抬起的点数

#ifdef A
    //protocol A
    for(i=0;i < event->touch_point;i++)
    {
        if((event->au8_touch_event[i] == 0)||(event->au8_touch_event[i] ==2))
        {
            input_report_key(data->input_dev, BTN_TOUCH, 1); 
            input_report_abs(data->input_dev, ABS_MT_PRESSURE, event->pressure[i]);
            input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]);
            input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]);
            input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]);
            input_mt_sync(data->input_dev);
        }
        else
        {
            uppoint++;
            input_mt_sync(data->input_dev);
        }
    }
    if(uppoint==event->touch_point)
    {
        input_report_key(data->input_dev,BTN_TOUCH,0);

    }
    else
        input_report_key(data->input_dev,BTN_TOUCH,event->touch_point>0);
    input_sync(data->input_dev);
#endif
#ifdef B
    //protocol B
    for(i=0;i < event->touch_point;i++)//循环处理 缓存中的所有点  
    {
    /*add by alex wang get slot*/
        input_mt_slot(data->input_dev,event->au8_finger_id[i]); //发送点的ID 
        if((event->au8_touch_event[i] == 0)||(event->au8_touch_event[i] ==2)) //如果点按下
        {
                        input_mt_report_slot_state(data->input_dev,MT_TOOL_FINGER , true); //手指按下 
            input_report_key(data->input_dev, BTN_TOUCH, 1); //告诉系统有键按下
            input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->au8_finger_id[i]);
                            input_report_abs(data->input_dev, ABS_MT_PRESSURE, event->pressure[i]);
                        input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, event->area[i]);
                input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->au16_x[i]);
                 input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->au16_y[i]);
        }
        else
        {
            uppoint++;
                        input_mt_report_slot_state(data->input_dev,MT_TOOL_FINGER,false);//报告手指抬起 
        }
    }
    if(uppoint==event->touch_point)
    {
        input_report_key(data->input_dev,BTN_TOUCH,0);/所有手指都抬起了 发送BTN_TOUCH 抬起事件 
    }
    else
        input_report_key(data->input_dev,BTN_TOUCH,event->touch_point>0);/还有手指没抬起,发送BTN_TOUCH 按下的事件

        input_sync(data->input_dev);//sync 设备同步 

}
#endif

未完待续

你可能感兴趣的:(android)