diff options
author | Wendly Li <wendlyli@google.com> | 2022-02-08 02:12:25 +0000 |
---|---|---|
committer | Wendly Li <wendlyli@google.com> | 2022-02-11 11:06:50 +0000 |
commit | e286e1f6629672757861e310ec65f10181be865e (patch) | |
tree | 1d80f2ea7858f0676b468269634eea76b6e13ea9 | |
parent | 31f49bb87d1d5e7d7085ac5bb5460914cc675086 (diff) | |
download | goodix_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-- | Kbuild | 3 | ||||
-rw-r--r-- | goodix_brl_hw.c | 1 | ||||
-rw-r--r-- | goodix_ts_core.c | 108 | ||||
-rw-r--r-- | goodix_ts_core.h | 3 | ||||
-rw-r--r-- | touch_apis.c | 352 | ||||
-rw-r--r-- | touch_apis.h | 52 |
6 files changed, 502 insertions, 17 deletions
@@ -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 |