summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidycchen <davidycchen@google.com>2021-11-25 15:51:31 +0800
committerdavidycchen <davidycchen@google.com>2021-11-26 11:34:59 +0800
commit8d731b8cfb5a2733598b04ea7e69ccddcbee9416 (patch)
tree2b11b2ed425fe439d00d42080aeee8fcaddbe779
parent4ad4a9cf451d4d4c68e981a7c4c53d9a3b5aa13f (diff)
downloadsynaptics_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.c27
-rw-r--r--syna_tcm2.h3
-rw-r--r--syna_tcm2_sysfs.c140
-rw-r--r--tcm/synaptics_touchcom_core_dev.h1
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,
};
/**