diff options
author | davidycchen <davidycchen@google.com> | 2021-11-25 15:51:31 +0800 |
---|---|---|
committer | davidycchen <davidycchen@google.com> | 2021-11-26 11:34:59 +0800 |
commit | 8d731b8cfb5a2733598b04ea7e69ccddcbee9416 (patch) | |
tree | 2b11b2ed425fe439d00d42080aeee8fcaddbe779 | |
parent | 4ad4a9cf451d4d4c68e981a7c4c53d9a3b5aa13f (diff) | |
download | synaptics_touch-8d731b8cfb5a2733598b04ea7e69ccddcbee9416.tar.gz |
synaptics: support to get touch raw data from sysfs node
Bug: 199104466
Test:
cd /sys/class/spi_master/spi0/spi0.0/synaptics_tcm.0/sysfs
echo 12 > get_raw_data; cat get_raw_data
Signed-off-by: davidycchen <davidycchen@google.com>
Change-Id: If6d2bed19af2b069439bea444ce21e4e923b5fff
-rw-r--r-- | syna_tcm2.c | 27 | ||||
-rw-r--r-- | syna_tcm2.h | 3 | ||||
-rw-r--r-- | syna_tcm2_sysfs.c | 140 | ||||
-rw-r--r-- | tcm/synaptics_touchcom_core_dev.h | 1 |
4 files changed, 171 insertions, 0 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c index 0aa0f18..d70803c 100644 --- a/syna_tcm2.c +++ b/syna_tcm2.c @@ -631,6 +631,7 @@ static irqreturn_t syna_dev_interrupt_thread(int irq, void *data) unsigned char code = 0; struct syna_tcm *tcm = data; struct syna_hw_attn_data *attn = &tcm->hw_if->bdata_attn; + struct tcm_dev *tcm_dev = tcm->tcm_dev; /* It is possible that interrupts were disabled while the handler is * executing, before acquiring the mutex. If so, simply return. @@ -682,6 +683,25 @@ static irqreturn_t syna_dev_interrupt_thread(int irq, void *data) } /* forward the touch event to system */ syna_dev_report_input_events(tcm); + } else if (code == tcm->raw_data_report_code) { + if (!tcm->raw_data_buffer) { + tcm->raw_data_buffer = kmalloc( + sizeof(u16) * (tcm_dev->rows * tcm_dev->cols + + tcm_dev->rows + tcm_dev->cols), + GFP_KERNEL); + if (!tcm->raw_data_buffer) { + LOGE("Allocate raw_data_buffer failed\n"); + goto exit; + } + } + if (tcm->event_data.data_length == sizeof(u16) * (tcm_dev->rows * tcm_dev->cols + + tcm_dev->rows + tcm_dev->cols)) { + memcpy(tcm->raw_data_buffer, tcm->event_data.buf, + tcm->event_data.data_length); + complete_all(&tcm->raw_data_completion); + } else { + LOGE("Raw data length: %d is incorrect.\n", tcm->event_data.data_length); + } } exit: @@ -1810,6 +1830,10 @@ static int syna_dev_probe(struct platform_device *pdev) } #endif + tcm->raw_data_report_code = 0; + init_completion(&tcm->raw_data_completion); + complete_all(&tcm->raw_data_completion); + #ifdef HAS_SYSFS_INTERFACE /* create the device file and register to char device classes */ retval = syna_cdev_create_sysfs(tcm, pdev); @@ -1893,6 +1917,9 @@ static int syna_dev_remove(struct platform_device *pdev) return 0; } + if (tcm->raw_data_buffer) + kfree(tcm->raw_data_buffer); + #if defined(USE_DRM_BRIDGE) syna_unregister_panel_bridge(&tcm->panel_bridge); #elif defined(ENABLE_DISP_NOTIFIER) diff --git a/syna_tcm2.h b/syna_tcm2.h index 1e78c3d..23647d2 100644 --- a/syna_tcm2.h +++ b/syna_tcm2.h @@ -359,6 +359,9 @@ struct syna_tcm { #if defined(ENABLE_DISP_NOTIFIER) struct notifier_block fb_notifier; #endif + u8 raw_data_report_code; + s16 *raw_data_buffer; + struct completion raw_data_completion; #if defined(USE_DRM_BRIDGE) struct drm_bridge panel_bridge; diff --git a/syna_tcm2_sysfs.c b/syna_tcm2_sysfs.c index 03ac8d2..8755654 100644 --- a/syna_tcm2_sysfs.c +++ b/syna_tcm2_sysfs.c @@ -702,7 +702,146 @@ exit: static struct kobj_attribute kobj_attr_force_active = __ATTR(force_active, 0220, NULL, syna_sysfs_force_active_store); +/** + * syna_sysfs_get_raw_data_show() + * + * Attribute to show the rawdata. + * + * @param + * [ in] kobj: an instance of kobj + * [ in] attr: an instance of kobj attribute structure + * [out] buf: string buffer shown on console + * + * @return + * on success, number of characters being output; + * otherwise, negative value on error. + */ +static ssize_t syna_sysfs_get_raw_data_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int retval; + unsigned int count = 0; + struct device *p_dev; + struct kobject *p_kobj; + struct syna_tcm *tcm; + struct tcm_dev *tcm_dev; + int i, j; + + p_kobj = g_sysfs_dir->parent; + p_dev = container_of(p_kobj, struct device, kobj); + tcm = dev_get_drvdata(p_dev); + tcm_dev = tcm->tcm_dev; + + syna_pal_mutex_lock(&g_extif_mutex); + + if (wait_for_completion_timeout(&tcm->raw_data_completion, + msecs_to_jiffies(500)) == 0) { + complete_all(&tcm->raw_data_completion); + retval = scnprintf(buf + count, PAGE_SIZE - count, "Timeout\n"); + goto exit; + } + + /* Mutual raw. */ + count += scnprintf(buf + count, PAGE_SIZE - count, "Mutual\n"); + for (i = 0; i < tcm_dev->rows; i++) { + for (j = 0; j < tcm_dev->cols; j++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + tcm->raw_data_buffer[i * tcm_dev->cols + j]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + } + + /* Self raw. */ + count += scnprintf(buf + count, PAGE_SIZE - count, "Self\n"); + for (i = 0; i < tcm_dev->cols; i++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + tcm->raw_data_buffer[tcm_dev->cols * tcm_dev->rows + i]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + + for (j = 0; j < tcm_dev->rows; j++) { + count += scnprintf(buf + count, PAGE_SIZE - count, "%d ", + tcm->raw_data_buffer[tcm_dev->cols * tcm_dev->rows + i + j]); + } + count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); + + retval = count; + + LOGI("Got raw data, report code %#x\n", tcm->raw_data_report_code); + +exit: + syna_tcm_set_dynamic_config(tcm->tcm_dev, DC_DISABLE_DOZE, 0, RESP_IN_ATTN); + syna_tcm_enable_report(tcm_dev, tcm->raw_data_report_code, false); + syna_pal_mutex_unlock(&g_extif_mutex); + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, false); + return retval; +} + +/** + * syna_sysfs_get_raw_data_store() + * + * Attribute to enable the rawdata report type. + * + * @param + * [ in] kobj: an instance of kobj + * [ in] attr: an instance of kobj attribute structure + * [ in] buf: string buffer input + * [ in] count: size of buffer input + * + * @return + * on success, return count; otherwise, return error code + */ +static ssize_t syna_sysfs_get_raw_data_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int retval = count; + unsigned char input; + unsigned char report_code; + struct device *p_dev; + struct kobject *p_kobj; + struct syna_tcm *tcm; + + p_kobj = g_sysfs_dir->parent; + p_dev = container_of(p_kobj, struct device, kobj); + tcm = dev_get_drvdata(p_dev); + + if (kstrtou8(buf, 16, &input)) + return -EINVAL; + + syna_set_bus_ref(tcm, SYNA_BUS_REF_SYSFS, true); + syna_pal_mutex_lock(&g_extif_mutex); + + switch (input) { + case REPORT_DELTA: + report_code = REPORT_DELTA; + break; + case REPORT_RAW: + report_code = REPORT_RAW; + break; + case REPORT_BASELINE: + report_code = REPORT_BASELINE; + break; + default: + LOGE("Invalid input %#x.\n", input); + retval = -EINVAL; + goto exit; + } + + LOGI("Enable raw data, report code %#x\n", report_code); + + syna_tcm_set_dynamic_config(tcm->tcm_dev, DC_DISABLE_DOZE, 1, RESP_IN_ATTN); + + tcm->raw_data_report_code = report_code; + syna_tcm_enable_report(tcm->tcm_dev, report_code, true); + reinit_completion(&tcm->raw_data_completion); + +exit: + syna_pal_mutex_unlock(&g_extif_mutex); + return retval; +} +static struct kobj_attribute kobj_attr_get_raw_data = + __ATTR(get_raw_data, 0664, syna_sysfs_get_raw_data_show, syna_sysfs_get_raw_data_store); /** * declaration of sysfs attributes @@ -713,6 +852,7 @@ static struct attribute *attrs[] = { &kobj_attr_reset.attr, &kobj_attr_scan_mode.attr, &kobj_attr_force_active.attr, + &kobj_attr_get_raw_data.attr, NULL, }; diff --git a/tcm/synaptics_touchcom_core_dev.h b/tcm/synaptics_touchcom_core_dev.h index 4765713..ab462e1 100644 --- a/tcm/synaptics_touchcom_core_dev.h +++ b/tcm/synaptics_touchcom_core_dev.h @@ -310,6 +310,7 @@ enum tcm_report_type { REPORT_TOUCH = 0x11, REPORT_DELTA = 0x12, REPORT_RAW = 0x13, + REPORT_BASELINE = 0x14, }; /** |