基于“xxx” Androidx平台的驱动及系统开发 之 触摸板篇

目录

  • 一、基于全志 A133 Android10平台,适配1366x768 - ilitek2511触摸
    • 1、原理图分析
    • 2、驱动移植与适配
    • 3、补丁和资源文件
  • 二、基于瑞芯微 RK3566 Android11平台,适配GT9XX触摸
    • 1、原理图分析
    • 2、补丁及资源文件
  • 三、遇到的问题与解决
    • 1、基于amlogic Android9平台,使用(V-By-One接口LCD屏,USB接口触摸板)的一体式触摸屏
    • 2、基于RK3566 Android11平台,使用(LVDS接口LCD屏,I2C接口触摸板)的分离式触摸屏
    • 3、基于GT9XX触摸IC 触摸出现 -> "点偏位" 或 "划线异常不连续"
      • ◕对该触摸驱动如何通过“CTP_CFG_GROUPx”这个配置组表更新到触摸IC寄存器内部的
      • 有些人可能是通过外部去对触摸进行矫正的,那么就需要把自动写入对应的配置信息组表功能给关了
    • 4、在屏幕熄屏情况下做触摸唤醒屏幕功能,但是内核版本原因,无法使用原厂提供的手势识别功能

一、基于全志 A133 Android10平台,适配1366x768 - ilitek2511触摸

1、原理图分析

在这里插入图片描述  ilitek2511触摸使用的时I2C通信,因此重点关注SDA(数据)、SCK(时钟)、INT(中断)、RST(复位)这四个引脚即可。

2、驱动移植与适配

  首先我们需要弄清除,触摸驱动是干嘛的,其实它只不过是通过I2C通信方式获取触摸板上触发的每个坐标点信息,通过事件方式上报,像这种通用的事件上报方式(触摸屏),上层的HAL、Framework等,原生Android或者原厂都是已经给做好了,已经只需要移植驱动层即可,一般别的层无需做修改的。
  通过触摸IC厂商提供的驱动移植资料修改设备树,如下图原厂提供的设备树和我修改好的设备树。
在这里插入图片描述
  设备树配置好后,直接将相关的驱动文件拷贝到 a\longan\kernel\linux-4.9\drivers\input\touchscreen 目录下创建的ilitek文件夹下即可,如下图所示。
在这里插入图片描述  通过以上操作,基本是已经将触摸驱动移植好了。

3、补丁和资源文件

下载链接

二、基于瑞芯微 RK3566 Android11平台,适配GT9XX触摸

1、原理图分析

在这里插入图片描述

2、补丁及资源文件

  这里就不多分析了,直接给上补丁文件。
下载链接

三、遇到的问题与解决

1、基于amlogic Android9平台,使用(V-By-One接口LCD屏,USB接口触摸板)的一体式触摸屏

出现问题1:明明获取的USB设备,但是一直处于disconnected断开,一直打印不支持该USB设备,日志如下图所示
在这里插入图片描述
解决方法1:其实这个是控制板卡上的液晶屏的参数设置不对引起的,使得它们与触摸控制器不匹配,从而使触摸屏功能无法正常工作。因此只需要更具屏幕规格书修改屏幕参数即可。

2、基于RK3566 Android11平台,使用(LVDS接口LCD屏,I2C接口触摸板)的分离式触摸屏

出现问题1:因为触摸板和LCD屏是分离的,因此有可能出现整合者将触摸板和LCD屏摆放的起始方向不一致 或者 触摸板默认竖屏,而屏幕默认横屏, 这两种原因都会导致触摸和显示UI对不上。
解决方法1:在device/rockchip/3566x/目录下的build.prop文件中添加 persist.sys.touch.orientation=90, 如我设置90就是说将触摸板旋转方向为90度,这样就可以使UI和触摸板对上了。

3、基于GT9XX触摸IC 触摸出现 -> “点偏位” 或 “划线异常不连续”

出现的问题1:在原厂提供的文档可以可知,一般每一种触摸IC都有对应的“CTP_CFG_GROUP”这个触摸配置组的,它作用就是优化矫正触摸的。
解决方法1:在drivers\input\touchscreen\gt9xxnew\gt9xx.h文件中将原厂提供的.cfg峰位文件内从内容替换对应CTP_CFG_GROUPx中的内容,如果不确定CTP_CFG_GROUPx是哪个,那可以选择最无脑的方法,将CTP_CFG_GROUP[1~n]中的内容都给替换掉即可。

◕对该触摸驱动如何通过“CTP_CFG_GROUPx”这个配置组表更新到触摸IC寄存器内部的

  找到drivers\input\touchscreen\gt9xxnew\gt9xx.c这个文件,该文件是触摸主功能的驱动文件。
  在goodix_ts_probe函数下找到如下图的函数调用:
在这里插入图片描述
  通过该函数索引到函数实现的位置,这里我把源码贴出来,已注释方式解释了。

/*******************************************************
Function:Initialize gtp.
Input:ts: goodix private data
Output:Executive outcomes.0: succeed, otherwise: failed
*******************************************************/
static s32 gtp_init_panel(struct goodix_ts_data *ts)
{s32 ret = -1;#if GTP_DRIVER_SEND_CFGs32 i = 0;u8 check_sum = 0;u8 opr_buf[16] = {0};u8 sensor_id = 0;/***************************(1)*********************************//* 这一部分是获取gt9xx.h文件定义的CTP_CFG_GROUPx配置信息组的信息到cfg_info_groupx[]中 */u8 cfg_info_group1[] = CTP_CFG_GROUP1;u8 cfg_info_group2[] = CTP_CFG_GROUP2;u8 cfg_info_group3[] = CTP_CFG_GROUP3;u8 cfg_info_group4[] = CTP_CFG_GROUP4;u8 cfg_info_group5[] = CTP_CFG_GROUP5;u8 cfg_info_group6[] = CTP_CFG_GROUP6;u8 cfg_info_group7[] = CTP_CFG_GROUP7;u8 cfg_info_group8[] = CTP_CFG_GROUP8;/***************************(1)*********************************//***************************(2)*********************************//* 这个是创建send_cfg_buf数组,将上面活动的cfg_info_groupx信息保以元素存到该数组里 */u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3,cfg_info_group4, cfg_info_group5, cfg_info_group6,cfg_info_group7, cfg_info_group8};/***************************(2)*********************************//***************************(3)*********************************//* CFG_GROUP_LEN这个方法在gt9xx.h文件中有定义,原型是#define CFG_GROUP_LEN(p_cfg_grp)  (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0])),它是计算数组的长度的 */u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1),CFG_GROUP_LEN(cfg_info_group2),CFG_GROUP_LEN(cfg_info_group3),CFG_GROUP_LEN(cfg_info_group4),CFG_GROUP_LEN(cfg_info_group5),CFG_GROUP_LEN(cfg_info_group6),CFG_GROUP_LEN(cfg_info_group7),CFG_GROUP_LEN(cfg_info_group8)};/***************************(3)*********************************/dprintk(DEBUG_INIT,"Config Groups Lengths: %d, %d, %d, %d, %d, %d, %d, %d\n",cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], cfg_info_len[3],cfg_info_len[4], cfg_info_len[5], cfg_info_len[6], cfg_info_len[7]);#if GTP_COMPATIBLE_MODEif (CHIP_TYPE_GT9F == ts->chip_type){ts->fw_error = 0;}else
#endif{/***************************(4)*********************************//* 检测固件是否正常 */ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);if (SUCCESS == ret){if (opr_buf[0] != 0xBE){ts->fw_error = 1;printk("Firmware error, no config sent!\n");return -1;}}/***************************(4)*********************************/}/***************************(5)*********************************/if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&(!cfg_info_len[3]) && (!cfg_info_len[4]) &&(!cfg_info_len[5]) && (!cfg_info_len[6]) &&(!cfg_info_len[7])){/* 如果所有配置信息组内容都为空,sensor_id值设置为0 */sensor_id = 0;}else{#if GTP_COMPATIBLE_MODEmsleep(50);#endif//       ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1);/* 下面是判断配置信息的名称是对应哪个触摸IC的名称,从而再设置其对应的sensor_id值 */dprintk(DEBUG_INIT,"CTP name : %s\n",config_info.name);if (!strcmp(config_info.name,"gt9271_mb976a9")){= 0;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name,"gt9110_wt097")){sensor_id = 1;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name,"gt9271_wt097")){sensor_id = 2;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name,"gt9110_g200")){sensor_id = 3;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name,"gt9271_noah")){sensor_id = 4;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name,"gt9271_p2")){sensor_id = 5;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name, "gt911_1060")) {sensor_id = 6;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else if (!strcmp(config_info.name, "gt911_784")) {sensor_id = 7;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);} else {sensor_id = 0;dprintk(DEBUG_INIT,"gt9xx:sensor_id = %d\n",sensor_id);}ret = SUCCESS;if (SUCCESS == ret){if (sensor_id >= 0x08){printk("Invalid sensor_id(0x%02X), No Config Sent!\n", sensor_id);ts->pnl_init_error = 1;return -1;}}else{printk("Failed to get sensor_id, No config sent!\n");ts->pnl_init_error = 1;return -1;}dprintk(DEBUG_INIT,"Sensor_ID: %d", sensor_id);}/***************************(5)*********************************//***************************(6)*********************************//* 上面设置的sensor_id值就是用来选择send_cfg_buf数组对应的触配置信息组元素的,这里获取对应配置信息组表的长度 */ts->gtp_cfg_len = cfg_info_len[sensor_id];/***************************(6)*********************************/dprintk(DEBUG_INIT,"CTP_CONFIG_GROUP%d used, config length: %d\n", sensor_id + 1, ts->gtp_cfg_len);/***************************(7)*********************************//* 用获取对应配置信息组表的长度与定义的配置信息组表最小长度作对比,确保配置信息组表的数据在长度上是符合的 */if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH){printk("Config Group%d is INVALID CONFIG GROUP(Len: %d)! NO Config Sent! You need to check you header file CFG_GROUP section!\n", sensor_id+1, ts->gtp_cfg_len);ts->pnl_init_error = 1;return -1;}/***************************(7)*********************************/#if GTP_COMPATIBLE_MODEif (CHIP_TYPE_GT9F == ts->chip_type){ts->fixed_cfg = 0;}else
#endif{/***************************(8)*********************************//* 获取IC寄存器对应的配置信息版本 */ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);if (ret == SUCCESS){dprintk(DEBUG_INIT,"CFG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X\n", sensor_id+1,send_cfg_buf[sensor_id][0], send_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);if (opr_buf[0] < 155){grp_cfg_version = send_cfg_buf[sensor_id][0];       // backup group config versionsend_cfg_buf[sensor_id][0] = 0x00;ts->fixed_cfg = 0;	/* 如果是opr_buf[0] < 155这种条件下,那么这个配置信息组不设置为固定不变标志 */}else        // treated as fixed config, not send config{dprintk(DEBUG_INIT,"Ic fixed config with config version(%d, 0x%02X)\n", opr_buf[0], opr_buf[0]);ts->fixed_cfg = 1;	/* 配置信息组设置为固定不变标志 */gtp_get_info(ts);return 0;}}else{printk("Failed to get ic config version!No config sent!\n");return -1;}/***************************(8)*********************************/}/***************************(9)*********************************//* 将send_cfg_buf[sensor_id]这个对应的配置信息组表信息拷贝到 config[GTP_ADDR_LENGTH]这个数组指定的开始位置中 */memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len);/***************************(9)*********************************/#if GTP_CUSTOM_CFGconfig[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);if (GTP_INT_TRIGGER == 0)  //RISING{config[TRIGGER_LOC] &= 0xfe;}else if (GTP_INT_TRIGGER == 1)  //FALLING{config[TRIGGER_LOC] |= 0x01;}
#endif  // GTP_CUSTOM_CFG/***************************(10)*********************************//* 计算校验和,并将校验和设置到config数组中 */check_sum = 0;for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++){check_sum += config[i];}config[ts->gtp_cfg_len] = (~check_sum) + 1;/***************************(10)*********************************/#else // driver not send configts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH);if (ret < 0){GTP_ERROR("Read Config Failed, Using Default Resolution & INT Trigger!");ts->abs_x_max = GTP_MAX_WIDTH;ts->abs_y_max = GTP_MAX_HEIGHT;ts->int_trigger_type = GTP_INT_TRIGGER;}#endif // GTP_DRIVER_SEND_CFG/***************************(11)*********************************//* 修正abs_x_max、abs_y_max、int_trigger_type的值   */if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)){ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;}/***************************(11)*********************************/#if GTP_COMPATIBLE_MODEif (CHIP_TYPE_GT9F == ts->chip_type){u8 sensor_num = 0;u8 driver_num = 0;u8 have_key = 0;have_key = (config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01);if (1 == ts->is_950){driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];if (have_key){driver_num--;}ts->bak_ref_len = (driver_num * (sensor_num - 1) + 2) * 2 * 6;}else{driver_num = (config[CFG_LOC_DRVA_NUM] & 0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F);if (have_key){driver_num--;}sensor_num = (config[CFG_LOC_SENS_NUM] & 0x0F) + ((config[CFG_LOC_SENS_NUM] >> 4) & 0x0F);ts->bak_ref_len = (driver_num * (sensor_num - 2) + 2) * 2;}GTP_INFO("Drv * Sen: %d * %d(key: %d), X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x",driver_num, sensor_num, have_key, ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);return 0;}else
#endif{#if GTP_DRIVER_SEND_CFG/***************************(12)*********************************//* 通过调用gtp_send_cfg将已经整好的config配置信息组表数据写入到触摸IC对应的寄存器中 */ret = gtp_send_cfg(ts->client);if (ret < 0){GTP_ERROR("Send config error.");}// set config version to CTP_CFG_GROUP, for resume to send configconfig[GTP_ADDR_LENGTH] = grp_cfg_version;check_sum = 0;for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++){check_sum += config[i];}config[ts->gtp_cfg_len] = (~check_sum) + 1;/***************************(12)*********************************/#endifGTP_INFO("X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x", ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);}msleep(10);return 0;
}

  gtp_send_cfg函数原型,如下所示:

/*******************************************************
Function:Send config.
Input:client: i2c device.
Output:result of i2c write operation.1: succeed, otherwise: failed
*********************************************************/s32 gtp_send_cfg(struct i2c_client *client)
{s32 ret = 2;#if GTP_DRIVER_SEND_CFGs32 retry = 0;struct goodix_ts_data *ts = i2c_get_clientdata(client);if (ts->fixed_cfg){GTP_INFO("Ic fixed config, no config sent!");return 0;}else if (ts->pnl_init_error){GTP_INFO("Error occured in init_panel, no config sent");return 0;}GTP_INFO("Driver send config.");for (retry = 0; retry < 5; retry++){ret = gtp_i2c_write(client, config , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);if (ret > 0){break;}}
#endifreturn ret;
}

有些人可能是通过外部去对触摸进行矫正的,那么就需要把自动写入对应的配置信息组表功能给关了

  在gt9xx.h文件中将#define GTP_DRIVER_SEND_CFG 1设置成0即可。

4、在屏幕熄屏情况下做触摸唤醒屏幕功能,但是内核版本原因,无法使用原厂提供的手势识别功能

出现问题1:由于我使用的内核版本与移植的触摸驱动使用的内核版本相差较大,导致无法使用原厂提供的手势识别功能。
须知:一般来说,触摸芯片厂商提供的触摸驱动内部有自带手势识别处理程序,也就是说一般是带有触摸唤醒的功能的。但是,一般默认是不使能的,也就是需要通过宏定义取打开的,我这里以Goodix Touchscreen驱动举例:

static void goodix_ts_work_func(struct work_struct *work)

  这个函数就是处理手势识别的处理工作函数,那么这个就需要先启用“GTP_GESTURE_WAKEUP”这个宏定义才能开启手势功能的程序,而手势功能的程序需要启用“CONFIG_HAS_EARLYSUSPEND”这个挂起功能宏定义,才能让手势功能正常使用,但遗憾的是开启“CONFIG_HAS_EARLYSUSPEND”这个挂机功能的宏定义,有几个使用的内核接口函数都不存在,也就说明该驱动程序的手势功能在我这个Linux内核版本不支持。
解决方法1:我的Linux内核版本不支持,因此只能自己手动获取屏幕熄屏和亮屏状态,然后在上报触摸事件是上报“KEY_POWER”事件来开启屏幕。所以我需要先获取屏幕是开启还是休眠状态,通过这个状态去控制是否上报“KEY_POWER”事件来开启屏幕,从而避免在开屏状态下上报了“KEY_POWER”事件导致关屏发生。
  这里我将我修改的补丁贴出,如下所示:

commit cdc3304684b7d6ef469a2e8ef401e5882ef07748
Author: dengjiawen <1411471554@qq.com>
Date:   Fri Oct 20 14:32:46 2023 +0800屏幕息屏或者睡眠模式下,可触摸唤醒屏幕(基于gt9xx触摸系列添加该功能)diff --git a/longan/kernel/linux-4.9/drivers/input/touchscreen/gt9xxnew/gt9xx.c b/longan/kernel/linux-4.9/drivers/input/touchscreen/gt9xxnew/gt9xx.c
index 77dc9bc566..af1bc4be38 100644
--- a/longan/kernel/linux-4.9/drivers/input/touchscreen/gt9xxnew/gt9xx.c
+++ b/longan/kernel/linux-4.9/drivers/input/touchscreen/gt9xxnew/gt9xx.c
@@ -50,7 +50,9 @@#include <linux/irq.h>#include "gt9xx.h"#include <linux/pm_runtime.h>
+#include "../../../video/fbdev/sunxi/disp2/disp/dev_disp.h"+extern int get_screen_status(void);     /* 声明引入获取屏幕状态函数 */#ifdef CONFIG_PM#include <linux/pm.h>#endif
@@ -664,6 +666,22 @@ static void gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
+
+/************************* 获取屏幕状态,上报KEY_POWER事件来打开屏幕 *********************************/
+    printk("get_screen_status = %d\n",get_screen_status());
+    if(get_screen_status()) {
+        /* 亮屏状态,不发出KEY_POWER事件唤醒屏幕 */
+        printk("screen is open\n");
+    } else {
+        /* 熄屏状态,发出KEY_POWER事件唤醒屏幕 */
+        input_event(ts->input_dev,EV_KEY,KEY_POWER,1);
+        input_sync(ts->input_dev);
+        input_event(ts->input_dev,EV_KEY,KEY_POWER,0);
+        input_sync(ts->input_dev);
+        printk("screen is close,in open the screen......\n");
+    }
+/*****************************************************************************************************/
+input_mt_sync(ts->input_dev);#endif@@ -2150,7 +2168,7 @@ static s8 gtp_request_input_dev(struct goodix_ts_data *ts)#if GTP_ICS_SLOT_REPORTinput_mt_init_slots(ts->input_dev, 16);     // in case of "out of memory"#else
-    ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+    ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) | BIT_MASK(EV_KEY);    /* 增加外部按键事件掩码,用于KEY_POWER事件 */#endif__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);@@ -2169,7 +2187,7 @@ if(gtp_gesture_wakeup)input_set_capability(ts->input_dev, EV_KEY, ctp_key_list[index]);}//#endif
-
+    input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);     /* 将按键功能 KEY_POWER 添加到输入设备中的按键功能列表中。这意味着输入设备可以检测到并报告关于电源键的按下和释放事件 */if(1 == exchange_x_y_flag)swap(ts->abs_x_max, ts->abs_y_max);diff --git a/longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/dev_disp.c b/longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/dev_disp.c
index 16c45a6529..8c3006fd25 100644
--- a/longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/dev_disp.c
+++ b/longan/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/dev_disp.c
@@ -97,6 +97,8 @@ int composer_init(struct disp_drv_info *p_disp_drv);int hwc_dump(char *buf);#endif+static int screen_status = 0;	/* 定义一个静态的屏幕状态变量 */
+static void disp_shutdown(struct platform_device *pdev);static ssize_t disp_sys_show(struct device *dev,struct device_attribute *attr, char *buf)
@@ -3009,6 +3011,7 @@ static int disp_runtime_suspend(struct device *dev)if (ret < 0) {dev_err(dev, "can't request output direction lcd_pwr_gpio gpio \n");}
+		screen_status = 0;}pr_info("%s finish\n", __func__);@@ -3077,6 +3080,7 @@ static int disp_runtime_resume(struct device *dev)if (ret < 0) {dev_err(dev, "can't request output direction lcd_pwr_gpio gpio \n");}
+		screen_status = 1;}pr_info("%s finish\n", __func__);@@ -3111,6 +3115,14 @@ static int disp_runtime_idle(struct device *dev)}#endif+/* 实现获取屏幕状态的函数,并导出共享 */
+int get_screen_status(void)
+{
+	return screen_status;
+}
+EXPORT_SYMBOL(get_screen_status);
+/***********************************/
+int disp_suspend(struct device *dev){u32 screen_id = 0;

解决方法2:修改原厂驱动源码,使其手势功能程序兼容本地使用的内核版本。
  在gt9xx.c文件中找到static void goodix_ts_work_func(struct work_struct *work)这个函数,这个函数就是处理事件上报功能的,如下图是我截取的原厂驱动双击屏幕开屏的程序段。
在这里插入图片描述
  这图程序可以看出,它是通过读取记录触摸手势状态的寄存器值来判断触发双击开屏功能的,如果触发了那么就会上报"KEY_POWER"事件来达到开屏目的,而它的屏幕状态通过doze_status这个静态变量取设置与判断的,最后会清除记录触摸手势状态的寄存器的值。
  至于具体修改方法就自行取尝试啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/513735.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【软件工程】浅谈讲解单元测试

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;软件工程 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 1. 单元测试的定义和作用 2. 单元测试的快速反馈 3. 单元测试对定位问题的帮助 4. 单元测试对代码设计的影响 5. 单元测试…

Tomcat实现java博客项目、状态页及常见配置介绍

目录 一、自建博客 1. 项目背景 2. 操作示例 二、状态页 1. 概述 2. server status 信息状态页 3. manager app 项目管理状态页 4. host manger 虚拟主机管理状态页 三、常见配置 1. 端口8005/tcp安全配置管理 2. tomcat端口号 3. 虚拟主机设置 4. Context配置 一…

每日汇评:在美国关键数据公布前,黄金保持“逢低买入”的交易模式

金价从周二早间2120美元的三个月高点回落&#xff1b; 由于对中国的担忧&#xff0c;美元试图反弹&#xff0c;尽管美债收益率低迷&#xff1b; 在看涨的每日技术面设置中&#xff0c;黄金价格回落是一个很好的买入机会&#xff1b; 金价正在复制周一亚洲交易时段的修正走势&am…

Linux内核内存管理架构详解

内存管理子系统可能是linux内核中最为复杂的一个子系统&#xff0c;其支持的功能需求众多&#xff0c;如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等&#xff0c;而且对性能也有很高的要求。本文从内存管理硬件架构、地址…

VScode+Live Service+Five Service实现php实时调试

VScodeLive ServiceFive Service实现php实时调试 一、VScode插件安装及配置 1.Code Runner settings.json设置&#xff08;打开方式&#xff1a;ctrlp&#xff0c;搜索settings.json&#xff09; 设置php为绝对路径&#xff08;注意路径分隔符为\\或/&#xff09; 2. Live S…

HUAWEI 华为交换机 配置 MAC 防漂移 防MAC伪造示例

组网需求 某企业网络中&#xff0c;用户需要访问企业的服务器。如果某些非法用户从其他接口假冒服务器的MAC 地址发送报文&#xff0c;则服务器的 MAC 地址将在其他接口学习到。这样用户发往服务器的报文就会发往非法用户&#xff0c;不仅会导致用户与服务器不能正常通信&…

B端设计:如何让UI组件库成为助力,而不是阻力。

Hi&#xff0c;我是大千UI工场&#xff0c;网上的UI组件库琳琅满目&#xff0c;比如elementUI、antdesign、iview等等&#xff0c;甚至很多前端框架&#xff0c;也出了很多UI组件&#xff0c;如若依、Layui、bootstrap等等&#xff0c;作为UI设计师该如何面对他们呢。 一、UI组…

深度学习模型部署(番外3)神经网络不同层的量化方法

神经网络层量化 批归一化层Batch Normalization(BN层) 关于归一化的原理可以看之前的这篇blog&#xff1a;BatchNorm原理与应用 批归一化在推理过程中会被融合到上一层或者下一层中&#xff0c;这种处理方式被称为批归一化折叠。这样可以减少量化&#xff0c;也可以减少属于的…

将ppt里的视频导出来

将ppt的后缀从pptx改为zip 找到【media】里面有存放图片和音频以及视频&#xff0c;看文件名后缀可以找到&#xff0c;mp4的即为视频&#xff0c;直接复制粘贴到桌面即可。 关闭压缩软件把ppt后缀改回&#xff0c;不影响ppt正常使用。

Android Studio开发(一) 构建项目

1、项目创建测试 1.1 前言 Android Studio 是由 Google 推出的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门用于开发 Android 应用程序。 基于 IntelliJ IDEA: Android Studio 是基于 JetBrains 的 IntelliJ IDEA 开发的&#xff0c;提供了丰富的功能和插件…

大数据开发-Hadoop分布式集群搭建

大数据开发-Hadoop分布式集群搭建 文章目录 大数据开发-Hadoop分布式集群搭建环境准备Hadoop配置启动Hadoop集群Hadoop客户端节点Hadoop客户端节点 环境准备 JDK1.8Hadoop3.X三台服务器 主节点需要启动namenode、secondary namenode、resource manager三个进程 从节点需要启动…