diff options
author | Jisoo Sung <js.sung@samsung.com> | 2020-01-06 15:47:08 +0900 |
---|---|---|
committer | Super Liu <supercjliu@google.com> | 2020-01-16 11:24:03 +0800 |
commit | dc3805d5abbcf7b1cb6c45981c3703e5e414a91f (patch) | |
tree | 97d63c9a1a6e7f5a9ae9cc89316db0a30e351394 | |
parent | 66fe1726bb7807ebab91039fe082a7b9c3740c7d (diff) | |
download | sec_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.c | 249 |
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 |