【RK3588 Android驱动实战】USB TP XY轴反转?不用改TP固件!系统端改上报数据快速搞定

博主:旭日财富者旭日财富者 2026-02-07 3936

嵌入式Android开发的同学,大概率遇到过USB触控面板(TP)的适配坑——比如XY轴反转:明明点屏幕左边,系统却识别成右边;向上滑动,页面反而向下走。最近在RK3588平台调试USB TP时,就碰到了这个问题,TP供应商给的方案是改TP端固件,但需要重新烧录TP程序、协调供应商联调,操作麻烦还耗时间。

后来我们换了个思路:直接在Android系统端修改TP上报的坐标数据,不用动TP硬件/固件,半小时就搞定了。今天就把这个实战方案拆解清楚,附上核心patch解析,希望能帮到有同样需求的同学。

一、问题回顾:RK3588 USB TP反向烦恼

先明确下我们遇到的具体问题:

RK3588 Android 12/13系统上,接入某款USB TP后,触控功能正常,但坐标映射完全反了——比如TP物理坐标的X轴(横向)对应系统的Y轴(纵向),且单轴方向还存在反转(比如按TP右侧,系统识别为左侧)。

最初联系TP供应商,得到的解决方案是:

1.提供TP的固件烧录工具;

2.修改TP内部的坐标映射参数;

3.重新烧录固件到TP芯片。

但这个方案有明显痛点:

需额外安装烧录工具,部分工具还依赖Windows系统;

烧录过程有风险,操作不当可能导致TP变砖;

若后续换批次TP,可能需要重复适配,灵活性差。

既然TP是通过USB HID协议向系统上报坐标数据,那能不能在系统驱动层拦截并修改这些数据?答案是肯定的——这就是我们最终采用的方案。

二、核心方案

1.核心逻辑:hid-multitouch.c(坐标转换的关键)

文件路径:kernel-5.10/drivers/hid/hid-multitouch.c

wKgZPGkaixGAUs5yAACFuC-kohc057.png

这是USB HID多点触控驱动的核心文件,我们的坐标反转+交换逻辑就加在这里。TP上报的原始X/Y坐标会经过这个文件处理后,再传递给Android输入子系统,所以在这里修改数据最直接有效。

先看原代码和修改后的对比:

// 原代码(直接上报原始坐标)input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);// 修改后(先转换坐标,再上报)intmax_x = input_abs_get_max(input, ABS_MT_POSITION_X);intmax_y = input_abs_get_max(input, ABS_MT_POSITION_Y);intnew_x = max_y - *slot->y; intnew_y = *slot->x; new_x = clamp_val(new_x,0, max_y);new_y = clamp_val(new_y,0, max_x);input_event(input, EV_ABS, ABS_MT_POSITION_X, new_x);input_event(input, EV_ABS, ABS_MT_POSITION_Y, new_y);

这部分是核心,必须逐行理解

步骤1:获取TP的最大坐标值

intmax_x = input_abs_get_max(input, ABS_MT_POSITION_X);intmax_y = input_abs_get_max(input, ABS_MT_POSITION_Y);

input_abs_get_maxLinux输入子系统提供的API,用于获取指定输入设备(这里是USB TP)的绝对坐标最大值

比如TP的分辨率是1920x1080,那么max_x=1919max_y=1079(坐标从0开始计数);

为什么要获取最大值?因为后续要通过最大值-原始坐标实现单轴方向反转

步骤2:坐标交换+方向反转

intnew_x = max_y - *slot->y; intnew_y = *slot->x; 

这两行是解决“XY轴反转的关键,我们用一个实际例子理解:

假设TP原始上报坐标是(x=200y=500),且TPmax_x=1919max_y=1079

原逻辑:系统收到X=200Y=500(对应错误的轴映射);

新逻辑:

new_x = 1079 - 500 = 579(用Y轴最大值减原始Y,实现Y轴反转,再作为新X);

new_y = 200(直接把原始X作为新Y,实现XY轴交换);

最终系统收到X=579Y=200,正好修正了轴反转问题。

步骤3:限制坐标范围(防异常)

new_x= clamp_val(new_x,0, max_y);new_y= clamp_val(new_y,0, max_x);

clamp_valLinux内核的工具函数,作用是将数值限制在指定范围内(小于最小值则取最小值,大于最大值则取最大值);

为什么需要?防止TP上报异常数据(比如负数、超出最大值),导致系统识别到无效坐标,出现触控漂移或无响应;

比如new_x计算后是- 10,会被修正为0;若new_x1080(超过max_y=1079),会被修正为1079

三、测试验证:修改后效果如何?

修改完上述3个文件后,按以下步骤验证:

1.重新编译RK3588内核;

2.将编译后的内核镜像(boot.img)烧录到RK3588开发板;

3.接入USB TP,测试触控功能。

验证结果

单点触控:点击屏幕任意位置,光标精准对应,无偏移;

滑动操作:向上///右滑动,页面滚动方向完全正确;

多点触控:双指缩放图片、双指旋转,功能正常无异常;

边缘测试:点击TP边缘区域,无超出范围无响应问题。

整个适配过程从修改代码到验证通过,流程简单,比供应商提供的TP固件方案效率高太多。

四、实用小贴士:适配其他TP的扩展思路

这个方案的优势在于通用性”——如果后续换其他型号的USB TP,只要遇到类似的轴反转方向反问题,都可以参考这个思路修改,只需调整hid-multitouch.c中的坐标转换公式:

问题类型

调整思路

示例公式(假设原始x/ymax_x/max_y

XY轴交换

new_x =原始ynew_y =原始x

new_x=*slot->y; new_y=*slot->x

X轴方向反

new_x = max_x -原始xnew_y =原始y

new_x=max_x-*slot->x; new_y=*slot->y

Y轴方向反

new_x =原始xnew_y = max_y -原始y

new_x=*slot->x; new_y=max_y-*slot->y

XY轴交换+双轴方向反

new_x = max_y -原始ynew_y = max_x -原始x

new_x=max_y-*slot->y; new_y=max_x-*slot->x

修改前必做的准备

getevent命令查看TP的原始坐标数据(Android终端执行getevent -l),确认原始x/y的范围和上报规律,再针对性调整公式,避免盲目修改。

五、总结:嵌入式适配的灵活思维

这次RK3588 USB TP的适配,本质上是绕开硬件限制,用软件灵活解决问题。在嵌入式开发中,我们常会遇到硬件端修改麻烦的场景,此时不妨多想想:

驱动层能不能拦截数据做处理?

系统层有没有API能适配需求?

应用层能不能通过配置兼容差异?

毕竟,软件的灵活性才是嵌入式开发的核心优势。如果大家在TP适配中还遇到过其他坑(比如多点触控失效、触控延迟),欢迎在评论区分享,我们一起探讨解决方案~