Rockchip平台TP驱动详解综述分析
- 格式:docx
- 大小:48.63 KB
- 文档页数:25
【驱动】TP电容屏驱动—3.TP报点协议AB之2.多点触控协议(MTP)多点触控协议(MTP)转载:https:///paul_liao/article/details/7085542作者翻译⽔平有限,欢迎指正,感谢好友lapset和leo的帮助!Multi-touch (MT) Protocol-------------------------Copyright (C)2009-2010Henrik Rydberg<rydberg@euromail.se>Introduction------------In order to utilize the full power of thenew multi-touch and multi-user devices, a way to report detailed data frommultiple contacts, i.e., objects in direct contact with the device surface, isneeded. This document describes themulti-touch (MT) protocol which allows kernel drivers to report details for anarbitrary number of contacts.为了使⽤功能强⼤的多点触控设备,⼀种⽅案是上报多触点的详细数据。
本⽂档所描述的多点触控协议(MTP)可以让内核驱动向⽤户层上报任意多个触点的数据信息。
The protocol is divided into two types,depending on the capabilities of the hardware. For devices handling anonymouscontacts (type A), the protocol describes how to send the raw data for allcontacts to the receiver. For devices capable of tracking identifiable contacts(type B), the protocol describes how to send updates for individual contacts viaevent slots.根据硬件功能,此协议分为两种类型。
单模光纤模块驱动芯片-概述说明以及解释1.引言1.1 概述单模光纤模块驱动芯片是一种关键性的元件,它在单模光纤通信系统中起到了至关重要的作用。
本文将重点探讨单模光纤模块驱动芯片的原理、应用领域和作用,并对它的重要性和发展前景进行分析。
首先,我们先来了解一下什么是单模光纤模块。
单模光纤模块是一种用于传输光信号的组件,它具有较小的核心直径,能够实现高速、长距离的光信号传输。
与多模光纤模块相比,单模光纤模块在光信号传输方面具有更好的性能,因此在许多领域得到广泛应用。
单模光纤模块驱动芯片作为单模光纤模块的控制和驱动核心,扮演着至关重要的角色。
它主要用于控制光信号的发射和接收过程,将电信号转换成光信号并进行调制。
在单模光纤通信系统中,单模光纤模块驱动芯片的性能将直接影响到系统的传输质量和可靠性。
单模光纤模块驱动芯片的应用领域非常广泛。
首先,在通信领域,它被广泛应用于光纤通信系统中,包括光纤传输网、光纤宽带接入网络等。
其次,在工业控制领域,它也被广泛应用于激光加工、光纤传感器等领域。
此外,在医疗、军事等领域,单模光纤模块驱动芯片也发挥着重要的作用。
总的来说,单模光纤模块驱动芯片在单模光纤通信系统中具有举足轻重的作用。
它不仅能够实现高速、长距离的光信号传输,还能够保证系统的稳定性和可靠性。
随着科技的不断进步,单模光纤模块驱动芯片的发展前景也非常广阔。
未来,我们可以预见,在通信、工业控制、医疗等领域,单模光纤模块驱动芯片将发挥更加重要的作用,并为社会的进步和发展做出更大的贡献。
1.2文章结构文章结构本篇文章主要由引言、正文和结论三部分组成。
1. 引言- 1.1 概述:简要介绍单模光纤模块驱动芯片的背景和作用。
- 1.2 文章结构:本部分,给出文章整体的结构和各个部分的内容概述。
- 1.3 目的:明确本文的目的和意义。
2. 正文- 2.1 单模光纤模块的基本原理:详细介绍单模光纤模块的工作原理和关键技术。
- 2.2 单模光纤模块的应用领域:探讨单模光纤模块在通信、传感等领域的广泛应用。
密级状态:绝密()秘密()内部(√)公开()RK平台Realtek WiFi驱动移植说明(系统产品一部)文件状态:[]正在修改[√]正式发布当前版本:V1.0作者:胡卫国完成日期:2015-03-13审核:完成日期:福州瑞芯微电子有限公司Fuzhou Rockchips Semiconductor Co.,Ltd(版本所有,翻版必究)版本历史版本号作者修改日期修改说明备注V1.0胡卫国2015-03-13初始版本目录1REALTEK驱动基本情况说明 (2)2WIFI驱动移植 (3)2.1WIFI驱动入口函数 (3)2.2电源控制及SDIO识别操作 (4)2.3M AKEFILE配置修改 (5)2.4使用自定义W I F I MAC地址 (6)3BT固件更新 (7)1Realtek驱动基本情况说明Realtek系列WiFi BT芯片,如RTL8188EU,RTL8189ES,RTL8723系列,驱动移植包都是类似的目录结构,驱动代码目录结构也类似。
以RTL8188EUS_RTL8189ES_linux_v4.1.8_9499.20131104.zip为例解压之后里面包含文档、驱动源码包、android reference代码等内容,具体如下:Android部分RK一般都已经移植好集成到SDK中,由于Realtek驱动更新比较频繁,所以客户最常遇到的事情就是更新WiFi驱动。
2WiFi驱动移植可对比SDK Kernel中已经移植好的驱动与Realtek的驱动进行合并。
驱动在以下目录drivers/net/wireless/rockchip_wlan/针对kernel3.10版本drivers/net/wireless/针对kernel3.0版本2.1wifi驱动入口函数Realtek提供的驱动入口函数为:module_init(rtw_drv_entry);module_exit(rtw_drv_halt);在以下文件中:os_dep\linux\sdio_intf.c针对sdio接口wifios_dep\linux\usb_intf.c针对usb接口wifiRK平台做了稍微修改,主要是为了增加RK版本信息打印及wifi gpio电源控制,启动sdio 识别。
本文描述在RK3126平台上添加一个新的TP驱动(gslx680驱动)以及详细的• 1• 2• 3• 4• 5• 6•7•8•9•10•11•12•13•14•15•16•17•18•19•20•21•22表示i2c2总线上下挂在了多个i2c设备。
其中ts@40是表示此i2c设备的设备类型为触摸屏,设备地址为0x40(7位地址,注意:在i2c的传输函数中,会将此地址左移一位,因此实际上gslx680的i2c 设备地址为0x80)。
该节点下有多个属性:1、compatible = "gslX680";属性用于驱动和设备的绑定。
表示特定的设备名称,此处为gslX680;2、reg = <0x40>;属性表示此设备的i2c地址为0x40,等同于@40;3、wake-gpio = <&gpio0 GPIO_D3 GPIO_ACTIVE_LOW>;表示复位引脚使用的是GPIO0 中的GPIO_D3这个引脚,低电平有效。
irp-gpio = <&gpio0 GPIO_A2 IRQ_TYPE_LEVEL_HIGH>;表示中断引脚使用的是GPIO0中的GPIO_A2这个引脚,高电平触发。
很奇怪,为什么这里没有上电的信息,以及在整个驱动程序中都没有给ic上电的操作。
在前面的MTK平台上的tp驱动都有上电的动作,暂时还搞不懂在RK 平台上为什么没有。
4、revert_x = <0>; revert_y = <0>;标记x和y是否需要翻转。
在上述的信息中,可以通过of接口获取到属性对应的值。
在后面的probe()函数中就会使用到。
注:关于dts的详细信息可以查看ARM Linux 3.x的设备树(Device Tree)和Device Tree Usage2、修改Makefile、Kconfig、defconfig(1)、修改Makefile添加gslx680驱动在drivers/input/touchscreen/Makefile中添加驱动:obj-$(CONFIG_TOUCHSCREEN_GSLX680) += gslx680/。
TenProtect(TP)驱动保护原理过 DNF TP 驱动保护(⼀)⽂章⽬录:01. 博⽂简介:02. 环境及⼯具准备:03. 分析 TP 所做的保护:04. ⼲掉 NtOpenProcess 中的 Deep InLine Hook:05. ⼲掉 NtOpenThread 中的 Deep InLine Hook:06. ⼲掉 NtReadVirtualMemory 中的 InLine Hook:07. ⼲掉 NtWriteVirtualMemory 中的 InLine Hook:08. ⼲掉 KiAttachProcess 的 InLine Hook:09. ⼲掉 NtGetContextThread 中的 InLine Hook:10. ⼲掉 NtSetContextThread 中的 InLine Hook:11. ⼲掉 DbgkpQueueMessage 中的 InLine Hook:12. ⼲掉 DbgkpSetProcessDebugObject 中的 InLine Hook:13. ⼲掉 Debug 清零:共四篇,本篇为第⼀篇。
01. 博⽂简介:本篇博⽂仅仅是我对过 TP 保护所作的⼀个总结,⾥⾯没有啥⾼深的技术,仅仅是 Hook ⽽已,并且只有些 InLine Hook 和 SSDT Hook 的代码,这些对⼤⽜⽽⾔都是⼩菜⼀碟,所以⼤⽜们可以直接飘过咯 ^_^然后就是关于本篇博⽂,估计会⽐较长,所以我会按照上⾯的⽬录分出来⼀,⼆,三,四篇相继发表。
我先来装回逼科普下 TP 吧,直接从百度百科抄袭点过来:TP 系统全称 TenProtect,是由腾讯⾃主研发推出的安全系统,可以有效保护游戏不受外挂侵犯,同时具备反⽊马盗号功能,能有效的防⽌⽤户游戏帐号和虚拟财产被窃取。
腾讯 TP 系统主要作⽤为外挂检测、反盗号、反⾮法⼯作室、防⾮法消息。
具体功能如下:反注⼊:TP系统能有效的阻⽌⾮法模块对游戏进⾏注⼊;反加速:TP系统能防⽌游戏客户端的⾮法加速功能;反模拟按键:TP系统能有效阻⽌模拟按键程序;反脱机: TP系统能针对⾮正常登录游戏的⾏为进⾏检测;反调试: TP系统采⽤内核级反调试技术,保护游戏进程不被调试和分析;反⽊马: TP系统可以保护玩家帐号不被⽊马程序窃取;检测外挂功能:TP系统能对外挂功能进⾏检测;指令混淆: TP系统能对正常指令进⾏虚拟和变形,加⼤外挂作者逆向难度;特征匹配: TP系统采⽤特征码匹配技术,能准确检测到外挂的使⽤;⽂件校验:TP系统可以准确检测游戏⽬录下的⽂件是否被第三⽅程序篡改;游戏内存数据校验: TP系统所特有技术⼿段可以准确感知到游戏关键数据的异常;游戏进程保护: TP系统可以保护游戏进程不被第三⽅程序读写;游戏虚拟财产保护:在玩家因不当操作引起帐号泄漏情况下,TP系统也可以保护玩家帐号内虚拟财产不被不法份⼦转移;我⼏个⽇⼦弄了过 TP 的驱动保护,算下来前前后后也弄了半来个⽉,虽然⽐较累,但还是收获了蛮多东西,这篇博⽂就是将如何过掉 TP 做的⼀个总结⽽已,在这篇⽂章中我会⼀⼀介绍过掉 TP 所 Hook 的各种 API 的思路,并附上简要的代码,在过 TP 驱动保护的过程中以及⼀些思路和⼀些代码也很⼤程度上都是来⾃国内的⼏⼤论坛,主要是看雪,⼀蓑烟⾬,DebugMan 等论坛,这⾥对我所借鉴的那些哥们说 Many Thanks。
UBOOTPHY驱动分析及调试⽅法UBOOT版本:2017.11⼀、PHY 简介M edia I ndependent I nterface ( MII ),介质独⽴接⼝,起初是定义 100M 以太⽹(Fast Ethernet)的MAC层与PHY 芯⽚之间的传输标准。
MAC 与 PHY 之间的 MII 连接可以是可插拔的连接器,或者是同⼀块 PCB 上 MAC 与 PHY 之间的⾛线。
MDIO与MDCLK是 MII 接⼝的⼀部分,⼆者可称为SMI (Serial Management Interface) 串⾏管理接⼝,⽤于在 MAC 和 PHY 之间传递配置信息。
在 MDIO 规范中定义 PHY 地址为5 bit,即同⼀组MDIO最多可配置 2^5 = 32个 PHY。
MII 接⼝图如下所⽰:能够和MII相提并论的还有RMII(精简MII)、SMII(串⾏MII)、GMII(千兆MII)、RGMII(精简GMII)等接⼝,它们与普通MII相⽐较,仅是传输速率与数据传输⽅式不同等,这⾥不做过多的介绍。
⼆、PHY 设备创建及驱动匹配以 rockchip 为例,当它的 mac 驱动 gmac_rockchip 成功的被匹配时,会调⽤到 gmac_rockchip_probe ,mac 相关我们不做分析,直接进⼊主题 designware_eth_probe 函数中。
⾸先会获取到对应的 regulator ,并会做⼀些电源配置,1 device_get_supply_regulator(dev, "phy-supply",2 &phy_supply);3 regulator_set_enable(phy_supply, true);UBOOT 中引⼊了 DM 驱动模型,相关的设备与驱动事先已经绑定过,如这⾥通过 phandle 进⽽找出其对应的,驱动在 rk8xx.c 中定义:1 U_BOOT_DRIVER(rk8xx_switch) = {2 .name = "rk8xx_switch",3 .id = UCLASS_REGULATOR,4 .ops = &rk8xx_switch_ops,5 .probe = rk8xx_switch_probe,6 };接下来要初始化 mdio 总线,并将其注册到系统的 mii_devs 中,在获取某个控制器时,即可通过 miiphy_get_dev_by_name 来获取:1 dw_mdio_init(dev->name, dev);2 priv->bus = miiphy_get_dev_by_name(dev->name);电源以及 MDIO 总线已初始化完毕,万事俱备,接下来就正式的对 phy 进⾏操作了,⼀起来看 dw_phy_init 函数:1static int dw_phy_init(struct dw_eth_dev *priv, void *dev)2 {3struct phy_device *phydev;4int mask = 0xffffffff, ret;56 #ifdef CONFIG_PHY_ADDR7 mask = 1 << CONFIG_PHY_ADDR;8#endif910 phydev = phy_find_by_mask(priv->bus, mask, priv->interface);11if (!phydev)12return -ENODEV;1314 phy_connect_dev(phydev, dev);1516 phydev->supported &= PHY_GBIT_FEATURES;17if (priv->max_speed) {18 ret = phy_set_supported(phydev, priv->max_speed);19if (ret)20return ret;21 }22 phydev->advertising = phydev->supported;2324 priv->phydev = phydev;25 phy_config(phydev);2627return0;28 }我们主要来看 phy_find_by_mask ,这⾥是核⼼,其它细节配置不去分析以免喧宾夺主。
TP驱动运行流程分析目录1.前论 (2)2.内核编程特点 (3)3.内核头文件及宏说明 (4)4.GT9系列驱动代码详细分析 (4)4.1函数goodix_ts_init() (4)4.1.1注册工作队列 (4)4.1.2注册i2c设备 (5)4.2函数goodix_ts_probe() (5)4.2.1测试I2C适配器能力 (5)4.2.2分配空间kzalloc() (5)4.2.3绑定工作队列函数 (6)4.2.4申请锁机制 (6)4.2.5申请IO口及上电复位 (6)4.2.6测试I2C通信 (8)4.2.7固件升级 (8)4.2.8初始化TP信息 (9)4.2.9注册输入设备 (9)4.2.10申请中断 (9)4.2.11读取版本号 (10)4.2.12创建读写节点 (10)4.3中断及轮询机制添加工作 (10)4.4最主要的工作函数goodix_ts_work_func() (11)4.4.1查找私有结构体数据 (11)4.4.2查看是否滑动唤醒 (11)4.4.3获取触摸信息 (11)4.4.4查看按键信息 (12)4.4.5报点方式 (12)4.4.6状态重置 (12)4.5其他函数功能 (12)4.5.1函数goodix_ts_early_suspend() (12)4.5.2函数gtp_enter_doze() (13)4.5.3函数goodix_ts_late_resume() (13)4.5.4函数gtp_irq_enable() (13)4.6退出及移除函数 (13)5.系统流程图 (13)5.1系统流程图 (14)5.2ESD保护机制流程图 (15)5.3滑动唤醒流程图 (15)6.自动升级流程简介 (16)7.Goodix_flashless相关信息 (16)7.1flashless简介 (16)7.2flashless相关函数及流程图 (16)7.2.1gtp_flashless_init()函数 (16)7.2.2工作函数goodix_ts_work_func() (18)1.前论以下内容按照驱动运行流程编写:优点是内容详细,基本上的函数都说明到位了。
【转】MTKTP驱动移植对于MTK TP驱动移植⼀般分为六部分:1、硬件IO⼝配置;2、TP驱动移植;3、I2C通信;4、中断触发;5、数据上报;6、虚拟按键;硬件电路:1、GPIO配置打开 mediatek\dct\DrvGen.exe选择 mediatek\custom\xiaoxi\kernel\dct\dct\codegen.dws 配置⽂件配置EINT7_CTP引脚、CTP_RST复位引脚2、TP驱动移植(以ft5x16为例)在\mediatek\custom\common\kernel\touchpanel⽬录下创建ft5x16,将供应商提供的驱动驱动资料拷贝到该⽬录下;修改配置⽂件:mediatek\config\prj\ProjectConfig.mk下的CUSTOM_KERNEL_TOUCHPANEL其值由改为ft5x16,表明对应ft5x16⼦⽬录;打开ft5x16.c⽂件,修改⼀下:1static struct i2c_board_info __initdata ft5x16_i2c_tpd={ I2C_BOARD_INFO("ft5x16", (0x70>>1))}; //"ft5x16"为设备名,设备地址为⾼7位23static struct tpd_driver_t tpd_device_driver = {4 .tpd_device_name = "FT5x16",5 .tpd_local_init = tpd_local_init,6 .suspend = tpd_suspend,7 .resume = tpd_resume,8 #ifdef TPD_HAVE_BUTTON9 .tpd_have_button = 1,10#else11 .tpd_have_button = 0,12#endif13 };1415/* called when loaded into kernel */16static int __init tpd_driver_init(void) {17 printk("MediaTek FT5x16 touch panel driver init\n");18/* 注册板级设备信息 */19 i2c_register_board_info(IIC_PORT, &ft5x16_i2c_tpd, 1); //IIC_PORT表⽰i2c控制器号,由电路原理图可知TP设备连接到i2c控制器0,ft5x16_i2c_tpd为i2c设备结构,1表⽰该i2c_board_info个数20if(tpd_driver_add(&tpd_device_driver) < 0)21 printk("add FT5x16 driver failed\n");22return0;23 }重新编译:./mk n k && ./mk bootimage3、I2C通信新驱动编译进内核,启动内核后,我们怎样验证i2c接⼝能够正常通信呢?系统启动后通过串⼝或adb shell进⼊系统命令⾏窗⼝,查询/sys/bus/i2c/devices⽬录下是否有0-0038信息,查询/sys/bus/i2c/drivers⽬录下是否存在‘ft5x16’设备名;先保证i2c能够正常通信;4、中断触发中断注册函数:mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1);//tpd_eint_interrupt_handler函数为中断回调函数5、数据上报当触摸屏产⽣中断的时候就会调⽤到该接⼝;然后在中断处理函数中唤醒运⾏在⼦线程中的等待队列,再通过⼦线程获取TP数据并上报到系统;1static DECLARE_WAIT_QUEUE_HEAD(waiter); //初始化等待队列23 thread = kthread_run(touch_event_handler, 0, TPD_DEVICE); //新建线程45static int touch_event_handler(void *unused)6 {7 ......8do9 {10 mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);11 set_current_state(TASK_INTERRUPTIBLE);12 wait_event_interruptible(waiter,tpd_flag!=0); //等待队列进⼊休眠,等待唤醒13 tpd_flag = 0;14 set_current_state(TASK_RUNNING);15 ......16if (tpd_touchinfo(&cinfo, &pinfo)) //获取TP数据17 {18//TPD_DEBUG("point_num = %d\n",point_num);19 TPD_DEBUG_SET_TIME;20if(point_num >0)21 {22for(i =0; i<point_num; i++)//only support 3 point23 {24 cinfo.x[i] = cinfo.x[i];25 cinfo.y[i] = cinfo.y[i];2627 tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]); //上报按下数据28 printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);29 }30 input_sync(tpd->dev);31 }32else33 {34 tpd_up(cinfo.x[0], cinfo.y[0]); //上报弹起数据35//TPD_DEBUG("release --->\n");36//input_mt_sync(tpd->dev);37 input_sync(tpd->dev);38 }39 }40 ......4142 }while(!kthread_should_stop());4344return0;45 }TP数据可以通过打印的⽅式进⾏查看,也可以激活‘系统设置’中‘开发者选项’的‘指针位置’,现在触摸操作在LCD的轨迹,也可以在packages\apps\Launcher2\src\com\android\launcher2\Launcher.java的onCreate⽅法最后添加Settings.System.putInt(this.getContentResolver(),Settings.System.POINTER_LOCATION, 1); 在Launcher中开启‘指针位置’功能(需要mm Launcher模块并重新打包和烧录system.img⽂件);注:如果TP获取到的数据⽐较乱的时候建议通过打开‘指针位置’功能进⾏查看,排除TP固件分辨与LCD没对应等问题;6、虚拟按键1static struct tpd_driver_t tpd_device_driver = {2 .tpd_device_name = "FT5x16",3 .tpd_local_init = tpd_local_init,4 .suspend = tpd_suspend,5 .resume = tpd_resume,6 #ifdef TPD_HAVE_BUTTON7 .tpd_have_button = 1,8#else9 .tpd_have_button = 0,10#endif11 };从tpd_driver_t结构可知tpd_have_button成员为虚拟按键标志位;由宏TPD_HAVA_BUTTON开关决定的,宏定义在tpd_custom_fts.h中;在tpd_custom_fts.h中定义了⼀系列关于虚拟按键的宏:#define TPD_HAVE_BUTTON //虚拟按键开关#define TPD_BUTTON_WIDTH (200) //按键宽度#define TPD_BUTTON_HEIGH (100) //按键⾼度#define TPD_KEY_COUNT 3 //按键个数#define TPD_KEYS {KEY_MENU, KEY_HOMEPAGE, KEY_BACK} //按键对应的功能#define TPD_KEYS_DIM {{80,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {240,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}, {400,900,TPD_BUTTON_WIDTH,TPD_BUTTON_HEIGH}} //按键对应位置TPD_KEYS_DIM中的坐标是该按键区域的中⼼点:TP驱动简要分析1static struct tpd_driver_t tpd_device_driver = {2 .tpd_device_name = FT5x16,3 .tpd_local_init = tpd_local_init, //初始化函数4 .suspend = tpd_suspend,5 .resume = tpd_resume,6 #ifdef TPD_HAVE_BUTTON7 .tpd_have_button = 1,8#else9 .tpd_have_button = 0,10#endif11 };1213/* called when loaded into kernel */14static int __init tpd_driver_init(void) {15 printk("MediaTek FT5x16 touch panel driver init\n");16 i2c_register_board_info(0, &ft5x16_i2c_tpd, 1); //注册板级设备信息17if(tpd_driver_add(&tpd_device_driver) < 0) //添加驱动18 printk("add FT5x16 driver failed\n");19return0;20 }MTK⾃⼰编写了⼀套TP框架,通过该框架管理TP设备,tpd_driver_add为框架的接⼝之⼀;系统通过tpd_driver_add添加驱动后会回调tpd_local_init函数;1 #ifdef TPD_HAVE_BUTTON2static int tpd_keys_local[TPD_KEY_COUNT] = TPD_KEYS; //存放按键功能信息3static int tpd_keys_dim_local[TPD_KEY_COUNT][4] = TPD_KEYS_DIM; //存放虚拟按键信息4#endif56static int tpd_local_init(void)7 {8 TPD_DMESG("FTS I2C Touchscreen Driver (Built %s @ %s)\n", __DATE__, __TIME__);910if(i2c_add_driver(&tpd_i2c_driver)!=0) //注册i2c驱动11 {12 TPD_DMESG("FTS unable to add i2c driver.\n");13return -1;14 }15if(tpd_load_status == 0)16 {17 TPD_DMESG("FTS add error touch panel driver.\n");18 i2c_del_driver(&tpd_i2c_driver);19return -1;20 }2122 #ifdef TPD_HAVE_BUTTON //如果定义虚拟按键,则初始化按键信息23 tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data24#endif2526#if (defined(TPD_WARP_START) && defined(TPD_WARP_END))27 TPD_DO_WARP = 1;28 memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT*4);29 memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT*4);30#endif3132#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))33 memcpy(tpd_calmat, tpd_def_calmat_local, 8*4);34 memcpy(tpd_def_calmat, tpd_def_calmat_local, 8*4);35#endif36 TPD_DMESG("end %s, %d\n", __FUNCTION__, __LINE__);37 tpd_type_cap = 1;38return0;39 }向系统注册i2c驱动后,如果找到对应的设备就会调⽤tpd_probe函数;1static const struct i2c_device_id ft5x16_tpd_id[] = {{TPD_NAME,0},{}};23static struct i2c_driver tpd_i2c_driver = {4 .driver = {5 .name = TPD_NAME,6 },7 .probe = tpd_prob,8 .remove = __devexit_p(tpd_remove),9 .id_table = ft5x16_tpd_id,10 .detect = tpd_detect,11 };1213static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)14 {15int retval = TPD_OK;16char data;17 u8 report_rate=0;18int err=0;19int reset_count = 0;20 u8 chip_id,i;2122 reset_proc:23 i2c_client = client;24 #ifdef MAIERXUN_TP_COM25if(touchpanel_flag){26return0;27 }28#endif29//复位30//power on, need confirm with SA31 mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);32 mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);33 mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);34 msleep(5);35 TPD_DMESG(" fts ic reset\n");3637//打开TP电源38 #ifdef TPD_POWER_SOURCE_CUSTOM39 hwPowerOn(TPD_POWER_SOURCE_CUSTOM, VOL_3300, "TP");40#else41 hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_3300, "TP");42#endif4344 mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);45 mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);46 mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);4748 #ifdef TPD_CLOSE_POWER_IN_SLEEP49 hwPowerDown(TPD_POWER_SOURCE,"TP");50 hwPowerOn(TPD_POWER_SOURCE,VOL_3300,"TP");51 msleep(100);5253#else /* 结束复位 */54 mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);55 mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);56 mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);57 msleep(5);58 TPD_DMESG(" fts ic reset\n");59 mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);60 mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);61 mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);62#endif6364/* 初始化中断引脚 */65 mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);66 mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);67 mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE);68 mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);6970/* 中断配置和注册 */71 mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);72 mt_eint_registration(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE, tpd_eint_interrupt_handler, 1); //注册中断处理函数,TP产⽣中断时就会回调tpd_eint_interrupt函数73 mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);7475 msleep(400);7677 err=i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &data);7879 TPD_DMESG("gao_i2c:err %d,data:%d\n", err,data);80if(err< 0 || data!=0)// reg0 data running state is 0; other state is not 081 {82 TPD_DMESG("I2C transfer error, line: %d\n", __LINE__);83 #ifdef TPD_RESET_ISSUE_WORKAROUND84if ( reset_count < TPD_MAX_RESET_COUNT )85 {86 reset_count++;87goto reset_proc;88 }89#endif90//add at 20150330 by zhu91 #ifdef MAIERXUN_TP_COM92 touchpanel_flag=false;93#endif94return -1;95 }9697 ......9899 #ifdef VELOCITY_CUSTOM_FT5206100if((err = misc_register(&tpd_misc_device))) //注册混杂设备驱动101 {102 printk("mtk_tpd: tpd_misc_device register failed\n");103104 }105#endif106107 #ifdef TPD_AUTO_UPGRADE108 printk("********************Enter CTP Auto Upgrade********************\n");109 fts_ctpm_auto_upgrade(i2c_client);110#endif111 thread = kthread_run(touch_event_handler, 0, TPD_DEVICE); //创建⼦线程,通过该⼦线程获取和上报数据112if (IS_ERR(thread))113 {114 retval = PTR_ERR(thread);115 TPD_DMESG(TPD_DEVICE " failed to create kernel thread: %d\n", retval);116 }117118 TPD_DMESG("FTS Touch Panel Device Probe %s\n", (retval < TPD_OK) ? "FAIL" : "PASS");119120/* 初始化TP的P-sensor功能,暂不分析 */121 #ifdef TPD_PROXIMITY122struct hwmsen_object obj_ps;123124 obj_ps.polling = 0;//interrupt mode125 obj_ps.sensor_operate = tpd_ps_operate;126if((err = hwmsen_attach(ID_PROXIMITY, &obj_ps)))127 {128 APS_ERR("proxi_fts attach fail = %d\n", err);132 APS_ERR("proxi_fts attach ok = %d\n", err);133 }134#endif135136 #ifdef MAIERXUN_TP_COM137 touchpanel_flag=true;138#endif139140return0;141142 }/* 中断处理函数 */1static void tpd_eint_interrupt_handler(void)2 {3//TPD_DEBUG("TPD interrupt has been triggered\n");4 TPD_DEBUG_PRINT_INT;5 tpd_flag = 1;6 wake_up_interruptible(&waiter); //唤醒等待队列7 }中断处理遵循中断上下⽂的设计原则,使得中断⼦程序只是简单唤醒等待队列就可以了,没有多余的操作;/* ⼦线程处理函数 */1static int touch_event_handler(void *unused)2 {3struct touch_info cinfo, pinfo;4int i=0;56struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };7 sched_setscheduler(current, SCHED_RR, ¶m);89 #ifdef TPD_PROXIMITY10int err;11 hwm_sensor_data sensor_data;12 u8 proximity_status;1314#endif15 u8 state;1617do//进⼊while循环进⾏睡眠-等待唤醒的操作18 {19 mt_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM); //中断使能(解除屏蔽)20 set_current_state(TASK_INTERRUPTIBLE);21 wait_event_interruptible(waiter,tpd_flag!=0); //进⼊睡眠等待唤醒2223 tpd_flag = 0;2425 set_current_state(TASK_RUNNING);26 ......2728 #ifdef TPD_PROXIMITY //TP的P-sensor功能,暂不分析29if (tpd_proximity_flag == 1)30 {31 i2c_smbus_read_i2c_block_data(i2c_client, 0xB0, 1, &state);32 TPD_PROXIMITY_DEBUG("proxi_5206 0xB0 state value is 1131 0x%02X\n", state);3334if(!(state&0x01))35 {36 tpd_enable_ps(1);37 }3839 i2c_smbus_read_i2c_block_data(i2c_client, 0x01, 1, &proximity_status);40 TPD_PROXIMITY_DEBUG("proxi_5206 0x01 value is 1139 0x%02X\n", proximity_status);4142if (proximity_status == 0xC0)43 {44 tpd_proximity_detect = 0;45 }46else if(proximity_status == 0xE0)47 {48 tpd_proximity_detect = 1;49 }5051 TPD_PROXIMITY_DEBUG("tpd_proximity_detect 1149 = %d\n", tpd_proximity_detect);5253if ((err = tpd_read_ps()))54 {55 TPD_PROXIMITY_DMESG("proxi_5206 read ps data 1156: %d\n", err);56 }57 sensor_data.values[0] = tpd_get_ps_value();58 sensor_data.value_divide = 1;59 sensor_data.status = SENSOR_STATUS_ACCURACY_MEDIUM;60if ((err = hwmsen_get_interrupt_data(ID_PROXIMITY, &sensor_data)))61 {62 TPD_PROXIMITY_DMESG(" proxi_5206 call hwmsen_get_interrupt_data failed= %d\n", err);6667if (tpd_touchinfo(&cinfo, &pinfo)) //获取TP设备数据,并把数据保存在cinfob buf中68 {69//TPD_DEBUG("point_num = %d\n",point_num);70 TPD_DEBUG_SET_TIME;71if(point_num >0)72 {73for(i =0; i<point_num; i++)//only support 3 point74 {75 printk(KERN_DEBUG"X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);7677 cinfo.x[i] = cinfo.x[i];78 cinfo.y[i] = cinfo.y[i];7980 tpd_down(cinfo.x[i], cinfo.y[i], cinfo.id[i]); //按下数据处理81 printk(KERN_DEBUG"----calibration----- X:%4d, Y:%4d, P:%4d \n", cinfo.x[i], cinfo.y[i], cinfo.id[i]);82 }83 input_sync(tpd->dev);84 }85else86 {87 tpd_up(cinfo.x[0], cinfo.y[0]); //弹起数据处理88//TPD_DEBUG("release --->\n");89//input_mt_sync(tpd->dev);90 input_sync(tpd->dev);91 }92 }93 ......9495 }while(!kthread_should_stop());9697return0;98 }/* 获取TP数据 */1static int tpd_touchinfo(struct touch_info *cinfo, struct touch_info *pinfo)2 {3int i = 0;4char data[128] = {0};5 u16 high_byte,low_byte,reg;6 u8 report_rate =0;78 p_point_num = point_num;9if (tpd_halt)10 {11 TPD_DMESG( "tpd_touchinfo return ..\n");12return false;13 }14 mutex_lock(&i2c_access);151617 reg = 0x00;18 fts_i2c_Read(i2c_client, ®, 1, data, 64); //获取TP数据,⼀些TP是⽀持多点触控的,所以有可能就产⽣多个触点的数据19 mutex_unlock(&i2c_access);2021/*get the number of the touch points*/22 point_num= data[2] & 0x0f;2324 TPD_DEBUG("point_num =%d\n",point_num);2526/* 根据芯⽚协议解析数据并存放在cinfo buf中 */27for(i = 0; i < point_num; i++)28 {29 cinfo->p[i] = data[3+6*i] >> 6; //event flag30 cinfo->id[i] = data[3+6*i+2]>>4; //touch id31/*get the X coordinate, 2 bytes*/32 high_byte = data[3+6*i];33 high_byte <<= 8;34 high_byte &= 0x0f00;35 low_byte = data[3+6*i + 1];36 cinfo->x[i] = high_byte |low_byte;373839/*get the Y coordinate, 2 bytes*/40 high_byte = data[3+6*i+2];41 high_byte <<= 8;42 high_byte &= 0x0f00;43 low_byte = data[3+6*i+3];44 cinfo->y[i] = high_byte |low_byte;45 }4647 }48 TPD_DEBUG(" cinfo->x[0] = %d, cinfo->y[0] = %d, cinfo->p[0] = %d\n", cinfo->x[0], cinfo->y[0], cinfo->p[0]);4950return true;51 }1static void tpd_down(int x, int y, int p) {2static int tpd_x = 0;3static int tpd_y = 0;45 tpd_x = x;6 tpd_y = y;78/* 通过输⼊⼦系统上报数据 */9 input_report_key(tpd->dev, BTN_TOUCH, 1);10 input_report_abs(tpd->dev, ABS_MT_TOUCH_MAJOR, 20);11 input_report_abs(tpd->dev, ABS_MT_POSITION_X, x);12 input_report_abs(tpd->dev, ABS_MT_POSITION_Y, y);1314 printk(KERN_ERR, "D[%4d %4d %4d] ", x, y, p);15/* track id Start 0 */16 input_report_abs(tpd->dev, ABS_MT_TRACKING_ID, p);17 input_mt_sync(tpd->dev);18 #ifndef MT657219if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())20#endif21 {22 tpd_button(x, y, 1); //虚拟按键的处理23 }24 TPD_EM_PRINT(x, y, x, y, p-1, 1);25 }2627static void tpd_up(int x, int y) {2829 input_report_key(tpd->dev, BTN_TOUCH, 0);30 input_mt_sync(tpd->dev);31 TPD_EM_PRINT(x, y, x, y, 0, 0);3233 #ifndef MT657234if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())35#endif36 {37 tpd_button(x, y, 0);38 }39 }/* 虚拟按键判断和处理函数 */1void tpd_button(unsigned int x, unsigned int y, unsigned int down) {2int i;3if(down) {4for(i=0;i<tpd_keycnt;i++)5 {6/* 判断数据是否落在虚拟按键的范围内,数据处理算法实现了以坐标点为中⼼的虚拟按键 */7if(x>=tpd_keys_dim[i][0]-(tpd_keys_dim[i][2]/2) &&8 x<=tpd_keys_dim[i][0]+(tpd_keys_dim[i][2]/2) &&9 y>=tpd_keys_dim[i][1]-(tpd_keys_dim[i][3]/2) &&10 y<=tpd_keys_dim[i][1]+(tpd_keys_dim[i][3]/2) &&11 !(tpd->btn_state&(1<<i)))12 {13 input_report_key(tpd->kpd, tpd_keys[i], 1); //上报按键14 input_sync(tpd->kpd);15 tpd->btn_state|=(1<<i);16 TPD_DEBUG("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);17 printk("[mtk-tpd] press key %d (%d)\n",i, tpd_keys[i]);18 }19 }20 } else {21for(i=0;i<tpd_keycnt;i++) {22if(tpd->btn_state&(1<<i)) {23 input_report_key(tpd->kpd, tpd_keys[i], 0);24 input_sync(tpd->kpd);25 TPD_DEBUG("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);26 printk("[mtk-tpd] release key %d (%d)\n",i, tpd_keys[i]);27 }28 }29 tpd->btn_state=0;30 }31 }32 tpd_keys_dim和tpd_keys的数据是通过tpd_button_setting初始化的,可以去看tpd_button_setting()的实现;通过简单分析,由此可知MTK的TP驱动的整体框架跟普通TP驱动框架也是⼤致差不多;。
GF-RK3399-Kit Android 用户手册版本号:V2.02021年04月浙江启扬智能科技有限公司版权所有QIYANG TECHNOLOGY Co., LtdCopyright Reserved版本更新记录有任何技术问题或需要帮助,请联系:*********************** 第3页 共34页 购买产品,请联系销售:********************更多信息请访问: 目 录目 录 ............................................................................................................................................. 3 阅读前须知:本手册主要介绍GF-RK3399-Kit 开发板Android7.1用户手册 .......................... 4 一、前言 . (4)公司简介 ................................................................................................................................... 4 二、上手教程 ................................................................................................................................... 5 2.1、入手指南 .......................................................................................................................... 5 2.2、串口调试 .......................................................................................................................... 6 三、固件升级 ................................................................................................................................. 10 3.1、工作模式说明 ................................................................................................................ 10 3.2、固件说明 ........................................................................................................................ 12 3.3、固件烧写 ........................................................................................................................ 13 3.4、网络MAC 地址烧写 ..................................................................................................... 17 四、Android 开发 .......................................................................................................................... 26 4.1、ADB 使用 ...................................................................................................................... 26 4.2、编译环境搭建 ................................................................................................................ 28 4.3、编译镜像 ........................................................................................................................ 29 4.4、烧写分区映像 ................................................................................................................ 31 4.5、制作统一固件 ................................................................................................................ 32 五、常见问题 (33)有任何技术问题或需要帮助,请联系:*********************** 第4页 共34页 购买产品,请联系销售:********************更多信息请访问: 阅读前须知:本手册主要介绍GF-RK3399-Kit 开发板Android7.1用户手册一、前言公司简介浙江启扬智能科技有限公司2007年成立于杭州, 是一家专注于ARM 嵌入式产品研发、生产与销售的国家高新技术企业。
本文描述在RK3126平台上添加一个新的TP驱动(gslx680驱动)以及详细的
• 1
• 2
• 3
• 4
• 5
• 6
•7
•8
•9
•10
•11
•12
•13
•14
•15
•16
•17
•18
•19
•20
•21
•22
表示i2c2总线上下挂在了多个i2c设备。
其中ts@40是表示此i2c设备的设备类型为触摸屏,设备地址为0x40(7位地址,
注意:在i2c的传输函数中,会将此地址左移一位,因此实际上gslx680的i2c 设备地址为0x80)。
该节点下有多个属性:
1、compatible = "gslX680";属性用于驱动和设备的绑定。
表示特定的设备名称,此处为gslX680;
2、reg = <0x40>;属性表示此设备的i2c地址为0x40,等同于@40;
3、wake-gpio = <&gpio0 GPIO_D3 GPIO_ACTIVE_LOW>;表示复位引脚使用的是GPIO0 中的GPIO_D3这个引脚,低电平有效。
irp-gpio = <&gpio0 GPIO_A2 IRQ_TYPE_LEVEL_HIGH>;表示中断引脚使用的是GPIO0中的GPIO_A2这个引脚,高电平触发。
很奇怪,为什么这里没有上电的信息,以及在整个驱动程序中都没有给ic上电的操作。
在前面的MTK平台上的tp驱动都有上电的动作,暂时还搞不懂在RK 平台上为什么没有。
4、revert_x = <0>; revert_y = <0>;标记x和y是否需要翻转。
在上述的信息中,可以通过of接口获取到属性对应的值。
在后面的probe()函数中就会使用到。
注:关于dts的详细信息可以查看ARM Linux 3.x的设备树(Device Tree)和Device Tree Usage
2、修改Makefile、Kconfig、defconfig
(1)、修改Makefile添加gslx680驱动
在drivers/input/touchscreen/Makefile中添加驱动:
obj-$(CONFIG_TOUCHSCREEN_GSLX680) += gslx680/。
只要当配置了CONFIG_TOUCHSCREEN_GSLX680的选项才会去编译gslx680目录下
• 1 • 2 • 3 • 4 • 5 • 6 •7 •8 •9 •10 •11 •12 •13 •14 •15 •16 •17 •18 •19 •20 •21 •22 •23 •24 •25 •26 •27 •28 •29 •30 •31 •32 •33 •34 •35 •36 •37 •38
注册名字为GSLX680_I2C_NAME的i2c驱动,即gslx680,该驱动支持的设备名为字gsl_ts_id[]里的设备名称。
因为我们在dts中已注册了一个名字为gslx680的i2c设备。
因此,设备与驱动可以匹配成功并正确执行probe()函数。
• 2 • 3 • 4 • 5 • 6 •7 •8 •9 •10 •11 •12 •13 •14 •15 •16 •17 •18 •19 •20 •21 •22 •23 •24 •25 •26 •27 •28 •29 •30 •31 •32 •33 •34 •35 •36 •37 •38 •39 •40 •41 •42 •43 •44
•46 •47 •48 •49 •50 •51 •52 •53 •54 •55 •56 •57 •58 •59 •60 •61 •62 •63 •64 •65 •66 •67 •68 •69 •70 •71 •72 •73 •74 •75 •76 •77 •78 •79 •80 •81 •82 •83 •84 •85 •86 •87 •88
•90 •91 •92 •93 •94 •95 •96 •97 •98 •99 •100 •101 •102 •103 •104 •105 •106 •107 •108 •109 •110 •111 •112 •113 •114 •115 •116 •117 •118 •119 •120 •121 •122 •123 •124 •125 •126 •127 •128 •129 •130 •131
• 1 • 2 • 3 • 4 • 5 • 6 •7 •8 •9 •10 •11 •12
•13
•14
•15
•16
client表示一个i2c的设备;
input表示一个输入设备;
work表示一个工作,用于处理中断到来之后获取坐标等信息;
wq表示一个工作队列,将上面的work加入到该工作队列中;
dd和touch_data用来存储坐标的相关信息;
device_id表示i2c设备的设备号;
irq申请的中断号;
irq_pin中断引脚;
wake_pin复位引脚;这两个引脚信息可以通过dts获取到.
tp创建一个为tp_device的数据结构,里面有个成员notifier_block用来接收LCD背光灯的亮暗的通知进而调用suspend()和resume()。
主要的实现在
• 1
• 2
• 3
可以通过设备节点np获取到它irq-gpio这一个属性的值存放在ts->irq_pin
• 1
• 2
• 2 • 3 • 4 • 5 • 6 •7 •8 •9 •10 •11 •12 •13 •14 •15 •16 •17 •18 •19 •20 •21 •22 •23 •24 •25 •26 •27 •28 •29 •30 •31 •32 •33 •34 •35 •36 •37 •38 •39 •40 •41 •42 •43 •44
•46 •47 •48 •49 •50 •51 •52 •53 •54 •55 •56 •57 •58 •59 •60 •61 •62 •63 •64 •65 •66 •67 •68 •69 •70 •71 •72 •73 •74 •75 •76 •77 •78 •79 •80 •81 •82 •83 •84 •85 •86 •87 •88
•90
•91
•92
•93
•94
•95
•96
在gslX680_ts_init()中主要做了如下工作:
配置获取坐标信息
每次当中断来了之后,就要求通过i2c去读取坐标的信息,至于从哪里读取以及读取多少个,都是通过ts->dd来决定的。
为存储坐标信息申请空间
坐标信息放在ts->touch_data中。
申请及初始化input_dev设备,向input子系统注册该设备
这里面的内容涉及到input子系统,我还没有做过深入的了解。
初始化工作ts->work
ts->work对应的操作为gslX680_ts_worker(),在中断来了之后,会
queue_work(ts->wq, &ts->work);让ts->work工作起来,就会去读取坐标等信息,然后通过input子系统上报给Android系统。
(6)、获取属性信息
通过of_接口获取revert_x和revert_y的信息,以此来决定坐标是否要翻转。
(7)、初始化ic
初始化的内容会放到一个全局的数组之中,这项工作一般都要FAE来完成。
(8)、申请中断号以及中断服务子程序
• 1
• 2
• 3
注:如果申请资源出错的话一定要记得释放资源以及前面的资源。
比如说这里为
• 1
• 2
• 3
• 4
• 5
• 6
•7
•8
•9
•10
•11
•12
•13
•14
•15
一旦有中断到来,立马调用gsl_ts_irq(),在这个中断服务子程序中先判断ts->work是否挂起,如果没有挂起就启动工作队列ts->wq的工作ts->work。
ts->work与gslX680_ts_worker()对应,主要用来读取坐标信息。
5、休眠唤醒
关于休眠和唤醒的内容根据ic的特性设置。
如休眠的时候需要关闭中断、配置进入休眠模式、拉低wake引脚。
唤醒的时候唤醒ic,使能wake引脚、使能中断等。