做嵌入式Android開發(fā)的同學(xué),大概率遇到過USB觸控面板(TP)的適配坑——比如XY軸反轉(zhuǎn):明明點(diǎn)屏幕左邊,系統(tǒng)卻識別成右邊;向上滑動(dòng),頁面反而向下走。最近在RK3588平臺調(diào)試USB TP時(shí),就碰到了這個(gè)問題,TP供應(yīng)商給的方案是改TP端固件,但需要重新燒錄TP程序、協(xié)調(diào)供應(yīng)商聯(lián)調(diào),操作麻煩還耗時(shí)間。
后來我們換了個(gè)思路:直接在Android系統(tǒng)端修改TP上報(bào)的坐標(biāo)數(shù)據(jù),不用動(dòng)TP硬件/固件,半小時(shí)就搞定了。今天就把這個(gè)實(shí)戰(zhàn)方案拆解清楚,附上核心patch解析,希望能幫到有同樣需求的同學(xué)。
一、問題回顧:RK3588 USB TP的“反向”煩惱
先明確下我們遇到的具體問題:
在RK3588 Android 12/13系統(tǒng)上,接入某款USB TP后,觸控功能正常,但坐標(biāo)映射完全反了——比如TP物理坐標(biāo)的X軸(橫向)對應(yīng)系統(tǒng)的Y軸(縱向),且單軸方向還存在反轉(zhuǎn)(比如按TP右側(cè),系統(tǒng)識別為左側(cè))。
最初聯(lián)系TP供應(yīng)商,得到的解決方案是:
1.提供TP的固件燒錄工具;
2.修改TP內(nèi)部的坐標(biāo)映射參數(shù);
3.重新燒錄固件到TP芯片。
但這個(gè)方案有明顯痛點(diǎn):
?需額外安裝燒錄工具,部分工具還依賴Windows系統(tǒng);
?燒錄過程有風(fēng)險(xiǎn),操作不當(dāng)可能導(dǎo)致TP變磚;
?若后續(xù)換批次TP,可能需要重復(fù)適配,靈活性差。
既然TP是通過USB HID協(xié)議向系統(tǒng)上報(bào)坐標(biāo)數(shù)據(jù),那能不能在系統(tǒng)驅(qū)動(dòng)層攔截并修改這些數(shù)據(jù)?答案是肯定的——這就是我們最終采用的方案。
二、核心方案
1.核心邏輯:hid-multitouch.c(坐標(biāo)轉(zhuǎn)換的關(guān)鍵)
文件路徑:kernel-5.10/drivers/hid/hid-multitouch.c

這是USB HID多點(diǎn)觸控驅(qū)動(dòng)的核心文件,我們的坐標(biāo)反轉(zhuǎn)+交換邏輯就加在這里。TP上報(bào)的原始X/Y坐標(biāo)會(huì)經(jīng)過這個(gè)文件處理后,再傳遞給Android輸入子系統(tǒng),所以在這里修改數(shù)據(jù)最直接有效。
先看原代碼和修改后的對比:
// 原代碼(直接上報(bào)原始坐標(biāo))input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);// 修改后(先轉(zhuǎn)換坐標(biāo),再上報(bào))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的最大坐標(biāo)值
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_max:Linux輸入子系統(tǒng)提供的API,用于獲取指定輸入設(shè)備(這里是USB TP)的“絕對坐標(biāo)最大值”;
?比如TP的分辨率是1920x1080,那么max_x=1919,max_y=1079(坐標(biāo)從0開始計(jì)數(shù));
?為什么要獲取最大值?因?yàn)楹罄m(xù)要通過“最大值-原始坐標(biāo)”實(shí)現(xiàn)單軸方向反轉(zhuǎn)。
步驟2:坐標(biāo)交換+方向反轉(zhuǎn)
intnew_x = max_y - *slot->y;intnew_y = *slot->x;
這兩行是解決“XY軸反轉(zhuǎn)”的關(guān)鍵,我們用一個(gè)實(shí)際例子理解:
假設(shè)TP原始上報(bào)坐標(biāo)是(x=200,y=500),且TP的max_x=1919,max_y=1079:
?原邏輯:系統(tǒng)收到X=200,Y=500(對應(yīng)錯(cuò)誤的軸映射);
?新邏輯:
new_x = 1079 - 500 = 579(用Y軸最大值減原始Y,實(shí)現(xiàn)Y軸反轉(zhuǎn),再作為新X);
new_y = 200(直接把原始X作為新Y,實(shí)現(xiàn)XY軸交換);
最終系統(tǒng)收到X=579,Y=200,正好修正了軸反轉(zhuǎn)問題。
步驟3:限制坐標(biāo)范圍(防異常)
new_x= clamp_val(new_x,0, max_y);new_y= clamp_val(new_y,0, max_x);
?clamp_val:Linux內(nèi)核的工具函數(shù),作用是“將數(shù)值限制在指定范圍內(nèi)”(小于最小值則取最小值,大于最大值則取最大值);
?為什么需要?防止TP上報(bào)異常數(shù)據(jù)(比如負(fù)數(shù)、超出最大值),導(dǎo)致系統(tǒng)識別到“無效坐標(biāo)”,出現(xiàn)觸控漂移或無響應(yīng);
?比如new_x計(jì)算后是- 10,會(huì)被修正為0;若new_x是1080(超過max_y=1079),會(huì)被修正為1079。
三、測試驗(yàn)證:修改后效果如何?
修改完上述3個(gè)文件后,按以下步驟驗(yàn)證:
1.重新編譯RK3588內(nèi)核;
2.將編譯后的內(nèi)核鏡像(boot.img)燒錄到RK3588開發(fā)板;
3.接入USB TP,測試觸控功能。
驗(yàn)證結(jié)果:
?單點(diǎn)觸控:點(diǎn)擊屏幕任意位置,光標(biāo)精準(zhǔn)對應(yīng),無偏移;
?滑動(dòng)操作:向上/下/左/右滑動(dòng),頁面滾動(dòng)方向完全正確;
?多點(diǎn)觸控:雙指縮放圖片、雙指旋轉(zhuǎn),功能正常無異常;
?邊緣測試:點(diǎn)擊TP邊緣區(qū)域,無“超出范圍”或“無響應(yīng)”問題。
整個(gè)適配過程從修改代碼到驗(yàn)證通過,流程簡單,比供應(yīng)商提供的“改TP固件”方案效率高太多。
四、實(shí)用小貼士:適配其他TP的擴(kuò)展思路
這個(gè)方案的優(yōu)勢在于“通用性”——如果后續(xù)換其他型號的USB TP,只要遇到類似的“軸反轉(zhuǎn)”或“方向反”問題,都可以參考這個(gè)思路修改,只需調(diào)整hid-multitouch.c中的坐標(biāo)轉(zhuǎn)換公式:
|
問題類型
|
調(diào)整思路
|
示例公式(假設(shè)原始x/y,max_x/max_y)
|
|
僅XY軸交換
|
new_x =原始y;new_y =原始x
|
new_x=*slot->y; new_y=*slot->x
|
|
僅X軸方向反
|
new_x = max_x -原始x;new_y =原始y
|
new_x=max_x-*slot->x; new_y=*slot->y
|
|
僅Y軸方向反
|
new_x =原始x;new_y = max_y -原始y
|
new_x=*slot->x; new_y=max_y-*slot->y
|
|
XY軸交換+雙軸方向反
|
new_x = max_y -原始y;new_y = max_x -原始x
|
new_x=max_y-*slot->y; new_y=max_x-*slot->x
|
修改前必做的準(zhǔn)備:
用getevent命令查看TP的原始坐標(biāo)數(shù)據(jù)(Android終端執(zhí)行getevent -l),確認(rèn)原始x/y的范圍和上報(bào)規(guī)律,再針對性調(diào)整公式,避免盲目修改。
五、總結(jié):嵌入式適配的“靈活思維”
這次RK3588 USB TP的適配,本質(zhì)上是“繞開硬件限制,用軟件靈活解決問題”。在嵌入式開發(fā)中,我們常會(huì)遇到“硬件端修改麻煩”的場景,此時(shí)不妨多想想:
?驅(qū)動(dòng)層能不能攔截?cái)?shù)據(jù)做處理?
?系統(tǒng)層有沒有API能適配需求?
?應(yīng)用層能不能通過配置兼容差異?
畢竟,軟件的靈活性才是嵌入式開發(fā)的“核心優(yōu)勢”。如果大家在TP適配中還遇到過其他坑(比如多點(diǎn)觸控失效、觸控延遲),歡迎在評論區(qū)分享,我們一起探討解決方案~
-
嵌入式
+關(guān)注
關(guān)注
5198文章
20435瀏覽量
333907 -
Android
+關(guān)注
關(guān)注
12文章
4023瀏覽量
133957 -
RK3588
+關(guān)注
關(guān)注
8文章
555瀏覽量
7316
發(fā)布評論請先 登錄
瑞芯微RK3588開發(fā)板RK3588 EVB和RK3588S EVB解讀
RK3588 Android+Linux雙系統(tǒng)方案的實(shí)現(xiàn)
RK3588 PCB推薦疊層及阻抗設(shè)計(jì)
用這份PCB設(shè)計(jì)實(shí)戰(zhàn)手冊輕松搞定RK3588
用這份PCB設(shè)計(jì)實(shí)戰(zhàn)手冊,輕松搞定RK3588
迅為RK3588開發(fā)板深度剖析丨首選的性能
RK3588采集Cameralink圖像快速搭建系統(tǒng)辦法
RK3588快速上手資料合集
如何實(shí)現(xiàn)基于RK3588的Android系統(tǒng)與Linux系統(tǒng)切換呢
RK3588 SDK編譯與固件燒寫步驟
RK3588 Android系統(tǒng)編譯命令
RK3588 Android 12.0 SDK編譯步驟分享
保姆級教程!RK3588 Linux6.1?固件簽名完整實(shí)現(xiàn)方案(不含rootfs)
【RK3588 Android驅(qū)動(dòng)實(shí)戰(zhàn)】USB TP XY軸反轉(zhuǎn)?不用改TP固件!系統(tǒng)端改上報(bào)數(shù)據(jù)快速搞定
評論