From: Jongpil Jung <jongpil19.jung@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> 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(+) 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)) { -- 2.17.1