测试平台

宿主机平台:Ubuntu 12.04.4 LTS

目标机:Easy-ARM IMX283

目标机内核:Linux 2.6.35.3

触摸屏基础知识

一、结构

  上图是电阻触摸屏的一个侧面剖视图。手指触摸的表面是一个硬涂层,用以保护下面的PET层。PET层是很薄的有弹性的PET薄膜,当表面被触摸时它会向下弯曲,并使得下面的两层ITO涂层能够相互接触并在该点连通电路。两个ITO层之间是约千分之一英寸厚的一些隔离支点使两层分开。最下面是一个透明的硬底层用来支撑上面的结构,通常是玻璃或者塑料。
        电阻触摸屏的多层结构会导致很大的光损失,对于手持设备通常需要加大背光源来弥补透光性不好的问题,但这样也会增加电池的消耗。电阻式触摸屏的优点是它的屏和控制系统都比较便宜,反应灵敏度也很好。

二、触摸坐标的计算

   ITO陶瓷层分为了上下两层,中间用隔离支点分开,这两层是X层和Y层。可以看成如下结构:

当没有触摸按下时,X层和Y层是分离的,此时就测不到电压

其中X层上X-到X+和Y-到Y+的电阻是均匀分布的,其电路等效图如下:

1、计算Y坐标,在Y+电极施加驱动电压V,Y-接地,芯片通过X+测量接触点的电压。

由于ITO层均匀导电,触点电压与V电压之比等于触点Y坐标与屏高度之比。

y/height = Vx/Vdrv

y = (Vx/Vdrv) * height

2、计算X坐标,在X+电极施加驱动电压V, X-电极接地,Y+做为引出端测量得到接触点的电压,由于ITO层均匀导电,触点电压与Vdrive电压之比等于触点X坐标与屏宽度之比。

x = (Vy/Vdrv) * width

测得的电压通常由ADC转化为数字信号,再进行简单处理就可以做为坐标判断触点的实际位置。另外触点压力的计算在此不再赘述。

触摸屏驱动实现

Linux将触摸屏驱动放在输入子系统 input 中。

input子系统

接下来我们回顾以下 input 子系统。

Linux内核的输入子系统为鼠标、键盘、触摸屏、游戏杆等输入设备提供了驱动框架。当程序员要为自己的输入设备编写驱动程序时,只需要实现从设备获取输入事件即可。

linux输入子系统的体系结构可以分为三个层面,分别为:硬件驱动层、子系统核心层、事件处理层;

1)设备驱动层

在给输入设备编写驱动程序时,需要为输入设备实现一个设备驱动。设备驱动包含的设备信息有:

(1) 设备的总线类型、厂商、 产品、版本号、名称等身份信息;
(2) 设备可产生的事件类型;
(3) 各事件类型的分量。
当输入设备发生输入事件时,驱动程序要把输入事件向输入子系统报告。

2)事件管理层

分为事件类、 MOUSE 类、游戏杆类型,所 以内核源码为这三种类型的输入设备分别实现了 evdev 、 mousedev 、 joydev 事件管理器。

3)核心层,即 drivers/input/input.c 起着桥梁的作用。

下面我们来剖析触摸屏驱动实现过程

触摸屏驱动分析

1 触摸屏 平台设备注册

板级文件中实现平台设备的注册、平台设备资源、平台设备私有数据

#if defined(CONFIG_TOUCHSCREEN_MXS) || defined(CONFIG_TOUCHSCREEN_MXS_MODULE)
// 平台设备私有数据(adc相关参数)
static struct mxs_touchscreen_plat_data mx28_ts_data = {
.x_plus_chan = LRADC_TOUCH_X_PLUS,
.x_minus_chan = LRADC_TOUCH_X_MINUS,
.y_plus_chan = LRADC_TOUCH_Y_PLUS,
.y_minus_chan = LRADC_TOUCH_Y_MINUS,
.x_plus_val = BM_LRADC_CTRL0_XPULSW,
.x_minus_val = BF_LRADC_CTRL0_XNURSW(2),
.y_plus_val = BF_LRADC_CTRL0_YPLLSW(1),
.y_minus_val = BM_LRADC_CTRL0_YNLRSW,
.x_plus_mask = BM_LRADC_CTRL0_XPULSW,
.x_minus_mask = BM_LRADC_CTRL0_XNURSW,
.y_plus_mask = BM_LRADC_CTRL0_YPLLSW,
.y_minus_mask = BM_LRADC_CTRL0_YNLRSW,
}; // 平台设备资源(寻址地址空间、中断等资源)
static struct resource mx28_ts_res[] = {
{
.flags = IORESOURCE_MEM,
.start = LRADC_PHYS_ADDR,
.end = LRADC_PHYS_ADDR + 0x2000 - 1,
},
{
.flags = IORESOURCE_IRQ,
.start = IRQ_LRADC_TOUCH,
.end = IRQ_LRADC_TOUCH,
},
{
.flags = IORESOURCE_IRQ,
.start = IRQ_LRADC_CH5,
.end = IRQ_LRADC_CH5,
},
}; static void __init mx28_init_ts(void)
{
struct platform_device *pdev; pdev = mxs_get_device("mxs-ts", 0); //获取"mxs-ts"设备
if (pdev == NULL || IS_ERR(pdev))
return;
pdev->resource = mx28_ts_res;
pdev->num_resources = ARRAY_SIZE(mx28_ts_res);
pdev->dev.platform_data = &mx28_ts_data;
mxs_add_device(pdev, 3); //添加到注册设备列表
}
#else
static void __init mx28_init_ts(void)
{
;
}
#endif

2 触摸屏 平台驱动注册

开发板的触摸驱动位置 drivers\input\touchscreen\mxs-ts.c

static struct platform_driver mxs_ts_driver = {
.probe = mxs_ts_probe,
.remove = __devexit_p(mxs_ts_remove),
#ifdef CONFIG_PM
.suspend = mxs_ts_suspend,
.resume = mxs_ts_resume,
#endif
.driver = {
.name = "mxs-ts",
},
}; static int __init mxs_ts_init(void)
{
return platform_driver_register(&mxs_ts_driver); //平台驱动注册,"mxs-ts"匹配触发 mxs_ts_probe
}

驱动安装时触发平台驱动注册,与平台设备 "mxs-ts" 匹配后触发 mxs_ts_probe函数

mxs_ts_probe 主要实现:

1.通过传递的平台设备私有数据来设置 input设备驱动参数,然后通过 input_register_device 注册该触摸设备;

2.获取平台设备资源,配置 lradc 及其中断;

request_irq(info->touch_irq, ts_handler, IRQF_DISABLED, "mxs_ts_touch", info);

当外部触摸时,触发 adc 中断,进入 ts_handler 中断函数,读取对应的 adc 值,然后通过上报给事件管理器

input_report_abs(info->idev, ABS_Y, info->x); //info->x 反应y方向的变化
input_report_abs(info->idev, ABS_X, info->y);
input_report_abs(info->idev, ABS_PRESSURE, pressure);
input_sync(info->idev);

3. input 驱动机制浅析

1 首先时 input 子系统初始化时的字符设备注册 (\drivers\input\input.c),这样就有了 dev/input 主设备

static int __init input_init(void)
{
int err; input_init_abs_bypass(); err = class_register(&input_class);
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
return err;
} err = input_proc_init();
if (err)
goto fail1; err = register_chrdev(INPUT_MAJOR, "input", &input_fops); //创建主设备号为13的"input"字符设备
if (err) {
printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
goto fail2;
} return 0; fail2: input_proc_exit();
fail1: class_unregister(&input_class);
return err;
}

下面来分析 input_register_handle 和 input_register_device

其中 input_register_device 由设备驱动调用,生成子设备

input_register_handle 由事件管理器调用

在 input_register_device 中

list_add_tail(&dev->node, &input_dev_list);    //将这个dev放到input_dev_list链表中 
list_for_each_entry(handler, &input_handler_list, node) 
  input_attach_handler(dev, handler);

list_for_each_entry()函数会将每个input_handle从链表中取出,放到handler中,最后会调用input_attach_handler()函数,将每个input_handle的id_table进行判断,若两者支持便进行连接。

在 input_register_handle 中

list_add_tail(&handler->node, &input_handler_list);  //将这个input_handler放到input_handler_list链表中
list_for_each_entry(dev, &input_dev_list, node) 
  input_attach_handler(dev, handler);

list_for_each_entry()函数会将每个dev从链表中取出,放到dev中,最后会调用input_attach_handler()函数,将每个dev与handle的id_table进行判断,若两者支持便进行连接。

触摸的事件管理器实现是 evdev.c

evdev驱动模块支持时,就会

static int __init evdev_init(void)
{
    return input_register_handler(&evdev_handler);
}
 
evdev_connect()函数,对

input_attach_handler()函数先看是否匹配 input_match_device(handler, dev); //匹配两者

然后调用 handler->connect(handler, dev, id); 进行连接

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error; id = input_match_device(handler, dev); //匹配两者
if (!id)
return -ENODEV; error = handler->connect(handler, dev, id);
if (error && error != -ENODEV)
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
handler->name, kobject_name(&dev->dev.kobj), error); return error;
}

如下图所示,开发板使用的是4线电阻触摸屏,该4线连接在ADC引脚上,该引脚专门是用来接收模拟输入信号.

Linux触摸驱动分析的更多相关文章

  1. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

  2. Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)

    一.spi总线注册 这里所说的SPI核心,就是指/drivers/spi/目录下spi.c文件中提供给其他文件的函数,首先看下spi核心的初始化函数spi_init(void).程序如下: 点击(此处 ...

  3. Linux I2C驱动分析(三)----i2c_dev驱动和应用层分析 【转】

    本文转载自:http://blog.chinaunix.net/uid-21558711-id-3959287.html 分类: LINUX 原文地址:Linux I2C驱动分析(三)----i2c_ ...

  4. 基于335X的Linux网口驱动分析

    基于335X的linux网口驱动分析 一. 系统构成 1.  硬件平台 AM335X 2.  LINUX内核版本 4.4.12 二. 网口驱动构架(mdio部分) mdio网口驱动部分 使用 总线.设 ...

  5. linux驱动基础系列--Linux I2c驱动分析

    前言 主要是想对Linux I2c驱动框架有一个整体的把控,因此会忽略协议上的某些细节,同时里面涉及到的一些驱动基础,比如平台驱动.设备模型.sysfs等也不进行详细说明原理,涉及到i2c协议部分也只 ...

  6. Linux gadget驱动分析1------驱动加载过程

    为了解决一个问题,简单看了一遍linux gadget驱动的加载流程.做一下记录. 使用的内核为linux 2.6.35 硬件为芯唐NUC950. gadget是在UDC驱动上面的一层,如果要编写ga ...

  7. Linux UART驱动分析

    1. 介绍 8250是IBM PC及兼容机使用的一种串口芯片; 16550是一种带先进先出(FIFO)功能的8250系列串口芯片; 16550A则是16550的升级版本, 修复了FIFO相关BUG, ...

  8. linux gsensor驱动分析【转】

    本文转载自:http://blog.sina.com.cn/s/blog_89f592f501013sr2.html 本文以Bma250驱动为例子,详细介绍Gsensor设计的一个模板. gsenso ...

  9. linux串口驱动分析——发送数据

    一.应用程序中write函数到底层驱动历程 和前文提到的一样,首先先注册串口,使用uart_register_driver函数,依次分别为tty_register_driver,cdev_init函数 ...

随机推荐

  1. HttpRunner3源码阅读:2. 模型定义

    models.py 昨天体验的时候我们分别执行了httprunner -h,httprunner startproject demo, httprunner run demo,但是源码中其调用了其他文 ...

  2. Windows影子用户创建与3389连接

    #当获得一条shell后,可以创建一个影子用户,通过影子用户可以行驶正常用户的所有权限与功能,并且只可在注册表中被检测出来---(应急响应注册表很重要) 1.首先需要拥有权限创建一个Administr ...

  3. 字节跳动Android面试凉凉,挥泪整理面筋,你不看看吗?

    想在金九银十找工作的现在可以开始准备了,这边给大家分享一下面试会遇到的问题. 找工作还是需要大家不要担心,由于我们干这一行的接触人本来就不多,难免看到面试官会紧张,主要是因为怕面试官问的答不上来,答不 ...

  4. "百度杯"CTF比赛 十月场——EXEC

    "百度杯"CTF比赛 十月场--EXEC 进入网站页面 查看源码 发现了vim,可能是vim泄露,于是在url地址输入了http://21b854b211034489a4ee1cb ...

  5. HTML5(十一)——WebSocket 基础教程

    一.为什么要学 WebSocket? websocket 是 HTML5 提供的一种长链接双向通讯协议,使得客户端和服务器之间的数据交换更简单,允许服务端主动向客户端推送数据,并且客户端与服务端只需连 ...

  6. 用notepad2代替notepad

    Windows自带的notepad.exe功能比较弱,notepad2是一个比较好的替代方案,但在任何系统调用notepad的时候都能用notepad2代替并不是一件容易的事,下面是一个解决方法: h ...

  7. CVE-2021-25646:Apache Druid远程命令执行漏洞复现

    漏洞概述 Apache Druid 是一个分布式的数据处理系统.Apache Druid包括执行用户提供的JavaScript的功能嵌入在各种类型请求中的代码.在Druid 0.20.0及更低版本中, ...

  8. STM32—DMA存储器到外设

    DMA目录 DMA简介 DMA框图 DMA传输数据分析 1.传输的方向 2.传输的数量 3.传输的模式 代码部分 DMA初始化结构体 USART配置函数 DMA配置函数 主函数 DMA简介 DMA(D ...

  9. 【工作篇】再次熟悉 SpringMVC 参数绑定

    前言 主要现在项目中使用的参数绑定五花八门的,搞得很头大,例如有些用字符串接收日期,用字符串接受数组等等,完全没有利用好 SpringMVC 的优势,这里自己也总结一下,免得到时又要百度谷歌查找. 以 ...

  10. [TcaplusDB知识库]数据库支撑底盘引擎计算层介绍

    在上次的TcaplusDB知识库中,TcaplusDB君为大家讲解了TcaplusDB所用的基于HASH表的Key-value存储引擎TXHDB.存储引擎作为数据库的支撑底盘,其重要性无可置疑,而在本 ...