mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 22:40:54 -04:00
dubai: input touch support fod
support fod Change-Id: Idcf036159065de4c67388ce0df422ca84e359845 Signed-off-by: dengwei1 <dengwei1@motorola.com> Reviewed-on: https://gerrit.mot.com/2139348 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Yeqing Wang <wangyq13@motorola.com> Reviewed-by: Wang Wang <wangwang1@lenovo.com> Submit-Approved: Jira Key
This commit is contained in:
parent
0678779d3b
commit
099f74a3fd
6 changed files with 675 additions and 2 deletions
|
|
@ -25,6 +25,10 @@ ifeq ($(findstring factory, $(TARGET_PRODUCT)), factory)
|
|||
KBUILD_OPTIONS += CONFIG_TARGET_BUILD_FACROTY=y
|
||||
endif
|
||||
|
||||
ifeq ($(TOUCHSCREEN_FOD),true)
|
||||
KBUILD_OPTIONS += CONFIG_GTP_FOD=y
|
||||
endif
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := goodix_brl_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ goodix_brl_mmi-objs := \
|
|||
goodix_cfg_bin.o \
|
||||
goodix_ts_utils.o \
|
||||
goodix_brl_fwupdate.o \
|
||||
goodix_ts_gesture.o \
|
||||
goodix_ts_inspect.o \
|
||||
goodix_ts_tools.o
|
||||
|
||||
|
|
@ -28,6 +27,13 @@ ifneq ($(filter m y,$(CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI)),)
|
|||
EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_GOODIX_BRL_SPI
|
||||
endif
|
||||
|
||||
ifneq ($(filter m y,$(CONFIG_GTP_FOD)),)
|
||||
EXTRA_CFLAGS += -DCONFIG_GTP_FOD
|
||||
goodix_brl_mmi-objs += goodix_ts_gesture_fod.o
|
||||
else
|
||||
goodix_brl_mmi-objs += goodix_ts_gesture.o
|
||||
endif
|
||||
|
||||
ifneq ($(filter m y,$(CONFIG_GTP_LIMIT_USE_SUPPLIER)),)
|
||||
EXTRA_CFLAGS += -DCONFIG_GTP_LIMIT_USE_SUPPLIER
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1182,6 +1182,10 @@ static int brl_event_handler(struct goodix_ts_core *cd,
|
|||
if (event_status & GOODIX_GESTURE_EVENT) {
|
||||
ts_event->event_type = EVENT_GESTURE;
|
||||
ts_event->gesture_type = pre_buf[4];
|
||||
#ifdef CONFIG_GTP_FOD
|
||||
memcpy(ts_event->gesture_data, &pre_buf[8],
|
||||
GOODIX_GESTURE_DATA_LEN);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1601,6 +1601,10 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data)
|
|||
#endif
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, KEY_POWER);
|
||||
#ifdef CONFIG_GTP_FOD
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TRIGGER_HAPPY1);
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TRIGGER_HAPPY2);
|
||||
#endif
|
||||
|
||||
r = input_register_device(input_dev);
|
||||
if (r < 0) {
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@
|
|||
#define GOODIX_MAX_PEN_KEY 2
|
||||
#define GOODIX_PEN_MAX_TILT 90
|
||||
#define GOODIX_CFG_MAX_SIZE 4096
|
||||
#define GOODIX_FW_MAX_SIEZE (300 * 1024)
|
||||
#define GOODIX_MAX_STR_LABLE_LEN 64
|
||||
#define GOODIX_MAX_FRAMEDATA_LEN 1700
|
||||
#define GOODIX_GESTURE_DATA_LEN 16
|
||||
|
||||
#define GOODIX_NORMAL_RESET_DELAY_MS 100
|
||||
#define GOODIX_HOLD_CPU_RESET_DELAY_MS 5
|
||||
|
|
@ -54,6 +56,12 @@
|
|||
#define STYLUS_CLK_SRC_GPIO "stylus_clk_gpio"
|
||||
#define STYLUS_CLK_SRC_PMIC "stylus_clk_pmic"
|
||||
|
||||
enum GOODIX_GESTURE_TYP {
|
||||
GESTURE_SINGLE_TAP = (1 << 0),
|
||||
GESTURE_DOUBLE_TAP = (1 << 1),
|
||||
GESTURE_FOD_PRESS = (1 << 2)
|
||||
};
|
||||
|
||||
enum CORD_PROB_STA {
|
||||
CORE_MODULE_UNPROBED = 0,
|
||||
CORE_MODULE_PROB_SUCCESS = 1,
|
||||
|
|
@ -389,6 +397,9 @@ struct goodix_ts_event {
|
|||
u8 gesture_type;
|
||||
struct goodix_touch_data touch_data;
|
||||
struct goodix_pen_data pen_data;
|
||||
#ifdef CONFIG_GTP_FOD
|
||||
u8 gesture_data[GOODIX_GESTURE_DATA_LEN];
|
||||
#endif
|
||||
};
|
||||
|
||||
enum goodix_ic_bus_type {
|
||||
|
|
@ -473,7 +484,6 @@ struct goodix_ts_core {
|
|||
struct goodix_ic_config *ic_configs[GOODIX_MAX_CONFIG_GROUP];
|
||||
struct regulator *avdd;
|
||||
struct regulator *iovdd;
|
||||
|
||||
struct pinctrl *pinctrl;
|
||||
struct pinctrl_state *pin_sta_active;
|
||||
struct pinctrl_state *pin_sta_suspend;
|
||||
|
|
@ -513,6 +523,9 @@ struct goodix_ts_core {
|
|||
int gesture_enabled;
|
||||
const char *supplier;
|
||||
bool need_update_cfg;
|
||||
#ifdef CONFIG_GTP_FOD
|
||||
unsigned char gesture_type;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* external module structures */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* Goodix Gesture Module
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Goodix, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be a reference
|
||||
* to you, when you are integrating the GOODiX's CTP IC into your system,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include "goodix_ts_core.h"
|
||||
#include "goodix_ts_mmi.h"
|
||||
|
||||
|
||||
|
||||
#define GOODIX_GESTURE_DOUBLE_TAP 0xCC
|
||||
#define GOODIX_GESTURE_SINGLE_TAP 0x4C
|
||||
#define GOODIX_GESTURE_FOD_DOWN 0x46
|
||||
#define GOODIX_GESTURE_FOD_UP 0x55
|
||||
/*
|
||||
* struct gesture_module - gesture module data
|
||||
* @registered: module register state
|
||||
* @sysfs_node_created: sysfs node state
|
||||
* @gesture_type: valid gesture type, each bit represent one gesture type
|
||||
* @gesture_data: store latest gesture code get from irq event
|
||||
* @gesture_ts_cmd: gesture command data
|
||||
*/
|
||||
struct gesture_module {
|
||||
atomic_t registered;
|
||||
rwlock_t rwlock;
|
||||
struct goodix_ts_core *ts_core;
|
||||
u8 gesture_type;
|
||||
struct goodix_ext_module module;
|
||||
};
|
||||
|
||||
static struct gesture_module *gsx_gesture; /*allocated in gesture init module*/
|
||||
static bool module_initialized;
|
||||
int goodix_gesture_enable(int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!module_initialized)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
if (atomic_read(&gsx_gesture->registered))
|
||||
ts_info("gesture module has been already registered");
|
||||
else
|
||||
ret = goodix_register_ext_module_no_wait(&gsx_gesture->module);
|
||||
atomic_set(&gsx_gesture->registered, 1);
|
||||
} else {
|
||||
if (!atomic_read(&gsx_gesture->registered))
|
||||
ts_info("gesture module has been already unregistered");
|
||||
else
|
||||
ret = goodix_unregister_ext_module(&gsx_gesture->module);
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
static ssize_t gsx_double_type_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
unsigned char type = gsx->ts_core->gesture_type;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(type & GESTURE_DOUBLE_TAP) ? "enable" : "disable");
|
||||
}
|
||||
|
||||
static ssize_t gsx_double_type_store(struct goodix_ext_module *module,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf[0] == '1') {
|
||||
ts_info("enable double tap");
|
||||
gsx->ts_core->gesture_type |= GESTURE_DOUBLE_TAP;
|
||||
} else if (buf[0] == '0') {
|
||||
ts_info("disable double tap");
|
||||
gsx->ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP;
|
||||
} else
|
||||
ts_err("invalid cmd[%d]", buf[0]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t gsx_single_type_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
unsigned char type = gsx->ts_core->gesture_type;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(type & GESTURE_SINGLE_TAP) ? "enable" : "disable");
|
||||
}
|
||||
|
||||
static ssize_t gsx_single_type_store(struct goodix_ext_module *module,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf[0] == '1') {
|
||||
ts_info("enable single tap");
|
||||
gsx->ts_core->gesture_type |= GESTURE_SINGLE_TAP;
|
||||
} else if (buf[0] == '0') {
|
||||
ts_info("disable single tap");
|
||||
gsx->ts_core->gesture_type &= ~GESTURE_SINGLE_TAP;
|
||||
} else
|
||||
ts_err("invalid cmd[%d]", buf[0]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t gsx_fod_type_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
unsigned char type = gsx->ts_core->gesture_type;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
(type & GESTURE_FOD_PRESS) ? "enable" : "disable");
|
||||
}
|
||||
|
||||
static ssize_t gsx_fod_type_store(struct goodix_ext_module *module,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
|
||||
if (!gsx)
|
||||
return -EIO;
|
||||
|
||||
if (atomic_read(&gsx->registered) == 0) {
|
||||
ts_err("gesture module is not registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buf[0] == '1') {
|
||||
ts_info("enable fod");
|
||||
gsx->ts_core->gesture_type |= GESTURE_FOD_PRESS;
|
||||
} else if (buf[0] == '0') {
|
||||
ts_info("disable fod");
|
||||
gsx->ts_core->gesture_type &= ~GESTURE_FOD_PRESS;
|
||||
} else
|
||||
ts_err("invalid cmd[%d]", buf[0]);
|
||||
|
||||
return count;
|
||||
}
|
||||
#if 0
|
||||
/**
|
||||
* gsx_gesture_type_show - show valid gesture type
|
||||
*
|
||||
* @module: pointer to goodix_ext_module struct
|
||||
* @buf: pointer to output buffer
|
||||
* Returns >=0 - succeed,< 0 - failed
|
||||
*/
|
||||
static ssize_t gsx_gesture_type_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
int count = 0, i, ret = 0;
|
||||
unsigned char *type;
|
||||
|
||||
type = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!type)
|
||||
return -ENOMEM;
|
||||
read_lock(&gsx_gesture->rwlock);
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (QUERYBIT(gsx_gesture->gesture_type, i)) {
|
||||
count += scnprintf(type + count,
|
||||
PAGE_SIZE, "%02x,", i);
|
||||
}
|
||||
}
|
||||
if (count > 0)
|
||||
ret = scnprintf(buf, PAGE_SIZE, "%s\n", type);
|
||||
read_unlock(&gsx_gesture->rwlock);
|
||||
|
||||
kfree(type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsx_gesture_type_store - set vailed gesture
|
||||
*
|
||||
* @module: pointer to goodix_ext_module struct
|
||||
* @buf: pointer to valid gesture type
|
||||
* @count: length of buf
|
||||
* Returns >0 - valid gestures, < 0 - failed
|
||||
*/
|
||||
static ssize_t gsx_gesture_type_store(struct goodix_ext_module *module,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (count <= 0 || count > 256 || buf == NULL) {
|
||||
ts_err("Parameter error");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
write_lock(&gsx_gesture->rwlock);
|
||||
memset(gsx_gesture->gesture_type, 0, GSX_GESTURE_TYPE_LEN);
|
||||
for (i = 0; i < count; i++)
|
||||
gsx_gesture->gesture_type[buf[i]/8] |= (0x1 << buf[i]%8);
|
||||
write_unlock(&gsx_gesture->rwlock);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
static ssize_t gsx_gesture_enable_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
atomic_read(&gsx_gesture->registered));
|
||||
}
|
||||
|
||||
static ssize_t gsx_gesture_enable_store(struct goodix_ext_module *module,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
bool val;
|
||||
int ret;
|
||||
|
||||
ret = strtobool(buf, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (val) {
|
||||
ret = goodix_gesture_enable(1);
|
||||
return ret ? ret : count;
|
||||
} else {
|
||||
ret = goodix_gesture_enable(0);
|
||||
return ret ? ret : count;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t gsx_gesture_data_show(struct goodix_ext_module *module,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t count;
|
||||
|
||||
read_lock(&gsx_gesture->rwlock);
|
||||
count = scnprintf(buf, PAGE_SIZE, "gesture type code:0x%x\n",
|
||||
gsx_gesture->gesture_type);
|
||||
read_unlock(&gsx_gesture->rwlock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
const struct goodix_ext_attribute gesture_attrs[] = {
|
||||
#if 0
|
||||
__EXTMOD_ATTR(type, 0666, gsx_gesture_type_show,
|
||||
gsx_gesture_type_store),
|
||||
#endif
|
||||
__EXTMOD_ATTR(enable, 0666, gsx_gesture_enable_show,
|
||||
gsx_gesture_enable_store),
|
||||
__EXTMOD_ATTR(data, 0444, gsx_gesture_data_show, NULL),
|
||||
__EXTMOD_ATTR(double_en, 0666,
|
||||
gsx_double_type_show, gsx_double_type_store),
|
||||
__EXTMOD_ATTR(single_en, 0666,
|
||||
gsx_single_type_show, gsx_single_type_store),
|
||||
__EXTMOD_ATTR(fod_en, 0666,
|
||||
gsx_fod_type_show, gsx_fod_type_store)
|
||||
};
|
||||
|
||||
static int gsx_gesture_init(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
struct gesture_module *gsx = module->priv_data;
|
||||
|
||||
if (!cd || !cd->hw_ops->gesture) {
|
||||
ts_err("gesture unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts_info("gesture switch: ON");
|
||||
ts_debug("enable all gesture type");
|
||||
|
||||
gsx->ts_core = cd;
|
||||
/*enable all gesture wakeup by default */
|
||||
gsx->ts_core->gesture_type = GESTURE_SINGLE_TAP |GESTURE_FOD_PRESS;
|
||||
|
||||
atomic_set(&gsx_gesture->registered, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsx_gesture_exit(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
if (!cd || !cd->hw_ops->gesture) {
|
||||
ts_err("gesture unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts_info("gesture switch: OFF");
|
||||
ts_debug("disable all gesture type");
|
||||
cd->gesture_type = 0;
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsx_gesture_ist - Gesture Irq handle
|
||||
* This functions is excuted when interrupt happended and
|
||||
* ic in doze mode.
|
||||
*
|
||||
* @cd: pointer to touch core data
|
||||
* @module: pointer to goodix_ext_module struct
|
||||
* return: 0 goon execute, EVT_CANCEL_IRQEVT stop execute
|
||||
*/
|
||||
static int gsx_gesture_ist(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
|
||||
struct goodix_ts_event gs_event = {0};
|
||||
int fodx, fody, overlay_area;
|
||||
int ret;
|
||||
#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI)
|
||||
struct gesture_event_data mmi_event;
|
||||
static unsigned long start = 0;
|
||||
static bool fod_down = false;
|
||||
#endif
|
||||
if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0)
|
||||
return EVT_CONTINUE;
|
||||
ret = hw_ops->event_handler(cd, &gs_event);
|
||||
if (ret) {
|
||||
ts_err("failed get gesture data");
|
||||
goto re_send_ges_cmd;
|
||||
}
|
||||
|
||||
if (!(gs_event.event_type & EVENT_GESTURE)) {
|
||||
ts_err("invalid event type: 0x%x",
|
||||
gs_event.event_type);
|
||||
goto re_send_ges_cmd;
|
||||
}
|
||||
ts_debug("got gesture type 0x%x", gs_event.gesture_type);
|
||||
#if defined(CONFIG_INPUT_TOUCHSCREEN_MMI)
|
||||
mmi_event.evcode =0;
|
||||
if ( cd->imports && cd->imports->report_gesture) {
|
||||
if(cd->gesture_type & GESTURE_SINGLE_TAP && gs_event.gesture_type == GOODIX_GESTURE_SINGLE_TAP) {
|
||||
ts_info("get SINGLE-TAP gesture");
|
||||
mmi_event.evcode =1;
|
||||
fod_down = false;
|
||||
/* call class method */
|
||||
ret = cd->imports->report_gesture(&mmi_event);
|
||||
if (!ret)
|
||||
PM_WAKEUP_EVENT(cd->gesture_wakelock, 3000);
|
||||
goto gesture_ist_exit;
|
||||
} else if(cd->gesture_type & GESTURE_FOD_PRESS && gs_event.gesture_type == GOODIX_GESTURE_FOD_DOWN ){
|
||||
int fod_down_interval = (int)jiffies_to_msecs(jiffies-start);
|
||||
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
|
||||
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
|
||||
overlay_area = gs_event.gesture_data[4];
|
||||
//goodix firmware do not send coordinate, we need hardcode a vaild coordinate
|
||||
mmi_event.evcode = 2;
|
||||
mmi_event.evdata.x= 540;
|
||||
mmi_event.evdata.y= 2164;
|
||||
ts_info("get FOD-DOWN gesture");
|
||||
if(fod_down_interval < 5000) {
|
||||
if(fod_down == true) {
|
||||
ts_debug("filter same fod down within 5s");
|
||||
goto gesture_ist_exit;
|
||||
}
|
||||
} else {
|
||||
fod_down= false;
|
||||
}
|
||||
ret = cd->imports->report_gesture(&mmi_event);
|
||||
if (!ret)
|
||||
PM_WAKEUP_EVENT(cd->gesture_wakelock, 3000);
|
||||
|
||||
input_report_key(cd->input_dev, BTN_TRIGGER_HAPPY1, 1);
|
||||
input_sync(cd->input_dev);
|
||||
input_report_key(cd->input_dev, BTN_TRIGGER_HAPPY1, 0);
|
||||
input_sync(cd->input_dev);
|
||||
fod_down = true;
|
||||
start=jiffies;
|
||||
goto gesture_ist_exit;
|
||||
}else if(cd->gesture_type & GESTURE_FOD_PRESS && gs_event.gesture_type == GOODIX_GESTURE_FOD_UP) {
|
||||
ts_info("get FOD-UP gesture");
|
||||
mmi_event.evcode = 3;
|
||||
input_report_key(cd->input_dev, BTN_TRIGGER_HAPPY2, 1);
|
||||
input_sync(cd->input_dev);
|
||||
input_report_key(cd->input_dev, BTN_TRIGGER_HAPPY2, 0);
|
||||
input_sync(cd->input_dev);
|
||||
fod_down = false;
|
||||
}
|
||||
} else {
|
||||
ts_debug("not support gesture type[%02X] to wakeup, suspended =%d", gs_event.gesture_type, atomic_read(&cd->suspended));
|
||||
fod_down = false;
|
||||
}
|
||||
#else
|
||||
switch (gs_event.gesture_type) {
|
||||
case GOODIX_GESTURE_SINGLE_TAP:
|
||||
if (cd->gesture_type & GESTURE_SINGLE_TAP) {
|
||||
ts_info("get SINGLE-TAP gesture");
|
||||
input_report_key(cd->input_dev, KEY_POWER, 1);
|
||||
input_sync(cd->input_dev);
|
||||
input_report_key(cd->input_dev, KEY_POWER, 0);
|
||||
input_sync(cd->input_dev);
|
||||
} else {
|
||||
ts_debug("not enable SINGLE-TAP");
|
||||
}
|
||||
break;
|
||||
case GOODIX_GESTURE_DOUBLE_TAP:
|
||||
if (cd->gesture_type & GESTURE_DOUBLE_TAP) {
|
||||
ts_info("get DOUBLE-TAP gesture");
|
||||
input_report_key(cd->input_dev, KEY_WAKEUP, 1);
|
||||
input_sync(cd->input_dev);
|
||||
input_report_key(cd->input_dev, KEY_WAKEUP, 0);
|
||||
input_sync(cd->input_dev);
|
||||
} else {
|
||||
ts_debug("not enable DOUBLE-TAP");
|
||||
}
|
||||
break;
|
||||
case GOODIX_GESTURE_FOD_DOWN:
|
||||
if (cd->gesture_type & GESTURE_FOD_PRESS) {
|
||||
ts_info("get FOD-DOWN gesture");
|
||||
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
|
||||
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
|
||||
overlay_area = gs_event.gesture_data[4];
|
||||
ts_info("fodx:%d fody:%d overlay_area:%d", fodx, fody, overlay_area);
|
||||
input_report_key(cd->input_dev, BTN_TOUCH, 1);
|
||||
input_mt_slot(cd->input_dev, 0);
|
||||
input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, 1);
|
||||
input_report_abs(cd->input_dev, ABS_MT_POSITION_X, fodx);
|
||||
input_report_abs(cd->input_dev, ABS_MT_POSITION_Y, fody);
|
||||
input_report_abs(cd->input_dev, ABS_MT_WIDTH_MAJOR, overlay_area);
|
||||
input_sync(cd->input_dev);
|
||||
} else {
|
||||
ts_debug("not enable FOD-DOWN");
|
||||
}
|
||||
break;
|
||||
case GOODIX_GESTURE_FOD_UP:
|
||||
if (cd->gesture_type & GESTURE_FOD_PRESS) {
|
||||
ts_info("get FOD-UP gesture");
|
||||
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
|
||||
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
|
||||
overlay_area = gs_event.gesture_data[4];
|
||||
input_report_key(cd->input_dev, BTN_TOUCH, 0);
|
||||
input_mt_slot(cd->input_dev, 0);
|
||||
input_mt_report_slot_state(cd->input_dev,
|
||||
MT_TOOL_FINGER, 0);
|
||||
input_sync(cd->input_dev);
|
||||
} else {
|
||||
ts_debug("not enable FOD-UP");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ts_err("not support gesture type[%02X]", gs_event.gesture_type);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
re_send_ges_cmd:
|
||||
if (hw_ops->gesture(cd, 0))
|
||||
ts_info("warning: failed re_send gesture cmd");
|
||||
gesture_ist_exit:
|
||||
if (!cd->tools_ctrl_sync)
|
||||
hw_ops->after_event_handler(cd);
|
||||
return EVT_CANCEL_IRQEVT;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsx_gesture_before_suspend - execute gesture suspend routine
|
||||
* This functions is excuted to set ic into doze mode
|
||||
*
|
||||
* @cd: pointer to touch core data
|
||||
* @module: pointer to goodix_ext_module struct
|
||||
* return: 0 goon execute, EVT_IRQCANCLED stop execute
|
||||
*/
|
||||
static int gsx_gesture_before_suspend(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
int ret;
|
||||
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
|
||||
|
||||
if (cd->gesture_type == 0)
|
||||
return EVT_CONTINUE;
|
||||
|
||||
ret = hw_ops->gesture(cd, 0);
|
||||
if (ret)
|
||||
ts_err("failed enter gesture mode");
|
||||
else
|
||||
ts_info("enter gesture mode, type[0x%02X]", cd->gesture_type);
|
||||
|
||||
hw_ops->irq_enable(cd, true);
|
||||
enable_irq_wake(cd->irq);
|
||||
|
||||
return EVT_CANCEL_SUSPEND;
|
||||
}
|
||||
|
||||
static int gsx_gesture_before_resume(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
|
||||
|
||||
if (cd->gesture_type == 0)
|
||||
return EVT_CONTINUE;
|
||||
hw_ops->irq_enable(cd, false);
|
||||
disable_irq_wake(cd->irq);
|
||||
hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
|
||||
|
||||
return EVT_CANCEL_RESUME;
|
||||
}
|
||||
|
||||
static struct goodix_ext_module_funcs gsx_gesture_funcs = {
|
||||
.irq_event = gsx_gesture_ist,
|
||||
.init = gsx_gesture_init,
|
||||
.exit = gsx_gesture_exit,
|
||||
.before_suspend = gsx_gesture_before_suspend,
|
||||
.before_resume = gsx_gesture_before_resume,
|
||||
};
|
||||
|
||||
int gesture_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct kobject *def_kobj = goodix_get_default_kobj();
|
||||
struct kobj_type *def_kobj_type = goodix_get_default_ktype();
|
||||
|
||||
gsx_gesture = kzalloc(sizeof(struct gesture_module), GFP_KERNEL);
|
||||
if (!gsx_gesture)
|
||||
return -ENOMEM;
|
||||
|
||||
gsx_gesture->module.funcs = &gsx_gesture_funcs;
|
||||
gsx_gesture->module.priority = EXTMOD_PRIO_GESTURE;
|
||||
gsx_gesture->module.name = "Goodix_gsx_gesture";
|
||||
gsx_gesture->module.priv_data = gsx_gesture;
|
||||
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
rwlock_init(&gsx_gesture->rwlock);
|
||||
|
||||
/* gesture sysfs init */
|
||||
ret = kobject_init_and_add(&gsx_gesture->module.kobj,
|
||||
def_kobj_type, def_kobj, "gesture");
|
||||
if (ret) {
|
||||
ts_err("failed create gesture sysfs node!");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++)
|
||||
ret = sysfs_create_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
if (ret) {
|
||||
ts_err("failed create gst sysfs files");
|
||||
while (--i >= 0)
|
||||
sysfs_remove_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
|
||||
kobject_put(&gsx_gesture->module.kobj);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
module_initialized = true;
|
||||
|
||||
goodix_gesture_enable(1);
|
||||
|
||||
ts_info("gesture module init success");
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ts_err("gesture module init failed!");
|
||||
kfree(gsx_gesture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gesture_module_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
ts_info("gesture module exit");
|
||||
if (!module_initialized)
|
||||
return;
|
||||
|
||||
goodix_gesture_enable(0);
|
||||
|
||||
/* deinit sysfs */
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
|
||||
sysfs_remove_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
|
||||
kobject_put(&gsx_gesture->module.kobj);
|
||||
kfree(gsx_gesture);
|
||||
module_initialized = false;
|
||||
}
|
||||
Loading…
Reference in a new issue