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不上报);

相关推荐
sweetying1 小时前
30了,人生按部就班
android·程序员
用户2018792831672 小时前
Binder驱动缓冲区的工作机制答疑
android
真夜2 小时前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app
用户2018792831672 小时前
浅析Binder通信的三种调用方式
android
用户092 小时前
深入了解 Android 16KB内存页面
android·kotlin
火车叼位3 小时前
Android Studio与命令行Gradle表现不一致问题分析
android
前行的小黑炭5 小时前
【Android】 Context使用不当,存在内存泄漏,语言不生效等等
android·kotlin·app
前行的小黑炭6 小时前
【Android】CoordinatorLayout详解;实现一个交互动画的效果(上滑隐藏,下滑出现);附例子
android·kotlin·app
用户20187928316718 小时前
Android黑夜白天模式切换原理分析
android
芦半山19 小时前
「幽灵调用」背后的真相:一个隐藏多年的Android原生Bug
android