summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJisoo Sung <js.sung@samsung.com>2020-01-06 15:47:08 +0900
committerSuper Liu <supercjliu@google.com>2020-01-16 11:24:03 +0800
commitdc3805d5abbcf7b1cb6c45981c3703e5e414a91f (patch)
tree97d63c9a1a6e7f5a9ae9cc89316db0a30e351394
parent66fe1726bb7807ebab91039fe082a7b9c3740c7d (diff)
downloadsec_touch-dc3805d5abbcf7b1cb6c45981c3703e5e414a91f.tar.gz
sec_touch: add manual cmd sysfs for register read and write
Bug: 145259282 Change-Id: Id9e0bbb02f753d7a996ce27247d6dc89eba60491 Signed-off-by: Jisoo Sung <js.sung@samsung.com> Signed-off-by: Super Liu <supercjliu@google.com>
-rw-r--r--sec_ts_only_vendor.c249
1 files changed, 241 insertions, 8 deletions
diff --git a/sec_ts_only_vendor.c b/sec_ts_only_vendor.c
index dab3575..bc272d0 100644
--- a/sec_ts_only_vendor.c
+++ b/sec_ts_only_vendor.c
@@ -39,6 +39,15 @@ static int lv1_readsize;
static int lv1_readremain;
static int lv1_readoffset;
+u8 lv1cmd_manual;
+static int lv1_readsize_manual;
+static int lv1_readremain_manual;
+static int lv1_readoffset_manual;
+
+#define SEC_TS_CMD_BUF_SZ 64
+static u8 cmd_buf[SEC_TS_CMD_BUF_SZ];
+static int cmd_buf_num;
+
static ssize_t sec_ts_reg_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
static ssize_t sec_ts_regreadsize_store(struct device *dev,
@@ -54,11 +63,22 @@ static ssize_t sec_ts_gesture_status_show(struct device *dev,
static inline ssize_t sec_ts_show_error(struct device *dev,
struct device_attribute *attr, char *buf);
-static DEVICE_ATTR(sec_ts_reg, (S_IWUSR | S_IWGRP), NULL, sec_ts_reg_store);
-static DEVICE_ATTR(sec_ts_regreadsize, (S_IWUSR | S_IWGRP), NULL, sec_ts_regreadsize_store);
-static DEVICE_ATTR(sec_ts_enter_recovery, (S_IWUSR | S_IWGRP), NULL, sec_ts_enter_recovery_store);
-static DEVICE_ATTR(sec_ts_regread, S_IRUGO, sec_ts_regread_show, NULL);
-static DEVICE_ATTR(sec_ts_gesture_status, S_IRUGO, sec_ts_gesture_status_show, NULL);
+static ssize_t sec_ts_reg_manual_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t sec_ts_regreadsize_manual_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t sec_ts_regread_manual_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static DEVICE_ATTR_WO(sec_ts_reg);
+static DEVICE_ATTR_WO(sec_ts_regreadsize);
+static DEVICE_ATTR_WO(sec_ts_enter_recovery);
+static DEVICE_ATTR_RO(sec_ts_regread);
+static DEVICE_ATTR_RO(sec_ts_gesture_status);
+
+static DEVICE_ATTR_WO(sec_ts_reg_manual);
+static DEVICE_ATTR_WO(sec_ts_regreadsize_manual);
+static DEVICE_ATTR_RO(sec_ts_regread_manual);
static struct attribute *cmd_attributes[] = {
&dev_attr_sec_ts_reg.attr,
@@ -66,6 +86,9 @@ static struct attribute *cmd_attributes[] = {
&dev_attr_sec_ts_enter_recovery.attr,
&dev_attr_sec_ts_regread.attr,
&dev_attr_sec_ts_gesture_status.attr,
+ &dev_attr_sec_ts_reg_manual.attr,
+ &dev_attr_sec_ts_regreadsize_manual.attr,
+ &dev_attr_sec_ts_regread_manual.attr,
NULL,
};
@@ -74,7 +97,215 @@ static struct attribute_group cmd_attr_group = {
};
/* for debugging--------------------------------------------------------------------------------------*/
-static ssize_t sec_ts_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+static void sec_ts_parsing_cmds(struct device *dev,
+ const char *buf, size_t size, bool write)
+{
+ u8 result, n = 0;
+ char *p, *temp_buf, *token;
+ size_t token_len = 0;
+ struct sec_ts_data *ts = dev_get_drvdata(dev);
+
+ /* clear cmd_buf */
+ memset(cmd_buf, 0, sizeof(cmd_buf));
+ cmd_buf_num = 0;
+
+ /* pre-check input */
+ if (write) {
+ if (size < 2) {
+ input_info(true, &ts->client->dev,
+ "%s: invalid input size %d\n",
+ __func__);
+ return;
+ }
+ } else {
+ if (size < 3) {
+ input_info(true, &ts->client->dev,
+ "%s: invalid input size %d\n",
+ __func__);
+ return;
+ } else if (buf[0] != 'R' && buf[0] != 'r') {
+ input_info(true, &ts->client->dev,
+ "%s: invalid input %c, Have to start with R(r)\n",
+ __func__, buf[0]);
+ return;
+ }
+ }
+
+ /* alloc temp_buf for parsing
+ * read case will skip 1st character
+ */
+ temp_buf = kstrdup(buf, GFP_KERNEL);
+ if (!temp_buf) {
+ pr_err("%s: memory allocation failed!",
+ __func__);
+ return;
+ }
+ p = temp_buf;
+
+ /* newline case at last char */
+ if (p[size - 1] == '\n')
+ p[size - 1] = '\0';
+
+ /* skip 1st character for read case */
+ if (!write)
+ p++;
+
+ /* parsing */
+ while (p && (n < SEC_TS_CMD_BUF_SZ)) {
+
+ while (isspace(*p))
+ p++;
+
+ token = strsep(&p, " ");
+ if (!token || *token == '\0')
+ break;
+
+ token_len = strlen(token);
+ if (token_len != 2) {
+ pr_err("%s: bad len %zu\n", __func__, token_len);
+ n = 0;
+ break;
+ }
+
+ if (kstrtou8(token, 16, &result)) {
+ /* Conversion failed due to bad input.
+ * Discard the entire buffer.
+ */
+ pr_err("%s: bad input\n", __func__);
+ n = 0;
+ break;
+ }
+ /* found a valid cmd/args */
+ cmd_buf[n] = result;
+ n++;
+ }
+ kfree(temp_buf);
+ cmd_buf_num = n;
+}
+
+/* sysfs file node to write reg
+ *
+ * echo _REG_ _VAL_ ... > sec_ts_reg_manual
+ *
+ * e.g. write reg 0xD7 with 0x02 0x04
+ * echo D7 02 04 > sec_ts_reg_manual
+ */
+static ssize_t sec_ts_reg_manual_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct sec_ts_data *ts = dev_get_drvdata(dev);
+
+ if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
+ input_info(true, &ts->client->dev,
+ "%s: Power off state\n", __func__);
+ return -EIO;
+ }
+
+ sec_ts_parsing_cmds(dev, buf, size, true);
+
+ if (cmd_buf_num) {
+ ts->sec_ts_write_burst(ts, cmd_buf, cmd_buf_num);
+
+ input_info(true, &ts->client->dev,
+ "%s: size %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", __func__,
+ cmd_buf_num, cmd_buf[0], cmd_buf[1], cmd_buf[2],
+ cmd_buf[3], cmd_buf[4]);
+ }
+
+ return size;
+}
+
+/* sysfs file node to read reg
+ *
+ * step 1: set reg and size that want to read
+ * echo R_REG_ _SIZE_ > sec_ts_regreadsize_manual
+ *
+ * e.g. read reg 0x52 for 3 bytes
+ * echo R52 03 > sec_ts_regreadsize_manual
+ *
+ * step 2: read reg
+ * cat sec_ts_regread_manual
+ */
+static ssize_t sec_ts_regreadsize_manual_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct sec_ts_data *ts = dev_get_drvdata(dev);
+
+ sec_ts_parsing_cmds(dev, buf, size, false);
+
+ if (cmd_buf_num == 2) {
+ lv1cmd_manual = cmd_buf[0];
+ lv1_readsize_manual = cmd_buf[1];
+ lv1_readoffset_manual = 0;
+ lv1_readremain_manual = 0;
+ input_info(true, &ts->client->dev,
+ "%s: read reg %X sz %d\n",
+ __func__, lv1cmd_manual, lv1_readsize_manual);
+ } else
+ input_info(true, &ts->client->dev,
+ "%s: invalid input to reg read! cmd_num %d, cmd %x %x\n",
+ __func__, cmd_buf_num, cmd_buf[0], cmd_buf[1]);
+
+ return size;
+}
+
+
+/* sysfs file node to read reg
+ * check sec_ts_regreadsize_manual_store() above for details.
+ */
+static ssize_t sec_ts_regread_manual_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 *read_lv1_buff_manual;
+ struct sec_ts_data *ts = dev_get_drvdata(dev);
+ unsigned int str_len = 0;
+ int ret = 0, i;
+
+ if (ts->power_status == SEC_TS_STATE_POWER_OFF) {
+ input_err(true, &ts->client->dev,
+ "%s: Power off state\n", __func__);
+ return -EIO;
+ }
+ if (lv1_readsize_manual < 1) {
+ input_err(true, &ts->client->dev,
+ "%s: Nothing to read\n", __func__);
+ return -EIO;
+ }
+
+ disable_irq(ts->client->irq);
+
+ read_lv1_buff_manual = kzalloc(lv1_readsize_manual, GFP_KERNEL);
+ if (!read_lv1_buff_manual)
+ goto malloc_err;
+
+ ret = ts->sec_ts_read_heap(ts, lv1cmd_manual,
+ read_lv1_buff_manual, lv1_readsize_manual);
+ if (ret < 0)
+ input_err(true, &ts->client->dev,
+ "%s: read reg %x failed!\n",
+ __func__, lv1cmd_manual);
+ else {
+ for (i = 0 ; i < lv1_readsize_manual ; i++)
+ str_len += scnprintf(buf + str_len,
+ PAGE_SIZE - str_len,
+ "%02X ",
+ (u8)read_lv1_buff_manual[i]);
+ str_len += scnprintf(buf + str_len, PAGE_SIZE - str_len, "\n");
+ input_info(true, &ts->client->dev, "%s: reg %X sz %d -> %s\n",
+ __func__, lv1cmd_manual, lv1_readsize_manual, buf);
+ }
+
+ kfree(read_lv1_buff_manual);
+
+malloc_err:
+ lv1_readremain_manual = 0;
+ enable_irq(ts->client->irq);
+
+ return str_len;
+}
+
+static ssize_t sec_ts_reg_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
{
struct sec_ts_data *ts = dev_get_drvdata(dev);
@@ -86,7 +317,9 @@ static ssize_t sec_ts_reg_store(struct device *dev, struct device_attribute *att
if (size > 0)
ts->sec_ts_write_burst(ts, (u8 *)buf, size);
- input_info(true, &ts->client->dev, "%s: 0x%x, 0x%x, size %d\n", __func__, buf[0], buf[1], (int)size);
+ input_info(true, &ts->client->dev,
+ "%s: 0x%x, 0x%x, size %d\n",
+ __func__, buf[0], buf[1], (int)size);
return size;
}
@@ -274,7 +507,7 @@ void sec_ts_raw_device_exit(struct sec_ts_data *ts)
{
sysfs_remove_group(&ts->dev->kobj, &cmd_attr_group);
#ifdef CONFIG_SEC_SYSFS
- sec_device_destroy(ts->dev->devt)
+ sec_device_destroy(ts->dev->devt);
#else
device_destroy(sec_class, 0);
#endif