如果有问题,请加QQ群 891339868 进行交流

今天继续分析NUC972触摸屏驱动,今天咱们详细说一下具体的TSC2007这个芯片的驱动代码。其实这段代码并不十分复杂,主要先搞清楚以下几点:

第一:触摸屏是注册到I2C总线上的input设备,所以驱动里面既包含I2C相关配置,也包含input设备相关配置;

第二:触摸屏驱动中具体的位置采样和各种滤波算法是触摸屏供应商提供的,作为触摸屏使用者一般不需要关注;

第三:触摸屏的中断配置和处理,主要是中断上半部和下半部的处理方法。

废话少说,直接步入正题,先看驱动的最后几行:

static const struct i2c_device_id tsc2007_idtable[] = {{ "tsc2007", 0 },{ }
};MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);//将i2c设备表注册到内核中,方便内核管理设备static struct i2c_driver tsc2007_driver = {.driver = {.owner   = THIS_MODULE,.name    = "tsc2007"},.id_table   = tsc2007_idtable,.probe       = tsc2007_probe,.remove        = tsc2007_remove,
};module_i2c_driver(tsc2007_driver);MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");
MODULE_LICENSE("GPL");

这部分代码主要是实现了两个功能,第一是将触摸屏芯片tsc2007的id_table添加到相对应的I2C总线设备id_table的链表中;第二是将触摸屏芯片tsc2007的驱动注册到I2C总线上。

再看一probe函数:

static int tsc2007_probe(struct i2c_client *client,const struct i2c_device_id *id)
{struct tsc2007 *ts;struct tsc2007_platform_data *pdata = client->dev.platform_data;struct input_dev *input_dev;int err;if (!pdata) {dev_err(&client->dev, "platform data is required!\n");return -EINVAL;}if (!i2c_check_functionality(client->adapter,I2C_FUNC_SMBUS_READ_WORD_DATA))return -EIO;ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);input_dev = input_allocate_device();if (!ts || !input_dev) {err = -ENOMEM;goto err_free_mem;}ts->client = client;ts->irq = client->irq;ts->input = input_dev;init_waitqueue_head(&ts->wait);ts->model             = pdata->model;ts->x_plate_ohms      = pdata->x_plate_ohms;ts->max_rt            = pdata->max_rt ? : MAX_12BIT;ts->poll_delay        = pdata->poll_delay ? : 1;ts->poll_period       = pdata->poll_period ? : 1;ts->get_pendown_state = pdata->get_pendown_state;ts->clear_penirq      = pdata->clear_penirq;printk("poll_period is %dms!\n",ts->poll_period);if (pdata->x_plate_ohms == 0) {dev_err(&client->dev, "x_plate_ohms is not set up in platform data");err = -EINVAL;goto err_free_mem;}snprintf(ts->phys, sizeof(ts->phys),"%s/input0", dev_name(&client->dev));input_dev->name = "TSC2007 Touchscreen";input_dev->phys = ts->phys;input_dev->id.bustype = BUS_I2C;input_dev->open = tsc2007_open;input_dev->close = tsc2007_close;input_set_drvdata(input_dev, ts);input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,pdata->fuzzz, 0);if (pdata->init_platform_hw)pdata->init_platform_hw();err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,IRQF_ONESHOT, client->dev.driver->name, ts);if (err < 0) {dev_err(&client->dev, "irq %d busy?\n", ts->irq);goto err_free_mem;}tsc2007_stop(ts);err = input_register_device(input_dev);if (err)goto err_free_irq;i2c_set_clientdata(client, ts);return 0;err_free_irq:free_irq(ts->irq, ts);if (pdata->exit_platform_hw)pdata->exit_platform_hw();err_free_mem:input_free_device(input_dev);kfree(ts);return err;
}

这段代码主要是定义一个input_dev类型的结构体,并用device端传递进来的数据进行填充,并配置触摸屏相关的参数,比如向input核心层上传数据的类型和数据的具体参数等,并向input子系统注册一个input设备;还有就是通过I2C接口对触摸屏进行初始化。下面详细分析一下:

首先看一下这段代码:

if (!i2c_check_functionality(client->adapter,I2C_FUNC_SMBUS_READ_WORD_DATA))
        return -EIO;

这段代码主要是检查当前的I2C适配器是否支持SMbus的读取寄存器的功能,详细的SMbus协议和功能标识有兴趣的可以自己百度,这里就不详细说了。

再看一下下面这段代码:

ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);input_dev = input_allocate_device();if (!ts || !input_dev) {err = -ENOMEM;goto err_free_mem;}

这段代码主要的功能是为抽象触摸屏的结构体ts社情内存并向内核申请一个input_dev的设备。

再看一下这段代码:

ts->client = client;ts->irq = client->irq;ts->input = input_dev;init_waitqueue_head(&ts->wait);ts->model             = pdata->model;ts->x_plate_ohms      = pdata->x_plate_ohms;ts->max_rt            = pdata->max_rt ? : MAX_12BIT;ts->poll_delay        = pdata->poll_delay ? : 1;ts->poll_period       = pdata->poll_period ? : 1;ts->get_pendown_state = pdata->get_pendown_state;ts->clear_penirq      = pdata->clear_penirq;

这段代码主要是对代表触摸屏的结构体ts的填充,主要包括名字、设备指针、初始化工作队列、触摸屏轮询延时和周期、触摸笔按下状态操作方法、清除触摸笔中断函数等。

再看一下这段代码:

input_dev->name = "TSC2007 Touchscreen";input_dev->phys = ts->phys;input_dev->id.bustype = BUS_I2C;input_dev->open = tsc2007_open;input_dev->close = tsc2007_close;input_set_drvdata(input_dev, ts);input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,pdata->fuzzz, 0);

同样的操作,这一段代码主要是对input设备相关的内容进行填充,有兴趣的可以将这个结构体追进去查看每个结构体成员的详细内容。

继续看下面的这一段代码:

err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,IRQF_ONESHOT, client->dev.driver->name, ts);if (err < 0) {dev_err(&client->dev, "irq %d busy?\n", ts->irq);goto err_free_mem;

这段代码主要是为触摸屏申请中断,这里面需要注意几个参数,首先是第二个参数,这个参数指向的参数是中断上半部的操作方法;其次是第三个参数,这个参数指向的是中断下半部的操作方式;第三个参数是中断类型的标志,IRQF_ONESHOT代表在这次中断没有处理完之前,如果这时再来中断的话,是不会再触发中断的,这样就避免了这次中断结束了出现中断泛滥的情况。

在看看这个函数中的最后几行代码:

tsc2007_stop(ts);err = input_register_device(input_dev);if (err)goto err_free_irq;i2c_set_clientdata(client, ts);

首先是要将触摸屏暂停了,主要是关闭中断、同步、置标志等,因为下面要对触摸屏进行初始化,即内核主动对触摸屏芯片进行写操作,这个时候如果有中断到来,会调用I2C的读操作,这样I2C的读写操作就会冲突。接下来的代码主要是注册input设备和通过i2c总线对触摸屏芯片TSC2007进行主动配置。

说到这里,tsc2007的probe函数已经分析完了。

接下来咱们讨论对应的中断函数,首先看一下中断上半部的操作函数:

static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
{struct tsc2007 *ts = handle;if (!ts->get_pendown_state || likely(ts->get_pendown_state()))return IRQ_WAKE_THREAD;if (ts->clear_penirq)ts->clear_penirq();return IRQ_HANDLED;
}

这段代码主要看函数的两个返回值,返回IRQ_WAKE_THREAD这个标志代表此次中断有效,调用中断下半部处理函数进行处理,返回IRQ_HANDLED这个标志代表此次中断无效,不处理,直接返回。其实在这里这样做的意义其实不大,只是又读了一次触屏笔的状态,起到了一定的消抖作用。

下面咱们看一下中断下半部的操作函数:

static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
{struct tsc2007 *ts = handle;struct input_dev *input = ts->input;struct ts_event tc;u32 rt;//第一次调用soft中断处理函数,要进行消抖处理printk("touchscreen's pen is down!\n");msleep(1);//睡眠30ms//确实有触摸屏按下if (tsc2007_is_pen_down(ts)) {while (!ts->stopped && tsc2007_is_pen_down(ts)) {/* pen is down, continue with the measurement */tsc2007_read_values(ts, &tc);rt = tsc2007_calculate_pressure(ts, &tc);if (rt == 0 && !ts->get_pendown_state) {/** If pressure reported is 0 and we don't have* callback to check pendown state, we have to* assume that pen was lifted up.*/break;}if (rt <= ts->max_rt) {dev_dbg(&ts->client->dev,"DOWN point(%4d,%4d), pressure (%4u)\n",tc.x, tc.y, rt);input_report_key(input, BTN_TOUCH, 1);input_report_abs(input, ABS_X, tc.x);input_report_abs(input, ABS_Y, tc.y);input_report_abs(input, ABS_PRESSURE, rt);input_sync(input);} else {/** Sample found inconsistent by debouncing or pressure is* beyond the maximum. Don't report it to user space,* repeat at least once more the measurement.*/dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);}wait_event_timeout(ts->wait, ts->stopped,msecs_to_jiffies(ts->poll_period));}dev_dbg(&ts->client->dev, "UP\n");input_report_key(input, BTN_TOUCH, 0);input_report_abs(input, ABS_PRESSURE, 0);input_sync(input);}if (ts->clear_penirq)ts->clear_penirq();return IRQ_HANDLED;
}

这个函数的内容是触摸屏读取上传位置信息和键值的核心部分,咱们详细分析一下:

tsc2007_read_values(ts, &tc);rt = tsc2007_calculate_pressure(ts, &tc);

上面这两行代码分别是读取触屏位置信息和压力信息的函数。

input_report_key(input, BTN_TOUCH, 1);input_report_abs(input, ABS_X, tc.x);input_report_abs(input, ABS_Y, tc.y);input_report_abs(input, ABS_PRESSURE, rt);input_sync(input);

上面这几行代码分别是想input子系统核心层上传按键值、触屏X轴、Y轴数据、触屏压力数据和同步信号。注意,这里面上传的是触摸屏的坐标值,不是与其相配合的LCD的坐标值,不过不要担心,在驱动里面不需要转换,因为应用层操作触屏是通过tslib这个库的API接口来进行的,这个工作tslib会帮大家做的,除非你在应用层直接操作的是root/dev/input/event*的设备节点,读出来的数据是触摸屏的原始坐标数据。

wait_event_timeout(ts->wait, ts->stopped,msecs_to_jiffies(ts->poll_period));

上面这一行代码主要是等待每次读取触屏数据的时间间隔,在调试触摸屏时,这个参数也挺重要。

input_report_key(input, BTN_TOUCH, 0);input_report_abs(input, ABS_PRESSURE, 0);input_sync(input);

上面这几行主要是等到触摸屏松开时,向input子系统核心层上报的信息。
说到这里,触摸屏驱动里面需要注意的地方已经基本上完了,其他的主要是触摸屏本身的一些操作。

好了,到今天为止,nuc972的触摸屏驱动代码整体就分析忘了,希望对大家有点儿帮助,如果有什么错误,可以直接给我留言,谢谢!拜拜!

NUC972触摸屏驱动移植过程分析(三)相关推荐

  1. NUC972触摸屏驱动移植过程分析(二)

    https://blog.csdn.net/b7376811/article/details/86607529 今天继续分析NUC972的触摸屏驱动移植过程,上一节主要分析了触摸屏需要数据,今天来分析 ...

  2. NUC972触摸屏驱动移植过程分析(一)

    https://blog.csdn.net/b7376811/article/details/86514683 因为下一个项目可能会用到触摸屏,所以这段时间对触摸屏的驱动的移植进行了研究,今天正好有机 ...

  3. 9.触摸屏驱动移植实战

    转自 https://edu.csdn.net/lecturer/505 朱老师物联网大讲堂 <5.linux驱动开发-第9部分-5.9.触摸屏驱动移植实战> 第一部分.章节目录 5.9. ...

  4. 移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植

    移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植的过程记录下来: (1)首先打一个补丁:s3c2410_touchscreen.patch, 在内核解压的根目录下 patch -N ...

  5. 驱动篇:底层驱动移植(三)(摘录)

    驱动篇:底层驱动移植(三)(摘录) GPIO 驱动 在 drivers/gpio 下实现了通用的基于 gpiolib 的 GPIO 驱动,其中定义了一个通用的用于描述底层 GPIO 控制器的gpio_ ...

  6. mtk6582平台GT9157触摸屏驱动移植

    一.GT9157触摸屏移植 1.在mediatek/config/sanstar82_cwet_kk/ProjectConfig.mk中 CUSTOM_KERNEL_TOUCHPANEL=GT9XX ...

  7. FL2440移植LINUX-3.4.2 -- 按键驱动和触摸屏驱动移植

    (一)先移植按键输入子系统驱动: 拿过去编译,改错,然后insmod: (二)触摸屏驱动拿过去编译,改错,然后insmod: 触摸屏驱动的使用: 编译: tar xzf tslib-1.4.tar.g ...

  8. usb触摸屏驱动移植

    最近公司产品在原有基础上增加一个触摸功能,因电路已经定型,只有usb接口引出来,所以只能选用市面上usb接口的触摸屏,联系了多家触摸屏代理商,移植时都存在问题. 公司产品用的平台是: PXA270 + ...

  9. 2.6.36.2 s3c6410 触摸屏驱动移植。

    CSDN_Acanoe 的博客:http://blog.csdn.net/ACanoe 硬件环境:OK6410 A板,4.3 寸TFT 屏.  移植内核:Linux2.6.36.2 . 参考内核: 飞 ...

最新文章

  1. linux搭建rabbitmq环境,RabbitMQlinux-centos环境配置
  2. 最长公共子上升序列(信息学奥赛一本通-T1306)
  3. javaweb基础知识点记录1
  4. setheading指令_set命令
  5. 用VMware GSX和W2K群集服务实现Exchange群集
  6. struts2与json的整合
  7. CMMI认证是什么,级别分类有哪些?
  8. SCI分区及影响因子查看方法
  9. h5页面如何切图_html5怎么切图
  10. 老毛子Padavan网段LAN修改
  11. 【操作系统-进程】PV操作——哲学家问题
  12. paper survey之——水下图像复原与增强水下光通信
  13. 新电脑自带win11刷win10 系统之后出现的触摸屏/板失灵等问题
  14. 吉林大学 十佳歌手 计算机科学与工程学院,贾海洋 - 吉林大学 - 计算机科学与技术学院...
  15. Python数据分析19——matplotlib可视化(一)之线形图
  16. 【能效管理】关于学校预付费水电系统云平台应用分析介绍
  17. 华硕h110m主板怎么样_华硕台式机主板怎么样 华硕台式机主板多少钱【详细介绍】...
  18. 手机吃鸡语音服务器异常是怎么回事,绝地求生语音卡怎么办_绝地求生新版本语音卡解决办法介绍_游戏吧...
  19. 使用接口根据关键词取视频列表详情
  20. python访问hive数据库踩坑指南

热门文章

  1. 网页的登录和注册页面
  2. 2. 硬件基础知识学习
  3. gpgpu学习推荐书籍
  4. Mysql 循环更新
  5. 再见了 SELECT * !大厂的 MySQL 查询优化方案,确实牛逼!
  6. [学习笔记]多元线性回归分析——理解篇
  7. 计算机网络——BGP协议
  8. 数据分析师—Excel函数篇
  9. Java环境下GDAL / OGR环境配置与入门
  10. libusb系列-007-Qt下使用libusb1.0.26源码