本人用的触摸屏IC是FocalTech公司的ft5306,是一款i2c的电容屏多点触控芯片。对于它的整体驱动官方已经给了,我们就触摸屏和按键部分的代码做相关说明。说明其中应该注意的地方。
对于所有的input设备,报告input事件时候都分这么几部分,首先在probe文件中设置设备发送的事件类型、按键类型、设置设备一些属性信息。然后在发送事件时候要根据probe的设置来发送事件,否则就会被判为无效忽略掉。
一、触摸屏部分
1.设备配置
对于触摸屏,必须支持的事件类型有以下这么三个
__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坐标取值范围
2.事件发送
我们知道每次触摸完成后都必须发送一个同步事件(EV_SYN)来表明这次触摸的完成。 那么对于多点触控的屏幕事件发送分为两种方法,一是每次事件同步前包括多个点,一是每次事件同步前仅包含一个点。
先来看包含多个点的
static void ft5x0x_report_value(struct ft5x0x_ts_data *data)
{
struct ts_event *event = &data->event;
int i;
int uppoint = 0; //已经抬起的点数
for (i = 0; i < event->touch_point; i++) //循环处理 缓存中的所有点
{
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_abs(data->input_dev,ABS_MT_POSITION_X,event->au16_x[i]); //x坐标
input_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]); //y坐标
input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR,event->pressure); //触摸点长轴长度
}
else
{
uppoint++; //没有按下,则表明这个手指已经抬起
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,false); //报告手指抬起
}
}
if(event->touch_point == uppoint)
{
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 设备同步
}
然后是每次同步仅发送一个点
static ft5x0x_report_value(struct ft5x0x_ts_data *data)
{
struct ts_event *event = &data->event;
int i;
for (i = 0; i < event->touch_point; i++) //循环处理 缓存中的所有点
{
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_abs(data->input_dev,ABS_MT_POSITION_X,event->au16_x[i]); //x坐标
input_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]); //y坐标
input_report_abs(data->input_dev,ABS_MT_TOUCH_MAJOR,event->pressure); //触摸点长轴长度
}
else
{
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,false); //手指抬起
}
input_mt_report_pointer_emulation(input_dev, true);//用模拟点的方法,来告知此次触摸已经完成。
input_sync(data->input_dev); //sync 设备同步
}
}
这两种方法都可以,但是建议选择上面那种,效率比较高。
二、触摸按键部分
对于触摸按键的发送可以分为两种方法,一是android提供的 virtualkey's 架构方法,一种是直接报告key event的方法。我们一一来看
1.报告key event方法
在probe中添加所支持的按键类型,本人用的触摸屏上有三个按键因此
报告支持事件类型
__set_bit(EV_SYN, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
报告支持的按键
__set_bit(KEY_HOME, input_dev->keybit);
__set_bit(KEY_BACK, input_dev->keybit);
__set_bit(KEY_MENU, inp