[7/8] Input: atmel_mxt_ts - add interface to read/write config file name.
diff mbox series

Message ID 20190828095349.30607-7-jongpuls@gmail.com
State New
Headers show
Series
  • [1/8] Input: atmel_mxt_ts - eanble calibration via sysfs
Related show

Commit Message

Jongpil Jung Aug. 28, 2019, 9:53 a.m. UTC
From: Jongpil Jung <jongpil19.jung@samsung.corp-partner.google.com>

Add interface to change config/firmware file name easily.
So, we can pass file name to kernel space before we update
config/firmware.

Change-Id: I5b0253feb47e62d7013148f5ef117a9f2ba0b162
---
 drivers/input/touchscreen/atmel_mxt_ts.c | 97 ++++++++++++++++++++++++
 1 file changed, 97 insertions(+)

Patch
diff mbox series

diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 3a17adf04e2a..2f1013c97433 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -334,6 +334,12 @@  struct mxt_data {
 	/* for config update handling */
 	struct completion crc_completion;
 
+	/* firmware file name */
+	char *fw_file;
+
+	/* config file name */
+	char *config_file;
+
 	u32 *t19_keymap;
 	unsigned int t19_num_keys;
 
@@ -2681,6 +2687,42 @@  static int mxt_configure_objects(struct mxt_data *data,
 	return 0;
 }
 
+static int mxt_update_file_name(struct device *dev, char **file_name,
+				const char *buf, size_t count)
+{
+	char *new_file_name;
+
+	/* Simple sanity check */
+	if (count > 64) {
+		dev_warn(dev, "File name too long\n");
+		return -EINVAL;
+	}
+
+	/* FIXME: devm_kmemdup() when available */
+	new_file_name = devm_kmalloc(dev, count + 1, GFP_KERNEL);
+	if (!new_file_name) {
+		dev_warn(dev, "no memory\n");
+		return -ENOMEM;
+	}
+
+	memcpy(new_file_name, buf, count + 1);
+
+	dev_dbg(dev, "new file name %s\n", new_file_name);
+
+	/* Echo into the sysfs entry may append newline at the end of buf */
+	if (new_file_name[count - 1] == '\n')
+		count--;
+
+	new_file_name[count] = '\0';
+
+	if (*file_name)
+		devm_kfree(dev, *file_name);
+
+	*file_name = new_file_name;
+
+	return 0;
+}
+
 static ssize_t mxt_backupnv_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
@@ -2718,6 +2760,45 @@  static ssize_t mxt_config_csum_show(struct device *dev,
 	return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_crc);
 }
 
+static ssize_t mxt_config_file_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", data->config_file);
+}
+
+static ssize_t mxt_config_file_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = mxt_update_file_name(dev, &data->config_file, buf, count);
+	return ret ? ret : count;
+}
+
+static ssize_t mxt_fw_file_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", data->fw_file);
+}
+
+static ssize_t mxt_fw_file_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = mxt_update_file_name(dev, &data->fw_file, buf, count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
 /* Firmware Version is returned as Major.Minor.Build */
 static ssize_t mxt_fw_version_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
@@ -2985,6 +3066,10 @@  static ssize_t mxt_update_fw_store(struct device *dev,
 static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
 static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
 static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+static DEVICE_ATTR(config_file, S_IRUGO | S_IWUSR, mxt_config_file_show,
+		   mxt_config_file_store);
+static DEVICE_ATTR(fw_file, S_IRUGO | S_IWUSR, mxt_fw_file_show,
+		   mxt_fw_file_store);
 static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
 static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
 static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
@@ -2996,6 +3081,8 @@  static struct attribute *mxt_attrs[] = {
 	&dev_attr_backupnv.attr,
 	&dev_attr_calibrate.attr,
 	&dev_attr_config_csum.attr,
+	&dev_attr_config_file.attr,
+	&dev_attr_fw_file.attr,
 	&dev_attr_fw_version.attr,
 	&dev_attr_hw_version.attr,
 	&dev_attr_info_csum.attr,
@@ -3167,6 +3254,16 @@  static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (error)
 		return error;
 
+	error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
+				     strlen(MXT_FW_NAME));
+	if (error)
+		return error;
+
+	error = mxt_update_file_name(&client->dev, &data->config_file,
+				     MXT_CFG_NAME, strlen(MXT_CFG_NAME));
+	if (error)
+		return error;
+
 	data->reset_gpio = devm_gpiod_get_optional(&client->dev,
 						   "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(data->reset_gpio)) {