summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWendly Li <wendlyli@google.com>2022-02-08 02:12:25 +0000
committerWendly Li <wendlyli@google.com>2022-02-11 11:06:50 +0000
commite286e1f6629672757861e310ec65f10181be865e (patch)
tree1d80f2ea7858f0676b468269634eea76b6e13ea9
parent31f49bb87d1d5e7d7085ac5bb5460914cc675086 (diff)
downloadgoodix_touch-e286e1f6629672757861e310ec65f10181be865e.tar.gz
Add APIs for factory
Bug: 214118886 Bug: 216386146 Bug: 216578458 Test: check sysfs works properly Change-Id: I51f83d192a9068ec2cdb93300a5834b839839aa1 Signed-off-by: Wendly Li <wendlyli@google.com>
-rw-r--r--Kbuild3
-rw-r--r--goodix_brl_hw.c1
-rw-r--r--goodix_ts_core.c108
-rw-r--r--goodix_ts_core.h3
-rw-r--r--touch_apis.c352
-rw-r--r--touch_apis.h52
6 files changed, 502 insertions, 17 deletions
diff --git a/Kbuild b/Kbuild
index af54d14..c8e9396 100644
--- a/Kbuild
+++ b/Kbuild
@@ -10,4 +10,5 @@ goodix_brl_touch-objs += \
goodix_ts_inspect.o \
goodix_ts_tools.o \
goodix_ts_utils.o \
- goodix_ts_proc.o
+ goodix_ts_proc.o \
+ touch_apis.o
diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c
index 19a2c1b..6e51680 100644
--- a/goodix_brl_hw.c
+++ b/goodix_brl_hw.c
@@ -1425,6 +1425,7 @@ static struct goodix_ts_hw_ops brl_hw_ops = {
.event_handler = brl_event_handler,
.after_event_handler = brl_after_event_handler,
.get_capacitance_data = brl_get_capacitance_data,
+ .ping = brl_dev_confirm,
};
struct goodix_ts_hw_ops *goodix_get_hw_ops(void)
diff --git a/goodix_ts_core.c b/goodix_ts_core.c
index 700dc9c..57bc14a 100644
--- a/goodix_ts_core.c
+++ b/goodix_ts_core.c
@@ -321,20 +321,6 @@ static ssize_t chip_info_show(
return cnt;
}
-/* reset chip */
-static ssize_t goodix_ts_reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct goodix_ts_core *core_data = dev_get_drvdata(dev);
- struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
-
- if (!buf || count <= 0)
- return -EINVAL;
- if (buf[0] != '0')
- hw_ops->reset(core_data, GOODIX_NORMAL_RESET_DELAY_MS);
- return count;
-}
-
/* read config */
static ssize_t read_cfg_show(
struct device *dev, struct device_attribute *attr, char *buf)
@@ -719,7 +705,6 @@ static ssize_t goodix_ts_debug_log_store(struct device *dev,
static DEVICE_ATTR(driver_info, 0440, driver_info_show, NULL);
static DEVICE_ATTR(chip_info, 0440, chip_info_show, NULL);
-static DEVICE_ATTR(reset, 0220, NULL, goodix_ts_reset_store);
static DEVICE_ATTR(send_cfg, 0220, NULL, goodix_ts_send_cfg_store);
static DEVICE_ATTR(read_cfg, 0440, read_cfg_show, NULL);
static DEVICE_ATTR(reg_rw, 0664, goodix_ts_reg_rw_show, goodix_ts_reg_rw_store);
@@ -733,7 +718,6 @@ static DEVICE_ATTR(
static struct attribute *sysfs_attrs[] = {
&dev_attr_driver_info.attr,
&dev_attr_chip_info.attr,
- &dev_attr_reset.attr,
&dev_attr_send_cfg.attr,
&dev_attr_read_cfg.attr,
&dev_attr_reg_rw.attr,
@@ -765,6 +749,78 @@ static void goodix_ts_sysfs_exit(struct goodix_ts_core *core_data)
sysfs_remove_group(&core_data->pdev->dev.kobj, &sysfs_group);
}
+int get_fw_version(struct device *dev, char *buf, size_t buf_size)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = cd->hw_ops->read_version(cd, &cd->fw_version);
+ if (ret) {
+ return ret;
+ }
+
+ snprintf(buf, buf_size, "%02x.%02x.%02x.%02x",
+ cd->fw_version.patch_vid[0], cd->fw_version.patch_vid[1],
+ cd->fw_version.patch_vid[2], cd->fw_version.patch_vid[3]);
+ return ret;
+}
+
+int get_irq_enabled(struct device *dev)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ return atomic_read(&cd->irq_enabled);
+}
+
+int set_irq_enabled(struct device *dev, bool enabled)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ return cd->hw_ops->irq_enable(cd, enabled);
+}
+
+bool is_scan_mode_supported(struct device *dev, enum scan_mode mode)
+{
+ return mode == SCAN_MODE_AUTO ? true : false;
+}
+
+int ping(struct device *dev)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ return cd->hw_ops->ping(cd);
+}
+
+int hardware_reset(struct device *dev)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ return cd->hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
+}
+
+int set_sensing_enabled(struct device *dev, bool enabled)
+{
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ if (enabled) {
+ cd->hw_ops->resume(cd);
+ cd->hw_ops->irq_enable(cd, true);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ ts_info("set sense ON");
+ } else {
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
+ cd->hw_ops->irq_enable(cd, false);
+ cd->hw_ops->suspend(cd);
+ ts_info("set sense OFF");
+ }
+ return 0;
+}
+
+int get_wake_lock_state(struct device *dev)
+{
+ return 1;
+}
+
+int set_wake_lock_state(struct device *dev, bool locked)
+{
+ return locked ? 0 : -EINVAL;
+}
+
/* prosfs create */
static int rawdata_proc_show(struct seq_file *m, void *v)
{
@@ -1995,6 +2051,23 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
goto err_init_sysfs;
}
+ /* create sysfs files for our own APIs */
+ cd->apis_data.get_fw_version = get_fw_version;
+ cd->apis_data.get_irq_enabled = get_irq_enabled;
+ cd->apis_data.set_irq_enabled = set_irq_enabled;
+ cd->apis_data.is_scan_mode_supported = is_scan_mode_supported;
+ cd->apis_data.ping = ping;
+ cd->apis_data.hardware_reset = hardware_reset;
+ cd->apis_data.set_sensing_enabled = set_sensing_enabled;
+ cd->apis_data.get_wake_lock_state = get_wake_lock_state;
+ cd->apis_data.set_wake_lock_state = set_wake_lock_state;
+
+ ret = touch_apis_init(&cd->pdev->dev, &cd->apis_data);
+ if (ret < 0) {
+ ts_err("failed set init apis");
+ goto err_init_apis;
+ }
+
/* create procfs files */
ret = goodix_ts_procfs_init(cd);
if (ret < 0) {
@@ -2042,6 +2115,8 @@ err_init_gesture:
err_init_esd:
goodix_ts_procfs_exit(cd);
err_init_procfs:
+ touch_apis_deinit(&cd->pdev->dev);
+err_init_apis:
goodix_ts_sysfs_exit(cd);
err_init_sysfs:
#if IS_ENABLED(CONFIG_FB)
@@ -2339,6 +2414,7 @@ static int goodix_ts_remove(struct platform_device *pdev)
goodix_ts_input_dev_remove(core_data);
goodix_ts_pen_dev_remove(core_data);
goodix_ts_sysfs_exit(core_data);
+ touch_apis_deinit(&core_data->pdev->dev);
goodix_ts_procfs_exit(core_data);
goodix_ts_power_off(core_data);
}
diff --git a/goodix_ts_core.h b/goodix_ts_core.h
index 92d12a7..f774f0d 100644
--- a/goodix_ts_core.h
+++ b/goodix_ts_core.h
@@ -39,6 +39,7 @@
#include <linux/fb.h>
#include <linux/notifier.h>
#endif
+#include "touch_apis.h"
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
@@ -464,6 +465,7 @@ struct goodix_ts_hw_ops {
int (*after_event_handler)(struct goodix_ts_core *cd);
int (*get_capacitance_data)(
struct goodix_ts_core *cd, struct ts_rawdata_info *info);
+ int (*ping)(struct goodix_ts_core *cd);
};
/*
@@ -499,6 +501,7 @@ struct goodix_ts_core {
struct goodix_ic_info ic_info;
struct goodix_bus_interface *bus;
struct goodix_ts_board_data board_data;
+ struct touch_apis_data apis_data;
struct goodix_ts_hw_ops *hw_ops;
struct input_dev *input_dev;
struct input_dev *pen_dev;
diff --git a/touch_apis.c b/touch_apis.c
new file mode 100644
index 0000000..727bed9
--- /dev/null
+++ b/touch_apis.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sysfs APIs for Google Pixel devices.
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "touch_apis.h"
+
+struct touch_apis_data *apis;
+
+static ssize_t fw_ver_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char fw_ver[0x100];
+ int ret = 0;
+
+ if (apis->get_fw_version != NULL) {
+ ret = apis->get_fw_version(dev, fw_ver, 0x100);
+ if (ret < 0) {
+ ret = snprintf(buf, PAGE_SIZE, "error: %d\n", ret);
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n", fw_ver);
+ }
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t help_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char fw_ver[0x100];
+ int ret = 0;
+ char *help_str = "APIs\n"
+ " fw_ver\n"
+ " help\n"
+ " irq_enabled\n"
+ " list_scan_mode\n"
+ " ping\n"
+ " reset\n"
+ " scan_mode\n"
+ " sensing_enabled\n"
+ " wake_lock\n";
+
+ ret = snprintf(buf, PAGE_SIZE, help_str, fw_ver);
+ return ret;
+}
+
+static ssize_t irq_enabled_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (apis->get_irq_enabled != NULL && apis->set_irq_enabled != NULL) {
+ ret = apis->get_irq_enabled(dev);
+ if (ret < 0) {
+ ret = snprintf(buf, PAGE_SIZE, "error: %d\n", ret);
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ ret ? "enabled" : "disable");
+ }
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t irq_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ bool enabled = false;
+
+ if (buf == NULL || count <= 0)
+ return -EINVAL;
+
+ if (strncmp(buf, "1", 1) == 0) {
+ enabled = true;
+ } else if (strncmp(buf, "0", 1) == 0) {
+ enabled = false;
+ } else {
+ return -EINVAL;
+ }
+
+ if (apis->set_irq_enabled != NULL) {
+ apis->set_irq_enabled(dev, enabled);
+ }
+ return count;
+}
+
+static ssize_t list_scan_mode_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+ enum scan_mode mode = SCAN_MODE_AUTO;
+ int len = 0;
+ static const char *mode_name[SCAN_MODE_MAX] = {
+ "auto mode",
+ "normal active mode",
+ "normal idle mode",
+ "low power active mode",
+ "low power idle mode",
+ };
+
+ if (apis->is_scan_mode_supported != NULL) {
+ len = snprintf(buf, PAGE_SIZE, "result:\n");
+ for (mode = SCAN_MODE_AUTO; mode < SCAN_MODE_MAX; mode++) {
+ ret = apis->is_scan_mode_supported(dev, mode);
+ if (ret) {
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "%d: %s\n", mode, mode_name[mode]);
+ }
+ }
+ ret = len;
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t ping_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (apis->ping != NULL) {
+ ret = apis->ping(dev);
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ ret == 0 ? "ack" : "non ack");
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t reset_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (apis->reset_result > RESET_RESULT_NOT_SUPPORT) {
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ apis->reset_result == RESET_RESULT_SUCCESS ? "success"
+ : apis->reset_result == RESET_RESULT_FAIL
+ ? "fail"
+ : "haven't reset");
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret = 0;
+
+ if (buf == NULL || count <= 0)
+ return -EINVAL;
+
+ if (strncmp(buf, "1", 1) == 0) {
+ if (apis->hardware_reset != NULL) {
+ ret = apis->hardware_reset(dev);
+ apis->reset_result = ret == 0 ? RESET_RESULT_SUCCESS
+ : RESET_RESULT_FAIL;
+ } else {
+ apis->reset_result = RESET_RESULT_NOT_SUPPORT;
+ }
+ } else if (strncmp(buf, "2", 0) == 0) {
+ if (apis->software_reset != NULL) {
+ ret = apis->software_reset(dev);
+ apis->reset_result = ret == 0 ? RESET_RESULT_SUCCESS
+ : RESET_RESULT_FAIL;
+ } else {
+ apis->reset_result = RESET_RESULT_NOT_SUPPORT;
+ }
+ } else {
+ apis->reset_result = RESET_RESULT_NOT_SUPPORT;
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t scan_mode_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "result: %d\n", apis->scan_mode);
+}
+
+static ssize_t scan_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ enum scan_mode mode = 0;
+
+ if (buf == NULL || count < SCAN_MODE_AUTO)
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, (int*)&mode)) {
+ return -EINVAL;
+ }
+
+ if (apis->is_scan_mode_supported == NULL ||
+ !apis->is_scan_mode_supported(dev, mode)) {
+ return -EINVAL;
+ }
+
+ if (apis->set_scan_mode != NULL) {
+ apis->set_scan_mode(dev, mode);
+ }
+ return count;
+}
+
+static ssize_t sensing_enabled_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (apis->ping != NULL) {
+ ret = apis->ping(dev);
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ ret == 0 ? "enabled" : "disabled");
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t sensing_enabled_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ bool enabled = false;
+
+ if (buf == NULL || count <= 0)
+ return -EINVAL;
+
+ if (strncmp(buf, "1", 1) == 0) {
+ enabled = true;
+ } else if (strncmp(buf, "0", 1) == 0) {
+ enabled = false;
+ } else {
+ return -EINVAL;
+ }
+
+ if (apis->set_sensing_enabled != NULL) {
+ apis->set_sensing_enabled(dev, enabled);
+ }
+ return count;
+}
+
+static ssize_t wake_lock_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret = 0;
+
+ if (apis->get_wake_lock_state != NULL) {
+ ret = apis->get_wake_lock_state(dev);
+ if (ret < 0) {
+ ret = snprintf(buf, PAGE_SIZE, "error: %d\n", ret);
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "result: %s\n",
+ ret == WAKE_LOCK_STATE_LOCKED ? "locked"
+ : "unlocked");
+ }
+ } else {
+ ret = snprintf(buf, PAGE_SIZE, "error: not support\n");
+ }
+ return ret;
+}
+
+static ssize_t wake_lock_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ bool locked = false;
+ int ret = 0;
+
+ if (buf == NULL || count <= 0)
+ return -EINVAL;
+
+ if (strncmp(buf, "1", 1) == 0) {
+ locked = WAKE_LOCK_STATE_LOCKED;
+ } else if (strncmp(buf, "0", 1) == 0) {
+ locked = WAKE_LOCK_STATE_UNLOCKED;
+ } else {
+ return -EINVAL;
+ }
+
+ if (apis->set_wake_lock_state != NULL) {
+ ret = apis->set_wake_lock_state(dev, locked);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+ return count;
+}
+
+static DEVICE_ATTR_RO(fw_ver);
+static DEVICE_ATTR_RO(help);
+static DEVICE_ATTR_RW(irq_enabled);
+static DEVICE_ATTR_RO(list_scan_mode);
+static DEVICE_ATTR_RO(ping);
+static DEVICE_ATTR_RW(reset);
+static DEVICE_ATTR_RW(scan_mode);
+static DEVICE_ATTR_RW(sensing_enabled);
+static DEVICE_ATTR_RW(wake_lock);
+
+static struct attribute *sysfs_attrs[] = {
+ &dev_attr_fw_ver.attr,
+ &dev_attr_help.attr,
+ &dev_attr_irq_enabled.attr,
+ &dev_attr_list_scan_mode.attr,
+ &dev_attr_ping.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_scan_mode.attr,
+ &dev_attr_sensing_enabled.attr,
+ &dev_attr_wake_lock.attr,
+ NULL,
+};
+
+static const struct attribute_group sysfs_group = {
+ .attrs = sysfs_attrs,
+};
+
+int touch_apis_init(struct device *dev, struct touch_apis_data *data)
+{
+ int ret = 0;
+
+ apis = data;
+ apis->scan_mode = SCAN_MODE_AUTO;
+ apis->reset_result = RESET_RESULT_NOT_READY;
+
+ ret = sysfs_create_group(&dev->kobj, &sysfs_group);
+ if (ret) {
+ dev_err(dev, "failed create core sysfs group");
+ return ret;
+ }
+ return ret;
+}
+
+void touch_apis_deinit(struct device *dev)
+{
+ sysfs_remove_group(&dev->kobj, &sysfs_group);
+ if (apis != NULL) {
+ apis = NULL;
+ }
+}
diff --git a/touch_apis.h b/touch_apis.h
new file mode 100644
index 0000000..db4a1f9
--- /dev/null
+++ b/touch_apis.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Sysfs APIs for Google Pixel devices.
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+#ifndef _TOUCH_APIS_H_
+#define _TOUCH_APIS_H_
+
+enum scan_mode {
+ SCAN_MODE_AUTO = 0,
+ SCAN_MODE_NORMAL_ACTIVE,
+ SCAN_MODE_NORMAL_IDLE,
+ SCAN_MODE_LOW_POWER_ACTIVE,
+ SCAN_MODE_LOW_POWER_IDLE,
+ SCAN_MODE_MAX,
+};
+
+enum wake_lock_state {
+ WAKE_LOCK_STATE_UNLOCKED = 0,
+ WAKE_LOCK_STATE_LOCKED,
+};
+
+enum reset_result {
+ RESET_RESULT_SUCCESS = 0,
+ RESET_RESULT_FAIL = -1,
+ RESET_RESULT_NOT_READY = -2,
+ RESET_RESULT_NOT_SUPPORT = -3,
+};
+
+struct touch_apis_data {
+ int reset_result;
+ int scan_mode;
+
+ int (*get_fw_version)(struct device *dev, char *buf, size_t buf_size);
+ int (*get_irq_enabled)(struct device *dev);
+ int (*set_irq_enabled)(struct device *dev, bool enabled);
+ bool (*is_scan_mode_supported)(struct device *dev, enum scan_mode mode);
+ int (*ping)(struct device *dev);
+ int (*hardware_reset)(struct device *dev);
+ int (*software_reset)(struct device *dev);
+ int (*set_scan_mode)(struct device *dev, enum scan_mode mode);
+ int (*set_sensing_enabled)(struct device *dev, bool enabled);
+ int (*get_wake_lock_state)(struct device *dev);
+ int (*set_wake_lock_state)(struct device *dev, bool locked);
+};
+
+extern int touch_apis_init(struct device *dev, struct touch_apis_data *data);
+extern void touch_apis_deinit(struct device *dev);
+
+#endif