设备树学习之(十三)电容触摸屏驱动
来源:互联网 发布:windows 10使用详解 编辑:程序博客网 时间:2024/06/03 22:04
开发板:tiny4412SDK + S702 + 4GB Flash
要移植的内核版本:Linux-4.4.0 (支持device tree)
u-boot版本:友善之臂自带的 U-Boot 2010.12
busybox版本:busybox 1.25
友善之臂提供的资料中,触摸屏驱动采用的是一线触控,但是保留了i2c接口,驱动芯片为FT5406,本文主要实现 i2c 接口的触摸屏驱动。
首先,分析下 FT5406 的基本电路接口:
基本都是通用的接口,如 I2C 接口,INT,WAKE,RST。如图:
以上可知,我们在驱动中必须定义一个中断口,来启动接收触摸数据,一个gpio脚来复位FT5406。wake:主要靠cpu发送一个唤醒指令给FT5406。
查看tiny4412原理图
再次,需确认FT5406的从地址,以便于I2C访问得到。这个可以根据FT5406数据手册查找到.
可知从地址高位必须为:3,低位必须根据 i2ccon 设定的值来确定,这点很奇怪。
我这边找到的从地址为:0x38
i2ccon 暂时未找到出处,可以用 i2c tools 探测一下
/mnt # ./i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
基本的东西确认好后,剩下的就是根据FT5406数据手册上的指令,开始写驱动了。
在此之前,我们先了解下驱动如何实现电容屏的多点触摸,其实很简单,主要需要
触摸屏IC FT5406 能够捕获多点数据,这点电容屏基本多能支持到捕获2点以上,而FT5406 可以捕获5个触摸点,编写驱动时,只要去获取这几个点的数据,然后上报就行。格式如图:
解释:
- 02h : 捕获的触摸点个数
- 03h- 1eh :对应每个点的x,y坐标数值。
- touch id 表示触点编号,对应于typeB的slot
驱动参考:Ft6236.c (drivers\input\touchscreen)
touch_demo{ compatible = "tiny4412,touch_demo"; interrupts = <6 0>; interrupt-parent = <&gpx1>; status = "okay";};
&i2c_1{ status = "okay"; touch@38{ compatible = "tiny4412,touch"; reg = <0x38>; };};
#include <linux/kernel.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/i2c.h>#include <linux/err.h>#include <linux/regmap.h>#include <linux/slab.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <linux/delay.h>#include <linux/gpio/consumer.h>#include <linux/input.h>#include <linux/input/mt.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/property.h>#include <linux/of_gpio.h>#define uchar unsigned charstatic void touch_read_handler(struct work_struct *work);DECLARE_WORK(touch_read_work, touch_read_handler);static struct i2c_client *touch_client;static struct input_dev *touch_dev;static int irq;static void touch_read(unsigned char sAddr, unsigned char *buf, unsigned int len){ struct i2c_msg msg[2]; int i, ret; unsigned char address; for (i = 0; i < len; i++) { /* 先写入要读取的寄存器地址 */ address = sAddr + i; msg[0].addr = touch_client->addr; /* 目的 */ msg[0].buf = &address; /* 源 */ msg[0].len = 1; /* 地址=1 byte */ msg[0].flags = 0; /* 表示写 */ /* 然后启动读操作 */ msg[1].addr = touch_client->addr; /* 源 */ msg[1].buf = &buf[i]; /* 目的 */ msg[1].len = 1; /* 数据=1 byte */ msg[1].flags = I2C_M_RD; /* 表示读 */ ret = i2c_transfer(touch_client->adapter, msg, 2); if (ret < 0) { printk("i2c_transfer eror\n"); } mdelay(10); }}static void touch_read_handler(struct work_struct *work){ unsigned char buf[13]; unsigned char touches, i, event, id; unsigned short x, y; bool act; /* read tp resister by i2c */ touch_read(0x00, buf, 13); /* number of touch points */ touches = buf[2] & 0x0f; //printk("point num %d\n", touches); if (touches > 2) { printk("%s touch read touches error\n",__func__); touches = 2; } for (i = 0; i < touches; i++) { y = ((buf[5 + i * 6] & 0x0f) << 8) | buf[6 + i * 6]; x = ((buf[3 + i * 6] & 0x0f) << 8) | buf[4 + i * 6]; //printk("%d point x:%08d y:%08d\n", i, x, y); event = buf[3 + i * 6] >> 6; //event flags id = buf[5 + i * 6] >> 4; //touch id //printk("event %d id %d\n", event, id); //down or contact act = (event == 0x00 || event == 0x02); input_mt_slot(touch_dev, id); input_mt_report_slot_state(touch_dev, MT_TOOL_FINGER, act); //if up return if (!act) continue; input_report_abs(touch_dev, ABS_MT_POSITION_X, x); input_report_abs(touch_dev, ABS_MT_POSITION_Y, y); } input_mt_sync_frame(touch_dev); input_sync(touch_dev);}static irqreturn_t touch_isr(int irq, void *dev_id){ schedule_work(&touch_read_work); return IRQ_HANDLED;}static int touch_probe(struct i2c_client *client, const struct i2c_device_id *id){ unsigned char buf; int ret; touch_client = client; printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); touch_read(0xa3, &buf, 1); printk("Chip vendor ID %x\n", buf); touch_read(0xa6, &buf, 1); printk("Firmware ID %x\n", buf); touch_read(0xa8, &buf, 1); printk("CTPM Vendor ID %x\n", buf); touch_read(0x00, &buf, 1); printk("DEVIDE_MODE %x\n", buf); touch_read(0x80, &buf, 1); printk("ID_G_THGROUP. %x\n", buf); touch_read(0x88, &buf, 1); printk("ID_G_PERIODACTIVE. %x\n", buf); touch_dev = input_allocate_device(); if (touch_dev == NULL) { printk("%s, allocate input device, error\n", __func__); return -1; } //告诉input能够支持哪些事件 input_set_abs_params(touch_dev, ABS_MT_POSITION_X, 0, 800, 0, 0); input_set_abs_params(touch_dev, ABS_MT_POSITION_Y, 0, 480, 0, 0); ret = input_mt_init_slots(touch_dev, 2, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); if (ret) { printk("%s, input_mt_init_slots error\n", __func__); return ret; } touch_dev->name = "touch"; touch_dev->id.bustype = BUS_I2C; touch_dev->dev.parent = &(touch_client)->dev; ret = input_register_device(touch_dev); if (ret) { printk("%s, register input device, error\n", __func__); return ret; } printk("irq is %d\n", irq); ret = devm_request_threaded_irq(&touch_client->dev, irq, touch_isr, NULL, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "touch1", NULL); if (ret < 0) { printk("failed to request_irq %d\n", ret); } return 0;}static int touch_remove(struct i2c_client *client){ return 0;}static const struct i2c_device_id touch_id_table[] ={ { "touch", 0 }, {}};/* 1. 分配/设置i2c_driver */static struct i2c_driver touch_driver ={ .driver = { .name = "touch", .owner = THIS_MODULE, }, .probe = touch_probe, .remove = touch_remove, .id_table = touch_id_table,};static int int_demo_remove(struct platform_device *pdev) { printk("%s enter.\n", __func__); return 0;}static int int_demo_probe(struct platform_device *pdev) { irq = platform_get_irq(pdev, 0); printk("int_demo_probe %d\n", irq); return 0;}static const struct of_device_id touch_demo_dt_ids[] = { { .compatible = "tiny4412,touch_demo", }, {},};MODULE_DEVICE_TABLE(of, touch_demo_dt_ids);static struct platform_driver touch_demo_driver = { .driver = { .name = "touch_demo", .of_match_table = of_match_ptr(touch_demo_dt_ids), }, .probe = int_demo_probe, .remove = int_demo_remove,};static int touch_drv_init(void){ int ret; /* 1.注册平台设备驱动 */ ret = platform_driver_register(&touch_demo_driver); if (ret) printk(KERN_ERR "int demo: probe failed: %d\n", ret); /* 2. 注册i2c_driver */ i2c_add_driver(&touch_driver); return 0;}static void touch_drv_exit(void){ i2c_del_driver(&touch_driver); platform_driver_unregister(&touch_demo_driver);}module_init(touch_drv_init);module_exit(touch_drv_exit);MODULE_LICENSE("GPL");
- 设备树学习之(十三)电容触摸屏驱动
- 设备树学习之(十三)电容触摸屏驱动
- Android电容触摸屏驱动
- 电容触摸屏驱动分析
- LINUX设备驱动之触摸屏驱动
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- 【Linux开发】linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
- 电容触摸屏驱动---基于FT5406
- 电容触摸屏驱动---基于FT5406
- 电容触摸屏驱动---基于FT5406
- 电容触摸屏驱动---基于FT5406
- 电容触摸屏驱动---基于FT5406
- mysql表关联中的索引使用情况
- SQLSERVER查询整个数据库中某个特定值所在的表和字段的方法
- 自定义log4j日志文件命名规则
- TextView显示不同大小字体
- 解决Android软键盘弹出 布局内指定内容上移实现
- 设备树学习之(十三)电容触摸屏驱动
- CentOS 安装oracle数据库(终于搞通了~~)
- GreenDao3.0简单使用
- 二分法查找
- C# 线性表之顺序存储结构
- Eclipse 配置Tomcat 404 解决方法
- 红外解码控制数码管
- Linux进度条小程序及背景知识简述
- 如何给Eclipse添加一个JDK或JRE