本人用的触摸屏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]);   //发送点的IDif (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]);   //发送点的IDif (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, input_dev->keybit);

触摸屏上的三个按键对应的坐标

(KEY_BACK)  120:1400   (KEY_HOME) 360:1400(KEY_MENU)  500:1400

key event的报告方法很简单只要报告相应的key 和设备同步sync就可以了

static void ft5x0x_report_value(struct ft5x0x_ts_data *data)
{struct ts_event *event = &data->event;int i;for (i = 0; i < event->touch_point; i++){if (event->au16_y[i]==1400){if(event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2){switch(event->au16_x[i]){case 120:input_report_key(data->input_dev, KEY_BACK, 1);break;case 360: input_report_key(data->input_dev, KEY_HOME, 1);break;case 500: input_report_key(data->input_dev, KEY_MENU, 1);break; default: break;}}else{switch(event->au16_x[i]){case 120:input_report_key(data->input_dev, KEY_BACK, 0);break;case 360: input_report_key(data->input_dev, KEY_HOME, 0);break;case 500: input_report_key(data->input_dev, KEY_MENU, 0);break; default: break;}}input_sync(data->input_dev);return;}
}

对于这种方法有一个bug,就是事件发送上去,系统并不认为是触摸屏发送的按键,系统的 触屏震动反馈 并不起作用。这并不符合标准的android触摸设备标准。具体怎么破本人比较菜没有找到方法,大神们谁知道 求破。

2.virtualkeys方法

virtualkeys是android提供的架构使用起来简单方便,推荐大家使用。直接上代码

static ssize_t ft5x06_virtual_keys_show(struct kobject *kobj,        //按键的配置struct kobj_attribute *attr, char *buf)
{return sprintf(buf,__stringify(EV_KEY) ":" __stringify(KEY_BACK) ":120:1400:8:8"   //键类型:键值:按键区域中心x坐标:按键区域中心y坐标:按键区域宽:按键区域高":" __stringify(EV_KEY) ":"__stringify(KEY_HOME) ":360:1400:8:8"":" __stringify(EV_KEY) ":"__stringify(KEY_MENU) ":500:1400:8:8""\n");
}static struct kobj_attribute ft5x06_virtual_keys_attr = {.attr = {.name = "virtualkeys.Ft5x0x_Touch_Screen",  //这里的名字必须为virtualkeys.设备名字  否则系统不会识别.mode = S_IRUGO,},.show = &ft5x06_virtual_keys_show,
};static struct attribute *ft5x06_properties_attrs[] = {&ft5x06_virtual_keys_attr.attr,NULL,
};static struct attribute_group ft5x06_properties_attr_group = {.attrs = ft5x06_properties_attrs,
};static void ft5x06_virtual_keys_init(void)
{struct kobject *properties_kobj;int ret;properties_kobj = kobject_create_and_add("board_properties", NULL);//添加目录board_propertiesif (properties_kobj)ret = sysfs_create_group(properties_kobj,//生成/sys/board_properties/virtualkeys.Ft5x0x_Touch_Screen虚拟按键配置文件&ft5x06_properties_attr_group); //可以使用 cat /sys/board_properties/virtualkeys.Ft5x0x_Touch_Screen命令来查看配置是否正确if (!properties_kobj || ret)pr_err("failed to create board_properties\n");
}

然后将ft5x06_virtual_keys_init()加入到 触摸屏的init 或者probe 函数中,这样触摸键就可以使用了。

三、触摸屏驱动流程

i2c中加入平台初始化代码

static struct ft5x0x_platform_data  ft5x0x_platform_i2c_data = {.x_max=540,.y_max=960,.irq= SABRESD_CHARGE_FLT_1_B,  //中断引脚.reset=SABRESD_DISP0_RST_B,  //复位引脚
};

触摸屏驱动初始化

static int __init ft5x0x_ts_init(void)
{int ret;ret = i2c_add_driver(&ft5x0x_ts_driver);if (ret) {printk(KERN_WARNING "Adding ft5x0x driver failed ""(errno = %d)\n", ret);} else {pr_info("Successfully added driver %s\n",       ft5x0x_ts_driver.driver.name);}return ret;
}

probe函数

#define VIRTUAL_LI       0
#define EVENT_LI        1
#define TOUCH_KEY       VIRTUAL_LI
static int ft5x0x_ts_probe(struct i2c_client *client,const struct i2c_device_id *id)
{。。。。。。。。。。ft5x0x_ts = kzalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);//分配参数内存..........i2c_set_clientdata(client, ft5x0x_ts);参数地址传给i2c 内核初始化一些参数ft5x0x_ts->irq = client->irq;  ft5x0x_ts->client = client;ft5x0x_ts->pdata = pdata;ft5x0x_ts->x_max = pdata->x_max - 1;ft5x0x_ts->y_max = pdata->y_max - 1;ft5x0x_ts->pdata->reset = FT5X0X_RESET_PIN;ft5x0x_ts->pdata->irq = ft5x0x_ts->irq;
.....................err = request_threaded_irq(client->irq, NULL, ft5x0x_ts_interrupt, //注册读取数据中断IRQF_TRIGGER_FALLING, client->dev.driver->name,ft5x0x_ts);。、、、、、、、、、、、、input_dev = input_allocate_device();//分配设备
...........................................__set_bit(EV_SYN, input_dev->evbit);  //注册设备支持event类型__set_bit(EV_ABS, input_dev->evbit);__set_bit(EV_KEY, input_dev->evbit);__set_bit(BTN_TOUCH, input_dev->keybit);
#if TOUCH_KEY == EVENT_LI             //如果使用event key的方法__set_bit(KEY_HOME, input_dev->keybit);   __set_bit(KEY_BACK, input_dev->keybit);  __set_bit(KEY_MENU, input_dev->keybit);
#endif  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);input_set_abs_params(input_dev, ABS_MT_POSITION_Y,0, ft5x0x_ts->y_max, 0, 0);input_dev->name ="Ft5x0x_Touch_Screen";//lijianzhangerr = input_register_device(input_dev);          //注册这个input设备。。。。。。。。。。。
#if TOUCH_KEY == VIRTUAL_LI       //如果使用虚拟键盘设定ft5x06_virtual_keys_init();
#endif
。。。。。。。。。。。。。。。。。。。。。
}

中断处理

static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id)
{struct ft5x0x_ts_data *ft5x0x_ts = dev_id;int ret = 0;disable_irq_nosync(ft5x0x_ts->irq);ret = ft5x0x_read_Touchdata(ft5x0x_ts); //读取数据if (ret == 0)ft5x0x_report_value(ft5x0x_ts);//报告数据enable_irq(ft5x0x_ts->irq);return IRQ_HANDLED;
}

报告事件

static void ft5x0x_report_value(struct ft5x0x_ts_data *data)
{struct ts_event *event = &data->event;int i;int uppoint = 0;/*protocol B*/    for (i = 0; i < event->touch_point; i++){
#if TOUCH_KEY == EVENT_LI     //如果使用 key event方法if (event->au16_y[i]==1400){if(event->au8_touch_event[i]== 0 || event->au8_touch_event[i] == 2){switch(event->au16_x[i]){case 120:input_report_key(data->input_dev, KEY_BACK, 1);break;case 360: input_report_key(data->input_dev, KEY_HOME, 1);break;case 500: input_report_key(data->input_dev, KEY_MENU, 1);break;  default: break;}}else{switch(event->au16_x[i]){case 120:input_report_key(data->input_dev, KEY_BACK, 0);break;case 360: input_report_key(data->input_dev, KEY_HOME, 0);break;case 500: input_report_key(data->input_dev, KEY_MENU, 0);break; default: break;}uppoint++;}input_sync(data->input_dev);return;}#endifinput_mt_slot(data->input_dev, event->au8_finger_id[i]);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]);       //lijianzhanginput_report_abs(data->input_dev, ABS_MT_POSITION_Y,event->au16_y[i]);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);}else{input_report_key(data->input_dev, BTN_TOUCH, event->touch_point > 0);}input_sync(data->input_dev);}

这里驱动流程做了简略的说明,关键的代码都已经贴出来了。与设备相关代码都是厂商给的没有太实际参考价值.

从android input的流程分析我们知道,驱动编译完成以后,要使触摸屏工作,还需要三个文件:触摸屏配置文件 (idc文件,用来配置触摸屏的一些属性)、keylayout文件(kl文件,安卓层面的按键映射文件)、characterMap文件(kcm文件,安卓层面的字符映射文件)
我们一一来看这三个文件

1.触摸屏配置文件

文件所在目录访问顺序:

首先ANDROID_ROOT/usr/idc目录下去找相应名字的文件并返回完整的路径名,如果找不到就从ANDROID_DATA/system/devices/idc下面去找,这里ANDROID_ROOT一般指的是/system目录,ANDROID_DATA一般指/data目录.

文件名称的查找顺序首先是Vendor_XXXX_Product_XXXX_Version_XXXX.idc,然后是Vendor_XXXX_Product_XXXX.idc最后是DEVICE_NAME.idc

总结来看安卓为输入设备打开配置文件依次会访问
/system/usr/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/system/usr/idc/Vendor_XXXX_Product_XXXX.idc
/system/usr/idc/DEVICE_NAME.idc
/data/system/devices/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/data/system/devices/idc/Vendor_XXXX_Product_XXXX.idc
/data/system/devices/idc/DEVICE_NAME.idc

我们驱动里并没有写版本号等这些信息,因此我们设备访问的idc文件会是/system/usr/idc/DEVICE_NAME.idc。因此我们在这个目录下增加文件Ft5x0x_Touch_Screen.idc.对于idc文件的内容,下面是我使用的idc文件的具体内容,仅供参考

touch.deviceType = touchScreen
touch.orientationAware = 1touch.size.calibration = none
touch.orientation.calibration = none                                    

2.key layout文件

key layout文件是android层面的按键映射文件,通过这个文件,用户可以对kernel发送上来的按键功能进行重新定义。也就是说,kernel发送上来一个home键,你可以在这里把它映射成一个back键或者其他的。一般情况下不会修改这个文件,因此我么完全可以使用默认的配置文件

这个文件访问顺序

/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/system/usr/keylayout/DEVICE_NAME.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
/data/system/devices/keylayout/DEVICE_NAME.kl
/system/usr/keylayout/Generic.kl
/data/system/devices/keylayout/Generic.kl

这里不用修改因此不用做改变

3.characterMap文件

characterMap文件是android层面的字符映射文件,比如:你摁下了一个'e'键,平时代表'e',shift+'e'代表'E',casplk+'e'代表'E',alt+'e'可能代表别的意思,这个配置文件就是,做这些映射的。一般情况下这个文件也不用修改。使用默认的就可以。这个文件的访问顺序:

/system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
/system/usr/keychars/DEVICE_NAME.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm
/data/system/devices/keychars/DEVICE_NAME.kcm
/system/usr/keychars/Generic.kcm
/data/system/devices/keychars/Generic.kcm
/system/usr/keychars/Virtual.kcm
/data/system/devices/keychars/Virtual.kcm

到了这里 我们的触摸屏已经完成了,烧写以后应该可以正常使用了。

在这里分享一个小技巧,getevent 这个工具,在/dev/input/目录下使用这个命令,会首先得到系统中所有input设备的描述,然后会得到,kernel发送的所有input事件,当我们写完驱动以后,可以用这个命令将发送的事件打印出来,看驱动写的是否正确。

android4.0触摸屏(touchscreen)以及屏幕按键驱动解析相关推荐

  1. AW9523 linux 按键驱动解析

    AW9523 linux 按键驱动解析 硬件介绍 AW9523是国产芯片,中文手册也是看着方便很多,我从datasheet中摘录一些编写驱动过程中重要信息贴到下面,当然,最好还是看芯片手册,项目使用A ...

  2. android触摸屏映射,解决android4.0 触摸屏分辨率映射不准

    前言 几个月以前升级了android4.0,在触摸屏这块一直有个令人头疼的问题,通常触摸屏的分辨率应该是根据当前屏幕分辨率而定. 但android4.0上就有点奇怪,不管怎么换屏幕的分辨率,触摸屏始终 ...

  3. UT-Exynos4412 三星ARM四核旗舰开发平台android4.0体验-17板载按键调试

    经过2012年的等待,四核的开发平台终于跟广大嵌入从业人员见面了,下面让我们来看下UT-Exynos 4412 开发板的详细参数吧,供广大嵌入式开发人员参考. 一.UT-Exynos 4412开发板高 ...

  4. android触摸屏idc,android4.0 触摸屏配置

    http://source.android.com/tech/input/input-device-configuration-files.html这篇文档,会按下面的顺序识别配置文件: /syste ...

  5. linux驱动由浅入深系列:基于高通平台分析触摸屏(TP)、虚拟按键驱动

    触摸屏的触摸板(touch panel简称TP)驱动的基本架构和普通按键驱动基本一致,可以参考文章: linux驱动由浅入深系列:输入子系统之二(编写一个gpio_key驱动).只是其功能稍稍复杂些, ...

  6. 怎么让Android4.0以上机器的虚拟按键中显示menu键

    4.0的menu被放到了actionbar上,如果不做任何设置的话,虚拟按键(虚拟的back和home键那里)上不会显示menu.网上搜了两个解决方法: 1. 修改AndroidManifest.xm ...

  7. android锁屏快捷键设置,Android4.0+锁屏程序开发——设置锁屏页面篇

    [如何开发一个锁屏应用] 想要开发一个锁屏应用,似乎很难,其实并没有想象中那么难. 从本质上来说,锁屏界面也只是一个Activity而已,只是这个界面比较特殊,在我们点亮屏幕的时候,这个界面就会出现. ...

  8. 触摸屏驱动和按键驱动冲突-----解决方法

    我的开发板上原先移植的有触摸屏的驱动,后来我有添加了以按键驱动.出问题了: 在我添加上按键驱动后,我的触摸屏驱动不能用了,在我按下按键时终端报错说:selected device not a Touc ...

  9. [RK3288][Android6.0] 系统按键驱动流程分析【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/77894406 Rockchip的按键驱动位于 kernel/drivers/input/ke ...

最新文章

  1. R线性回归模型构建:残差值、回归值、预测域、置信区间
  2. html生成1-32位随机数,如何生成一个32位的随机数 | 求索阁
  3. oracle 查看动态性能视图,oracle常用动态性能视图
  4. java获取spring数据源_Spring动态注册多数据源的实现方法
  5. python 数据库模块_MySQl 数据库 之 python模块 pymysql 简单介绍
  6. 计算机网络(第七版)谢希仁编著 前五章课后答案计算题详解
  7. CMMI认证适用的行业范围
  8. 我的世界怎么修改服务器文本,《我的世界手机版》如何修改界面文本 自定义语言教程...
  9. pdf打印机有什么功能
  10. php开源视频cms,迅睿PHP开源视频电影CMS系统
  11. kaka启动出现:Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000c00000, 1073,0)
  12. SFTP传输文件工具FileZilla下载安装教程
  13. matplotlib 柱状图画误差棒
  14. 基于JSON+JQuery实现的多条件筛选功能(类似京东和淘宝功能)
  15. 超写实虚拟人制作教程
  16. comsol临时文件夹中有不支持的字符_错误:发生错误。请查看日志文件 C:\Users......
  17. python基础编程简单案例:购买商品
  18. linux系统字符设备文件类型,Linux文件类型以及颜色标识
  19. python实现守护进程_Python如何实现守护进程的方法示例
  20. 智能加工技术案例分析

热门文章

  1. 地理信息系统(GIS)系列——ArcGIS API for JavaScript 3.9(1)
  2. 输入法 for android2.3,落格输入法|落格输入法安卓版 v3.2.3_手机天堂
  3. 淘米手套游戏CTO潘辉《如何提高手游开发的效率》
  4. 华为云云数据库RDS的购买方式
  5. 解决Endnote插入参考文献时导致word闪退问题
  6. 实现延迟低于500毫秒的1080P实时音视频直播的实践分享
  7. Android studio 系统存储数据SharedPreferences
  8. AGV调度系统/两阶段算法模拟源代码 地图建模
  9. 基于Java毕业设计智能停车场管理系统源码+系统+mysql+lw文档+
  10. QQ资料修改器无法连接封面服务器,QQ编辑资料失败/qq头像和昵称无法修改怎么办 是什么原因?...