
简介面向Android系统开发与驱动调试工程师该压缩包聚焦GSL1680/GSL1688电容屏触控芯片在Linux内核与HAL层之间的驱动实现可帮助理解多点触控信号从硬件中断到输入事件上报的完整链路。资源仅22KB内部包含2个文件分别为1个C源码文件与1个头文件前者覆盖驱动主体涉及初始化、中断处理及数据读写等关键路径后者提供寄存器定义与接口声明便于内核模块编译与驱动逻辑分析。已有179人学习下载。通过研读这份精简源码可掌握GSL1680系列的寄存器配置方法、触摸坐标解析流程以及中断上报机制并对照GSL1688差异为适配不同面板、调整报告率或优化功耗提供直接参考。对调试Android触摸异常、深入理解input子系统的工程师而言这是一份极具实用价值的驱动代码样例。1. GSL1680-Driver.rar 到手先别急着编译这套方案到底在解决什么问题GSL1680 和 GSL1688 是国产电容触控 IC 里出镜率相当高的两颗白牌平板、工控一体机、带屏幕的门禁和充电桩上经常能看到。对应的 Android 驱动方案常被打包成一个叫 GSL1680-Driver 的 rar里面一般是一堆 .c/.h 源码和一份或多份 cfg 文件标题里的 android_gsl1 不是某个特殊分支而是方案商把整套触控适配工程按 GSL1 系列命名后的发布物。这套东西解决的核心问题是让触摸屏能通过 I2C 中断把坐标数据送进 Android 内核的 input 子系统再被上层手势框架消费掉触摸数据还要能按屏幕分辨率、传感器通道布局正确映射不能出现反转、漂移和跳点。适合照着做的人有两类一类是做 BSP 的内核工程师需要把方案商的驱动合入自己的内核树另一类是跟屏厂或方案商联调的项目开发屏幕显示已经亮了但触摸要么完全没反应要么坐标错乱得用这套驱动把问题收口。2. 从 rar 包到内核源码树先确认驱动接口再谈 GSL1680/GSL1688 移植2.1 解包之后先看这几处判断驱动是给几号内核用的拿到 rar 包第一件事不是解压后立刻拷贝而是先搞清楚这份源码原本挂在哪个内核版本下面。GSL 系列驱动对内核接口非常敏感明明同一个芯片老内核的驱动可能是靠 board 文件注册 platform_device而新内核已经全面切到 device tree拿老驱动往新内核里塞光是 struct input_dev 的申请和中断注册方式就够你改半天。unrar x GSL1680-Driver.rar cd GSL1680-Driver ls -R | head -80 grep -n linux/of_gpio.h\|linux/input/mt.h gslx680/*.c | head -20解压后的目录名常见的有 gslx680、gsl1680、gsl_ts 几种不必被名字干扰重点是看 .c 文件里 include 了哪些头文件。出现 linux/of_gpio.h 和 linux/of_irq.h说明驱动已经基于设备树解析 GPIO 和中断这是 3.x 中后期到 4.x 内核的典型写法如果出现的是 mach/gpio.h 或者直接操作 GPIO 编号的宏说明驱动还停留在更老的板级时代需要花时间把of_property_read_u32这类解析逻辑补齐。再确认触摸事件上报用的是哪一套 API。老的直接调input_report_abs新的会走 MT protocol B涉及input_mt_init_slots、input_mt_report_slot_state和input_mt_report_pointer_emulation。这一步决定你拷进去之后要不要在前半段就做一次不小的 rewrite而不是只调 dts。2.2 放进内核树Makefile、Kconfig 和对象文件对应关系确认接口匹配之后把驱动源码放到drivers/input/touchscreen/下然后处理 Makefile 和 Kconfig。这一步看着简单实际很容易翻车方案商为了兼容多颗芯片目录里可能存在多个 .c 文件而 Kconfig 里的依赖没写全或者 Makefile 里的 obj 名字和实际 .c 文件名对不上编译直接报No rule to make target。cp -r gslx680 /your-kernel/drivers/input/touchscreen/ cd /your-kernel/drivers/input/touchscreen vi Makefile # Makefile 末尾追加 obj-$(CONFIG_TOUCHSCREEN_GSLX680) gslx680.o然后在 Kconfig 里追加config TOUCHSCREEN_GSLX680 tristate GSLX680/GSL1680/GSL1688 touchscreen driver depends on I2C INPUT help Support for GSL1680/GSL1688 series touchscreen controllers.这里要注意.o目标名字必须和实际编译的.c文件对应。如果方案包里主体是 gsl1680.c而 Makefile 写的是 gslx680.o链接时会报undefined symbol或者根本编不出这个 obj如果内核树里已经存在另一个方案商的 gsl_ts 驱动还要避免两个 obj 互相覆盖符号。我的习惯是先单独编译这一个文件make drivers/input/touchscreen/gslx680.o把编译错误提前暴露出来再去调全量构建。2.3 预先确认平台 I2C 总线与 probe 日志的读取方式触摸芯片是 I2C 设备probe 能不能成功跟它挂在哪条 I2C 总线、地址对不对直接相关。GSL1680 常见 I2C 地址是 0x40GSL1688 可能也是 0x40但不同方案商会在驱动里改一定要以驱动源码里i2c_driver的id_table或 dts compatible 为准。grep -n id_table\|compatible /your-kernel/drivers/input/touchscreen/gslx680.c | head -20 cat /your-kernel/arch/arm64/boot/dts/rockchip/your-board.dts | grep -n i2c\|touch在 Rockchip 平台上I2C 控制器节点一般是i2c0到i2c3具体触摸屏接在哪一组看原理图最可靠。没有原理图时可以把驱动里带的测试工具或i2cdetect跑一遍确认总线上能不能扫到 0x40。probe 是否执行到看dmesg里有没有gslx680或i2c read/write error相关打印。很多新手在这步会忽略一个前提如果这路 I2C 的status是disabled驱动写再多都不会被调用到。另外做烧录调试前Windows 下记得先装好对应平台的 USB 驱动比如 Rockchip 的 Loader 驱动否则板子连 ADB 都枚举不到后面的 log 全看不到。3. 设备树和 menuconfig 配置GSL1680 驱动能不能 probe九成看这里3.1 从 Kconfig 到 defconfig触摸驱动该编成模块还是编进内核把驱动源码放进内核树不等于它会被编译。Linux 内核默认只编译 defconfig 里勾选的项Kconfig 里新加的配置项不会自动生效。你需要在 menuconfig 里找到对应条目并打开或者直接往 defconfig 里写一行。make ARCHarm64 your_board_defconfig make ARCHarm64 menuconfigmenuconfig 的路径通常在Device Drivers - Input device support - Touchscreens - GSLX680/GSL1680/GSL1688 touchscreen driver。注意方案商可能改了菜单显示名直接按 Y 搜索GSL是最快的方式。选中后保存退出再确认 .config 里生成了CONFIG_TOUCHSCREEN_GSLX680y。这里还有个选择编进内核还是编成 .ko 模块。我的建议是调试阶段直接编成 y这样开机就 probe不用处理模块加载顺序。如果你非要用模块要有心理准备Android 的 init 进程加载 .ko 的时机、路径和 SELinux 策略都可能卡你尤其是 Android 10 之后的镜像把分区权限管得很死模块稍后引入的麻烦比编进内核多得多。GSL 配置固件依赖文件系统路径模块加载晚几秒触摸就晚几秒可用对用户体验影响很明显。3.2 I2C 地址、INT 中断脚、RST 复位脚设备树三件套怎么落驱动能不能正常 probe九成取决于 dts 里这几项对不对。下面是一段在 Rockchip 平台上常见的写法具体 GPIO 编号必须按你板子的原理图换算不能照着抄。i2c3 { status okay; clock-frequency 100000; gsl1680: touchscreen40 { compatible silead,gsl1680; reg 0x40; interrupt-parent gpio3; interrupts RK_PB5 IRQ_TYPE_EDGE_FALLING; irq-gpio gpio3 RK_PB5 GPIO_ACTIVE_LOW; reset-gpio gpio3 RK_PB6 GPIO_ACTIVE_LOW; power-gpio gpio3 RK_PB7 GPIO_ACTIVE_HIGH; touchscreen-max-id 10; }; };reg对应芯片的 I2C 从机地址0x40 是常见默认值GSL1688 可能有方案用 0x41以原理图和驱动i2c_driver的.address_list为准。interrupts里的触发方式很关键GSL 系列驱动在中断回调里读数据有的驱动要求IRQ_TYPE_LEVEL_LOW有的是EDGE_FALLING配错了最常见的结果是中断风暴——系统频繁 wakeup 但触摸没反应或者反过来完全没中断。reset-gpio必须给驱动 probe 时会拉低再拉高复位芯片power-gpio不是所有板子都接如果原理图上确认没接这一行可以删掉保留反而可能因为驱动在 probe 里去操作一个没注册的 GPIO 导致失败。GPIO 宏的换算也要注意RK_PB5这种写法只在 Rockchip 平台宏定义里可用别的平台要写GPIO_ACTIVE_LOW对应的硬件编号或者直接用gpio3 GPIO_PB5 GPIO_ACTIVE_LOW。同一个 GPIO 不能既当中断又当普通输入重复申请dts 里interrupts和irq-gpio同时写时驱动内部如果用了 gpio_to_irq要确认没有冲突。3.3 GSL1680 与 GSL1688 在编译期的差异一个宏决定十几处寄存器GSL1680 和 GSL1688 的驱动源码经常是同一套代码里通过预编译宏切换寄存器配置和初始化参数。方案包通常会在头文件里用一个宏定义把型号区分开比如#define GSL1688或#define GSL1680也可能是让 Makefile 里加ccflags-y。grep -n GSL1688\|GSL1680 gslx680.h gsl_ts.c | head -30如果在头文件里看到大量类似#ifdef GSL1688的块说明这颗驱动同时支持两颗 IC编译前必须确认选对。常见做法是在 Makefile 里加一行编译参数ccflags-y -DGSL1688加了宏之后初始化数组、通道映射、坐标换算都会切到另一套。这个环节容易出的问题是只改了设备树 compatible忘了编译宏结果驱动还是按 GSL1680 初始化 GSL1688 芯片触摸要么完全不触发要么报点位置是镜像的。确认编译宏之后最好在 probe 函数里留一行pr_info把当前型号打出来dmesg 里一眼能看出有没有选错。4. GSL 系列的 cfg 固件机制放在哪、怎么下发、失败怎么查4.1 内置数组和外部 cfg 加载两种机制的取舍GSL 系列触控芯片和多数普通触控 IC 不一样它上电后不能直接工作需要下发一份配置数据里面是一段段寄存器地址和写入值屏幕的分辨率、通道映射、触摸报点参数全在这份数据里。方案商习惯把这东西叫 cfgGSL1688 和 GSL1680 各有各的 cfg而且不同尺寸、不同通道布局的屏cfg 完全不能互换。驱动里加载 cfg 常见有两种方式。第一种是把 cfg 直接转成一个常量数组编译进驱动驱动源码里会有类似static u32 gsl1680_init_data[]这样的大数组probe 时直接通过 I2C 写进芯片。第二种是驱动运行时通过request_firmware从文件系统读取外部 cfg 文件。现在多数方案倾向于第二种因为换一块屏只换 cfg 文件不用重新编内核对生产切换非常友好。static int gsl_fw_load(struct i2c_client *client) { const struct firmware *fw NULL; /* 一般通过 request_firmware 从文件系统读取 cfg */ ret request_firmware(fw, gsl1680.cfg, client-dev); if (ret) { dev_err(client-dev, firmware request failed\n); return ret; } /* 然后把 fw-data 按寄存器写下去 */ }这里需要注意如果编译选项里CONFIG_FW_LOADER没有打开request_firmware会直接返回-ENOENT连文件系统都不会去搜。另外如果你的内核里启用了CONFIG_FW_LOADER_USER_HELPER加载固件时还可能依赖用户态 helper这在内核裁剪严重的 Android 板上也容易成为黑匣子。4.2 cfg 放到 Android 哪个目录驱动在开机时才能拿到request_firmware并不是随便从根目录找文件它依赖内核的 firmware 搜索路径。Android 平台上常见路径是/vendor/firmware也有方案用/etc/firmware或/system/etc/firmware。你手上的驱动源码里一般能看到fw request_firmware(fw, gsl1680.cfg, dev)这样的调用前面gsl1680.cfg只是文件名路径由内核的fw_path决定。adb root adb remount adb push gsl1680.cfg /vendor/firmware/ adb shell chmod 644 /vendor/firmware/gsl1680.cfg adb shell ls -l /vendor/firmware/gsl1680.cfg把 cfg 推上去之后顺手验证一下内核能不能读。在 Android 10 之后SELinux 是最大的拦路虎kernel 要读/vendor/firmware下的文件必须有对应的file_type权限。你在 dmesg 里经常能看到类似avc: denied { read } for pid... commkworker ... scontextu:r:kernel:s0 tcontextu:object_r:firmware_file:s0这样的记录这是最常见的导致触摸没反应但驱动 probe 又成功的情况。解决方式一般是在 sepolicy 里给 kernel 或对应 domain 加一条 allow 规则调试阶段可以先用adb shell setenforce 0验证确认是 SELinux 问题后再去补策略别在排障时死磕一个点。还有更省事的做法把 cfg 编进dtbo或作为内核 initramfs 的一部分避开运行时文件系统权限问题。但这个做法耦合度高换屏就要重编镜像所以只在无法解决文件系统问题时才建议。4.3 固件加载失败后触摸是什么表现怎么从 log 定位固件加载失败的表现很隐蔽驱动可能已经成功 probeinput 设备也注册了但触摸就是没反应或者在触摸瞬间才有孤立事件滑动时坐标完全断在某个区域。原因是芯片里没有可用的配置数据中断虽在触发但驱动回读坐标得到的是一堆无效值。adb shell dmesg | grep -iE gsl|firmware|avc | tail -40看 dmesg 是这里主要的排查手段。出现firmware request failed说明 cfg 文件名或路径不对出现avc: denied说明文件在但没权限没有 GSL 相关打印说明驱动根本没执行到固件加载那段逻辑。另外还要确认 cfg 文件本身没被 Windows 记事本改过格式方案商发的 cfg 看起来像文本但内部可能有二进制段用adb push时注意传输模式别用任何会做换行转换的方式解压或编辑。5. GSL1680/GSL1688 移植避坑五个高频翻车点和处理顺序5.1 现象一中断不停触发坐标却全是错乱的板子能开机驱动也 probe 成功但 dmesg 里中断风暴触摸时坐标乱跳比如点左上角报出右侧坐标或者完全无规律。原因多半是 I2C 速率太高芯片回读寄存器时数据出错其次是中断触发方式配成EDGE而驱动期望LEVEL导致中断丢失或重复进入。解决顺序是先把 dts 里 I2C 的clock-frequency降到 100kHzGSL 系列在 400kHz 下不是所有板子都可靠再看驱动里的中断标志是否和 dts 一致两个地方都改了之后重新编镜像烧录确认中断频率和坐标输出都恢复正常。5.2 现象二系统休眠唤醒后触摸彻底没有反应这个问题在 Android 平板上很常见表现为亮屏状态下触摸正常按电源键灭屏再唤醒触摸就死了必须重启才能恢复。原因一般是驱动在 suspend 回调里没有正确拉低复位脚或者 resume 之后没有重新下发 cfg 配置芯片还停在某个低功耗状态里中断已经不再上报。解决方式是在驱动的suspend里把 reset-gpio 拉低resume里先拉高再拉低然后重新加载一次 cfg。调试时可以用下面命令反复验证adb shell echo mem /sys/power/state # 唤醒后立即测试触摸 adb shell getevent -lt如果唤醒后 getevent 完全没有新事件基本可以确认是驱动电源管理没写完整。还有一些方案商驱动把 cfg 重新下发放在了 workqueue 里但 workqueue 被系统冻结了也会出现同样现象这时候要检查驱动注册 workqueue 时有没有加WQ_FREEZABLE相关处理。5.3 现象三GSL1680 换 GSL1688 后中断完全不来同一块板子之前 1680 触摸正常换成 1688 芯片后完全没中断。这个现象指向三个地方compatible 匹配、编译宏、cfg 固件。设备树里 compatible 如果还写silead,gsl1680而驱动里of_device_id列表只匹配 1680那 1688 的 I2C 设备根本不会绑定到驱动上其次是第 3.3 节说的编译宏没切到 GSL1688 的话初始化寄存器就是一套错误配置最后是 cfg1680 的 cfg 无论如何不能用在 1688 上寄存器映射不同芯片可能直接初始化失败。排查时先cat /sys/bus/i2c/devices/3-0040/name看设备名是否出现再 dmesg 看驱动有没有打印型号确认最后换对 cfg三步走完基本能解决。5.4 现象四触摸时好时坏看起来像“玄学”有一个项目里遇到的现象是触摸偶尔不灵重启几次又变好用户反馈说像玄学。这通常不是驱动时序问题而是 cfg 和芯片批次不匹配。GSL1688 在不同批次、不同屏厂供货时内部通道自检参数有差异方案商给的 cfg 版本必须和实物批次对应如果芯片里已经有旧版本配置驱动再下发新 cfg 时又因为 I2C 时序偶尔失败就会出现一会儿好一会儿坏。解决方法是向方案商或屏厂要对应批次的 cfg并在驱动里把固件下发的重试次数调大到 3 到 5 次每次失败后重新复位芯片再试。也不用过度相信所谓最新的 cfg版本对不上往往是越新越乱。5.5 现象五屏幕驱动已经点亮触摸就是没反应很多时候触摸没反应问题反而在触摸链路之外。比如一块 TFT 屏用的是 JD9365DA-H3 驱动 IC屏幕已经正常点亮但触摸完全没有输入事件。这看起来是触摸的问题实际可能是 I2C 总线没有使能或者这路 I2C 的 pinctrl 被屏驱动或者其他外设占用。优先用i2cdetect确认总线上能不能扫到 0x40扫不到就是总线级别的问题再确认 dts 中对应 I2C 节点的pinctrl-0是否配置了正确的 I2C 引脚 mux。如果总线已经被其他设备占用有些平台会报 i2c arbitration lostdmesg 里能看到痕迹。6. 调通之后别急着收工触摸链路验证与固件回退驱动能 probe、中断能触发、坐标能上报只算完成了一半。最后一公里是把这条链路放在 Android 系统层面验证并处理掉量产时可能出现的固件漏加载。adb shell getevent -lt在屏幕上用手写笔从左上角滑到右下角getevent应该输出连续的ABS_MT_TRACKING_ID、ABS_MT_POSITION_X、ABS_MT_POSITION_Y事件坐标变化应该平稳不能有跳变。这里有个习惯我一直在用每次移植完都写一个十几行的读取脚本把 200 个触摸事件的坐标拉出来做线性度检查肉眼看不出来的间歇断点脚本统计就能暴露。另外还要在/proc/bus/input/devices里确认触摸设备名和中断号绑定正确避免多个触摸设备共存时上层框架选错设备。量产前还有一个重要动作把固件加载做成自愈逻辑。GSL 系列驱动在极少数板子上会因为 I2C 时序出现固件下发失败如果只是概率性失败用户拿到手触摸就是死的运维成本很高。我一般的做法是在 init.rc 里加一个启动后检查的脚本检测到对应 input 设备不存在时手动触发一次驱动提供的固件加载入口。if [ ! -e /sys/bus/i2c/devices/3-0040/name ]; then echo 1 /sys/devices/platform/gslx680/update_fw fi固件加载入口的命名在不同方案包里不一样有的叫update_fw有的叫force_update以驱动里device_create_file的节点名为准。这个自愈脚本本质上是给驱动行为兜底避免因为一次偶发失败就整机返修。经历过一个批次几十台机器陆续触摸失灵之后我现在每到一个新平台驱动合入的第一天就会把这种回退逻辑加上而不是等项目爆发问题再补。固件加载这种事概率再低也别赌补一个自愈入口花不了半小时后面省下的是大量的售后沟通成本。希望帮到你。本文还有配套的精品资源点击获取