RK3568 android11 usb接口TP与电磁笔触点上报优先级问题

一,问题描述

双USB接口,电容触摸跟电磁手写笔触摸会产生误触现象,所以需要在底层实现电磁笔优先级。

电磁屏优先(指当笔和手都放屏上,手不发信息),因为都是USB接口使用,电容触摸跟电磁手写笔触摸会产生误触现象;

bash 复制代码
rk3568:/ # getevent
add device 1: /dev/input/event5
  name:     "ILITEK ILITEK-TP"
add device 2: /dev/input/event0
  name:     "fdd70030.pwm"
add device 3: /dev/input/event1
  name:     "rk805 pwrkey"
add device 4: /dev/input/event4
  name:     "rk-headset"
add device 5: /dev/input/event3
  name:     "adc-keys"
add device 6: /dev/input/event2
  name:     "HUION Huion Monitor"

cat sys/kernel/debug/usb/devices 查看本地usb设备信息

bash 复制代码
rk3568:/ # cat sys/kernel/debug/usb/devices
T:  Bus=02 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#=  3 Spd=12   MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=222a ProdID=0001 Rev= 0.02
S:  Manufacturer=ILITEK
S:  Product=ILITEK-TP
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=400mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=1ms
E:  Ad=02(O) Atr=03(Int.) MxPS=  64 Ivl=1ms


T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=256c ProdID=006d Rev= 1.12
S:  Manufacturer=HUION
S:  Product=Huion Monitor
C:* #Ifs= 2 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=2ms
I:* If#= 1 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=82(I) Atr=03(Int.) MxPS=  16 Ivl=2ms

dev/input/event5 (触摸 ILITEK ILITEK-TP)

dev/input/event2 (电磁笔 HUION Huion Monitor)


二,驱动代码分析

1. TP上报

源码路径:kernel/drivers/hid/hid-multitouch.c

主要是mt_report函数:

c 复制代码
static void mt_report(struct hid_device *hid, struct hid_report *report)  //静态函数mt_report
{
        struct mt_device *td = hid_get_drvdata(hid); //通过 hid_get_drvdata 获取与 HID设备有关的多点触控设备数据结构(mt_device)
        struct hid_field *field = report->field[0];  //获取当前报告的第一个字段 field
        struct mt_report_data *rdata;

        if (!(hid->claimed & HID_CLAIMED_INPUT))  //检查设备状态
                return;

        rdata = mt_find_report_data(td, report); //查找与当前报告相关联的多点触控数据结构 rdata
        if (rdata && rdata->is_mt_collection)   //如果 rdata 存在并且它标记为多点触控集合,则调用 mt_touch_report(hid, rdata) 函数来处理该触控报告
                return mt_touch_report(hid, rdata);

        if (field && field->hidinput && field->hidinput->input)
                input_sync(field->hidinput->input);  //同步输入设备状态
}

这段代码是用于在一个 HID (人机接口设备)驱动中处理多点触控(MT, Multi-Touch)报告的函数。

2. 电磁笔上报

跟踪代码发现电磁笔使用的是hid通用驱动;
源码路径:kernel/drivers/hid/hid-input.c

上报信息主要是以下位置:

c 复制代码
if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
        if (value) {   //如果 value 为真(通常表示触控笔或指针当前在数字化仪的感应范围内)
                input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);  //表示正在使用电磁笔
                return;
        }
        input_event(input, usage->type, usage->code, 0);  //表示当前工具不再激活(使用 usage->code 设置为 0)
        input_event(input, usage->type, BTN_TOOL_RUBBER, 0);  //表示电磁笔不在使用
        return;
}

这段代码首先判断 usage 结构的 hid 字段是否等于一个特定值,这个值表明当前事件对应于数字化仪的 "InRange" 事件。


三,功能实现

思路如下:

1.在电磁笔上报信息的地方定义一个全局变量,按下设置为true,松开设置为false;

2.在TP触摸处理多点触控的位置根据变量的状态进行判断

3.电磁笔上报时,屏蔽TP触摸的上报;反之电磁笔停止上报,TP触摸正常;

参考补丁:

bash 复制代码
diff --git a/kernel/drivers/hid/hid-input.c b/kernel/drivers/hid/hid-input.c
index dd3f4aa052..e644b599c9 100644
--- a/kernel/drivers/hid/hid-input.c
+++ b/kernel/drivers/hid/hid-input.c
@@ -36,6 +36,9 @@
#define unk    KEY_UNKNOWN
+bool touch_blocked;
+EXPORT_SYMBOL(touch_blocked);

static const unsigned char hid_keyboard[256] = {
       0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
      50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
@@ -1268,12 +1271,17 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
     }
     if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
+    printk(KERN_ERR "[fy-1]:value = %d,quirks = %x, BTN_TOOL_RUBBER = %d, usage->code = %d,usage->type = %u\n",value,(*quirks & HID_QUIRK_INVERT), BTN_TOOL_RUBBER, usage->code, usage->type);
         if (value) {
             input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
+            touch_blocked = true;
+            printk(KERN_ERR "[fy-2]:value = %d,usage->code = %d,usage->type = %u,BTN_TOOL_RUBBER = %d\n",value,usage->code, usage->type, BTN_TOOL_RUBBER);
             return;
         }
         input_event(input, usage->type, usage->code, 0);
         input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
+        touch_blocked = false;
+        printk(KERN_ERR "[fy-3]:value = %d,usage->code = %d,usage->type = %u,BTN_TOOL_RUBBER = %d\n",value,usage->code, usage->type, BTN_TOOL_RUBBER);
         return;
     }
diff --git a/kernel/drivers/hid/hid-multitouch.c b/kernel/drivers/hid/hid-multitouch.c
index 0c72702fc1..ffb9a4820b 100644
--- a/kernel/drivers/hid/hid-multitouch.c
+++ b/kernel/drivers/hid/hid-multitouch.c
@@ -1366,18 +1366,28 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
     return 0;
}
+extern bool touch_blocked;
static void mt_report(struct hid_device *hid, struct hid_report *report)
{
     struct mt_device *td = hid_get_drvdata(hid);
     struct hid_field *field = report->field[0];
     struct mt_report_data *rdata;
+    printk(KERN_INFO "[FY-1]------mt_report: Entered mt_report for HID device: %p\n", hid);
     if (!(hid->claimed & HID_CLAIMED_INPUT))
         return;
     rdata = mt_find_report_data(td, report);
-    if (rdata && rdata->is_mt_collection)
-        return mt_touch_report(hid, rdata);
+    if (rdata && rdata->is_mt_collection){
+        printk(KERN_INFO "[FY-2]------mt_report: Found MT collection, processing touch report\n");
+        if(touch_blocked){
+           printk(KERN_INFO "[FY-3]------mt_report: Touch events are blocked.\n");
+           return;
+        }else{
+           printk(KERN_INFO "[FY-4]------mt_report: Touch events are open.\n");
+           return mt_touch_report(hid, rdata);
+        }
+    }
     if (field && field->hidinput && field->hidinput->input)
         input_sync(field->hidinput->input);

编译烧录后,验证功能正常(电磁笔使用时TP不上报);

相关推荐
千里马学框架6 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台6 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone6 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc6 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo6 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077006 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼6 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone6 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen6 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone6 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui