ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

QT/E触摸屏支持实战:TaoToken统一Key打通嵌入式输入链路

QT/E触摸屏支持实战:TaoToken统一Key打通嵌入式输入链路 1. QT/E 触摸屏从驱动到应用层为什么总断链QT/E 触摸屏支持这件事说穿了就是把一条链路打通触摸面板产生中断内核 input 子系统上报事件tslib 做校准和滤波QT/E 的鼠标协议插件读取设备节点最后 QWS 或 EGLFS 把坐标投递给你的 QWidget。这条链上任何一环断了表现都是「点了没反应」或者「点左边跳右边」。工控 HMI 和手持终端开发者最常遇到的就是驱动明明加载了、cat /dev/input/event0也有数据但 QT 程序里就是不动。我在一块 i.MX6 工控板上调这块花了整整两天。现象是命令行用ts_test画线完全正常一跑./app -qws就失灵。后来发现是 QWS_MOUSE_PROTO 指向了/dev/h3600_tsraw这个默认名而我的板子实际节点是/dev/input/event1。QT/E 的 LinuxTp 插件在编译时把设备路径写死了不改源码或者不通过环境变量覆盖它永远找不到正确的节点。这条链路涉及几个关键概念先对齐一下。tslib 是触摸屏的抽象层负责把原始 ADC 值通过pointercal校准文件换算成屏幕像素坐标同时做去抖和滤波。QT/E 的鼠标协议插件qmouselinuxtp_qws.cpp对应 LinuxTpqmouselinuxinput_qws.cpp对应 LinuxInput负责从 tslib 或直接 from evdev 读事件。QWS 是 QT/E 自带的窗口系统EGLFS 是 QT5 之后基于 OpenGL ES 的全屏平台插件两者读取触摸参数的路径不一样。适合读这篇的人正在做 QT/E 嵌入式 HMI、手持终端、医疗设备面板的开发者已经能交叉编译 QT/E 库但触摸没调通的以及从 QT4 QWS 迁移到 QT5 EGLFS 时触摸配置对不上的。下面我按「先定位问题、再给可复制配置、最后验证和排障」的顺序写每一步都能直接抄到你的板子上跑。核心检索词先明确QT/E 触摸屏支持、tslib 校准配置、QWS_MOUSE_PROTO、EGLFS 触摸参数、pointercal 文件、触摸坐标偏移排查。这些词你搜到的多数文章只讲一半我把驱动到应用层整条链补齐。2. TaoToken 统一 Key 在嵌入式输入链路调试里的前置准备调试触摸链路时我经常需要查 QT/E 源码里鼠标插件的实现、对比不同版本的qmouselinuxtp_qws.cpp差异或者让模型帮我分析evtest的原始输出格式。这些查询如果每次都要切换不同的 API Key 和模型入口效率很低。TaoToken 在这里的作用是提供一个统一的 Key把模型对话、代码补全、文档检索收敛到一个入口省掉在多个平台之间倒腾凭证的时间。先说清楚它是什么TaoToken 是一个大模型 API 聚合服务你用同一个 Key 就能调用不同厂商的模型。对嵌入式开发者来说实际价值在于调试时可以让模型读你的evtest输出、帮你写 tslib 的校准脚本、解释 QT/E 源码里的坐标变换逻辑而不用为每个模型单独申请和配置 Key。它适合谁需要频繁查文档、读源码、写测试脚本又不想在凭证管理上花时间的开发者。前置准备分三步。第一步拿到 Key。访问 API Keys 管理页https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite登录后创建一个新 Key复制保存。这个 Key 后面在环境变量或配置文件里用。第二步确认你的调用方式。如果你是在开发机上用命令行工具查资料可以直接用 curl 测通如果你是在 IDE 里用插件比如 Cline、Continue需要在插件设置里填 Base URL 和 Key。Base URL 是https://taotoken.net/api注意这个地址不带 UTM 参数直接写就行。第三步选模型。调试触摸链路时我一般用擅长读代码和长文本的模型来分析源码用响应快的模型做日常查询。你可以在模型对话页https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite看当前可用的模型列表记下你要用的 Model ID后面配置里要填。这里有个坑要提前说TaoToken 是 API 服务不是编辑器插件本身也不是代理工具。它的作用是让你用一个 Key 调用模型你的 QT/E 代码、tslib 配置、设备节点这些还是在你本地板子和开发机上操作。别指望它替你编译 QT 库或者烧写文件系统。如果你打算长期在嵌入式项目里用模型辅助编码和调试可以了解 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite它面向的是持续编码和 Agent 场景比单次调用更适合日常开发流。但这一节的重点是先把 Key 拿到、Base URL 记好、Model ID 选好后面配置触摸链路时随时能查资料。3. tslib 校准与 QWS/EGLFS 触摸参数的可复制配置这一节是全文的核心我给出一套可以直接抄的配置。分三块tslib 校准、QWS 环境变量、EGLFS 参数。每块都给出文件路径和完整内容。3.1 tslib 校准与 pointercal 文件生成tslib 的校准文件叫pointercal默认放在/etc/pointercal。它是一行 7 个数字格式是a0 a1 a2 a3 a4 a5 a6前 6 个是坐标变换系数第 7 个是缩放因子。你不需要手算用ts_calibrate生成即可。前提是你的板子上已经编译并安装了 tslib且TSLIB_TSDEVICE指向正确的设备节点。先确认设备节点ls /dev/input/ cat /proc/bus/input/devices找到你的触摸屏对应的 event 节点比如/dev/input/event1。然后设置环境变量并运行校准export TSLIB_TSDEVICE/dev/input/event1 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/etc/ts.conf export TSLIB_PLUGINDIR/usr/lib/ts ts_calibrate屏幕上会出现十字光标依次点击五个点。完成后/etc/pointercal就生成了。如果提示open /dev/input/event1: No such file or directory说明节点名不对回到cat /proc/bus/input/devices重新确认。/etc/ts.conf的内容也要对常见配置如下module_raw input module pthres pmin1 module variance delta30 module dejitter delta100 module linearmodule_raw input表示从 Linux input 子系统读原始事件。如果你用的是老式 ADC 触摸屏可能是module_raw h3600之类按你的驱动来。module linear负责用 pointercal 做线性变换这行必须有。3.2 QWS 环境变量配置QT/E 在 QWS 模式下触摸协议通过QWS_MOUSE_PROTO指定。格式是协议名:设备节点。如果你用 tslib协议名是Tslib如果直接用 Linux input协议名是LinuxInput。在板子的启动脚本里比如/etc/profile或你的应用启动脚本加上export QTDIR/usr/local/qt-e export QWS_MOUSE_PROTOTslib:/dev/input/event1 export QWS_DISPLAYLinuxFb:/dev/fb0 export TSLIB_TSDEVICE/dev/input/event1 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/etc/ts.conf export TSLIB_PLUGINDIR/usr/lib/ts export LD_LIBRARY_PATH$QTDIR/lib:/usr/lib/ts:$LD_LIBRARY_PATH注意QWS_MOUSE_PROTO里的设备节点要和TSLIB_TSDEVICE一致。如果你在编译 QT/E 时改了qmouselinuxtp_qws.cpp里的默认路径这里的环境变量会覆盖它。如果你用的是 QT5 的 EGLFSQWS_MOUSE_PROTO 不再生效改用QT_QPA_EGLFS_TSLIB或QT_QPA_EGLFS_INTEGRATION。下一小节说。3.3 EGLFS 触摸参数配置QT5 之后EGLFS 平台插件读取触摸的方式变了。你需要设置export QT_QPA_PLATFORMeglfs export QT_QPA_EGLFS_INTEGRATIONeglfs_integration export QT_QPA_EGLFS_TSLIB1 export QT_QPA_EGLFS_PHYSICAL_WIDTH154 export QT_QPA_EGLFS_PHYSICAL_HEIGHT86 export TSLIB_TSDEVICE/dev/input/event1 export TSLIB_CALIBFILE/etc/pointercal export TSLIB_CONFFILE/etc/ts.confQT_QPA_EGLFS_TSLIB1告诉 EGLFS 用 tslib 读触摸。物理宽高按你屏幕的实际毫米数填影响的是 DPI 计算不影响触摸坐标但填错会导致界面元素缩放异常。如果你不用 tslib直接用 libinput可以设export QT_QPA_EGLFS_INTEGRATIONeglfs_kms export QT_QPA_EGLFS_KMS_CONFIG/etc/qt-eglfs-kms.json然后在 JSON 里配触摸设备。不过工控场景下 tslib 更常见因为校准文件好管理。3.4 设备节点映射的 udev 规则板子重启后 event 节点号可能变导致配置失效。用 udev 规则固定节点名# /etc/udev/rules.d/99-touchscreen.rules SUBSYSTEMinput, ATTRS{name}Goodix-TS, SYMLINKinput/touchscreen这样无论 event 号怎么变/dev/input/touchscreen始终指向你的触摸屏。然后把所有配置里的/dev/input/event1换成/dev/input/touchscreen。ATTRS{name}的值从cat /proc/bus/input/devices里的Name拿。4. 触摸坐标验证与多点触控回归测试配置写完怎么确认真的通了分三步验证原始事件、tslib 层、QT 应用层。4.1 用 evtest 看原始事件evtest /dev/input/event1手指点屏幕你应该看到类似输出Event: time 1690000000.123456, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 0 Event: time 1690000000.123456, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 400 Event: time 1690000000.123456, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 300 Event: time 1690000000.123456, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1如果这里没输出问题在驱动层跟 QT 无关。检查设备树里触摸屏的 interrupt 和 reset 引脚配置。4.2 用 ts_test 验证 tslib 层export TSLIB_TSDEVICE/dev/input/event1 ts_test屏幕上会出现一个十字你手指移动时十字跟着动。如果十字不动或者乱跳检查/etc/ts.conf里的module_raw和module linear是否加载。如果坐标偏移重新跑ts_calibrate。4.3 QT 应用层验证写一个最小 QT 程序打印触摸坐标#include QApplication #include QWidget #include QMouseEvent #include QDebug class TouchWidget : public QWidget { protected: void mousePressEvent(QMouseEvent *e) override { qDebug() press: e-pos() global: e-globalPos(); } void mouseMoveEvent(QMouseEvent *e) override { qDebug() move: e-pos(); } }; int main(int argc, char **argv) { QApplication app(argc, argv); TouchWidget w; w.resize(800, 480); w.show(); return app.exec(); }编译后运行./touch_test -qws点屏幕终端应该打印坐标。如果没打印检查QWS_MOUSE_PROTO是否设置、设备节点是否存在、LD_LIBRARY_PATH是否包含 tslib 库。4.4 多点触控回归测试如果你的触摸屏支持多点用evtest看 ABS_MT_SLOT 和 ABS_MT_TRACKING_ID 事件。QT/E 的 QWS 对多点支持有限QT5 的 EGLFS 配合 libinput 支持更好。测试动作# 同时用两根手指点屏幕观察 evtest 输出 evtest /dev/input/event1 | grep -E ABS_MT_SLOT|ABS_MT_TRACKING_ID|ABS_MT_POSITION如果只有单点事件说明驱动没上报多点检查设备树里touchscreen-max-points或类似属性。回归测试脚本可以写成#!/bin/bash # touch_regression.sh DEV/dev/input/event1 echo 开始触摸回归测试请依次点击屏幕四角和中点 for i in 1 2 3 4 5; do echo 请点击第 $i 个点... timeout 10 evtest $DEV | head -20 echo --- done5. 本篇常见错排查401、local proxy failed、reading choices、OAuth调试触摸链路时如果你同时用模型辅助查资料可能会遇到 API 调用报错。这些错和触摸本身无关但会打断你的调试节奏这里一并列出来。5.1 401 Unauthorized报错原文{error:{message:Invalid API key provided,type:invalid_request_error}}原因Key 填错、过期、或者复制时带了空格。检查你的环境变量或配置文件里的 Key确保没有多余字符。如果你在 Cline 或 Continue 里配置注意 Base URL 要填https://taotoken.net/api不要多写路径。5.2 local proxy failed报错原文Error: local proxy failed: dial tcp 127.0.0.1:7890: connect: connection refused原因你的开发机上配了本地代理但代理服务没启动。嵌入式开发机经常为了拉依赖配代理后来关了但环境变量还在。检查http_proxy和https_proxyenv | grep -i proxy unset http_proxy https_proxy all_proxy然后重试。注意这里说的是开发机上的本地代理配置问题不是让你去用什么网络工具只是清理残留的环境变量。5.3 reading choices 报错报错原文Error: reading choices: unexpected end of JSON input原因模型返回的 JSON 被截断通常是 max_tokens 设太小或者网络中断。如果你在让模型分析长源码把 max_tokens 调大或者分段发送。在 Cline 里可以在设置里调Max Tokens。5.4 OAuth 相关报错报错原文Error: OAuth token expired, please re-authenticate原因如果你用的是需要 OAuth 的客户端比如某些 IDE 插件token 过期了。重新走一遍授权流程或者在插件设置里换成 API Key 方式。TaoToken 用的是 API Key不涉及 OAuth所以如果你在插件里看到这个错说明插件还在用旧的认证方式改成填 Base URL Key 即可。5.5 CC Switch / Cline MCP / Codex auth.json 三件套如果你用 CC Switch 管理多个模型配置或者用 Cline 的 MCP 功能或者用 Codex 的 auth.json记住三件套必须齐全Base URL、Key、Model ID。CC Switch 的配置示例{ name: taotoken, baseUrl: https://taotoken.net/api, apiKey: sk-你的Key, model: claude-3-5-sonnet-20241022 }Cline 的 MCP 配置在cline_mcp_settings.json{ mcpServers: { taotoken: { url: https://taotoken.net/api, apiKey: sk-你的Key } } }Codex 的auth.json{ apiKey: sk-你的Key, baseUrl: https://taotoken.net/api, model: gpt-4o }三件套缺一不可。只填 Key 不填 Base URL会走默认端点只填 Base URL 不填 Model ID会报模型不存在。5.6 触摸链路本身的常见错回到触摸。如果你遇到open /dev/input/event1: Permission denied检查设备节点权限ls -l /dev/input/event1 chmod 666 /dev/input/event1或者把你的应用加到input组。如果 QT 程序报QWSMouseHandler: Cannot open mouse device检查QWS_MOUSE_PROTO格式冒号前后不能有空格。如果坐标偏移但ts_test正常检查 QT 的屏幕分辨率是否和触摸屏分辨率一致。QWS 下用-display参数指定EGLFS 下检查QT_QPA_EGLFS_PHYSICAL_WIDTH/HEIGHT。6. 把统一 Key 接进你的嵌入式调试流触摸链路调通之后日常开发里还有很多重复劳动读 QT/E 源码找坐标变换函数、写 tslib 校准的自动化脚本、分析 evtest 日志、对比不同板子的设备树配置。这些事如果每次都要手动翻文档很耗时间。我的做法是把 TaoToken 的 Key 配到开发机的环境变量里然后在终端里用 curl 快速查询export TAOTOKEN_KEYsk-你的Key curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_KEY \ -H Content-Type: application/json \ -d { model: claude-3-5-sonnet-20241022, messages: [{role:user,content:解释 QT/E qmouselinuxtp_qws.cpp 里坐标变换的流程}] }这样在调试板子的时候不用切浏览器就能查源码逻辑。如果你在 IDE 里写 QT 代码把 Key 配到 Cline 或 Continue 里写触摸事件处理时可以直接让模型补全。对于长期做嵌入式 HMI 的Coding Plan 更适合因为它面向持续编码场景不用每次单独调用。你可以从接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite看具体的接入方式文档里有各语言的示例。最后给一个实用技巧把触摸调试的常用命令写成脚本配合模型查询形成固定流程。比如#!/bin/bash # touch_debug.sh echo 设备节点 cat /proc/bus/input/devices | grep -A5 -i touch echo tslib 校准文件 cat /etc/pointercal 2/dev/null || echo pointercal 不存在 echo 环境变量 env | grep -E TSLIB|QWS_MOUSE|QT_QPA echo 原始事件测试5秒 timeout 5 evtest /dev/input/event1 | head -30每次板子出问题先跑这个脚本把输出贴给模型分析比你自己一行行查快得多。触摸链路的问题无非就是节点、权限、校准、协议四类脚本跑完基本能定位到哪一类。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进