一,问题描述
双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不上报);