Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51a9f39d authored by Amy Maloche's avatar Amy Maloche Committed by Sudhakar Manapati
Browse files

input: synaptics_fw_update: Add sysfs entry for fw_name



Allow user to read and write firmware name from sysfs.
Also modify firmware update so it does not interfere with
suspend.

This patch is propagated from the msm-3.4 kernel.
(commit: b494b9aa7601e222a3e68fd12ab1c8cff1fcc519
input: synaptics_fw_update: Add sysfs entry for fw_name)

Change-Id: Iec1e3ef375211a8665443dcfd7b4e24a025fde93
Signed-off-by: default avatarAmy Maloche <amaloche@codeaurora.org>
Signed-off-by: default avatarSudhakar Manapati <smanap@codeaurora.org>
parent cb02d546
Loading
Loading
Loading
Loading
+112 −117
Original line number Diff line number Diff line
@@ -53,8 +53,6 @@
#define BLOCK_NUMBER_OFFSET 0
#define BLOCK_DATA_OFFSET 2

#define NAME_BUFFER_SIZE 128

enum falsh_config_area {
	UI_CONFIG_AREA = 0x00,
	PERM_CONFIG_AREA = 0x01,
@@ -99,53 +97,6 @@ enum image_file_option {

#define SLEEP_TIME_US 50

static ssize_t fwu_sysfs_show_image(struct file *data_file,
		struct kobject *kobj, struct bin_attribute *attributes,
		char *buf, loff_t pos, size_t count);

static ssize_t fwu_sysfs_store_image(struct file *data_file,
		struct kobject *kobj, struct bin_attribute *attributes,
		char *buf, loff_t pos, size_t count);

static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_write_config_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_read_config_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_config_area_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_image_size_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count);

static ssize_t fwu_sysfs_block_size_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static ssize_t fwu_sysfs_config_id_show(struct device *dev,
		struct device_attribute *attr, char *buf);

static int fwu_wait_for_idle(int timeout_ms);

struct image_header_data {
@@ -292,59 +243,7 @@ struct synaptics_rmi4_fwu_handle {
	struct f34_flash_properties flash_properties;
	struct workqueue_struct *fwu_workqueue;
	struct delayed_work fwu_work;
	char *firmware_name;
};

static struct bin_attribute dev_attr_data = {
	.attr = {
		.name = "data",
		.mode = (S_IRUGO | S_IWUGO),
	},
	.size = 0,
	.read = fwu_sysfs_show_image,
	.write = fwu_sysfs_store_image,
};

static struct device_attribute attrs[] = {
	__ATTR(force_update_fw, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_force_reflash_store),
	__ATTR(update_fw, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_do_reflash_store),
	__ATTR(writeconfig, (S_IWUSR | S_IWGRP),
			synaptics_rmi4_show_error,
			fwu_sysfs_write_config_store),
	__ATTR(readconfig, (S_IWUSR | S_IWGRP),
			synaptics_rmi4_show_error,
			fwu_sysfs_read_config_store),
	__ATTR(configarea, (S_IWUSR | S_IWGRP),
			synaptics_rmi4_show_error,
			fwu_sysfs_config_area_store),
	__ATTR(imagesize, (S_IWUSR | S_IWGRP),
			synaptics_rmi4_show_error,
			fwu_sysfs_image_size_store),
	__ATTR(blocksize, S_IRUGO,
			fwu_sysfs_block_size_show,
			synaptics_rmi4_store_error),
	__ATTR(fwblockcount, S_IRUGO,
			fwu_sysfs_firmware_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(configblockcount, S_IRUGO,
			fwu_sysfs_configuration_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(permconfigblockcount, S_IRUGO,
			fwu_sysfs_perm_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(blconfigblockcount, S_IRUGO,
			fwu_sysfs_bl_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(dispconfigblockcount, S_IRUGO,
			fwu_sysfs_disp_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(config_id, S_IRUGO,
			fwu_sysfs_config_id_show,
			synaptics_rmi4_store_error),
	char firmware_name[NAME_BUFFER_SIZE];
};

static struct synaptics_rmi4_fwu_handle *fwu;
@@ -1307,23 +1206,23 @@ static int fwu_start_reflash(void)

	pr_notice("%s: Start of reflash process\n", __func__);

	if (!fwu->rmi4_data->fw_image_name) {
		retval = 0;
	if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) == 0) {
		dev_err(&fwu->rmi4_data->i2c_client->dev,
			"Firmware image name not given, skipping update\n");
		goto exit;
		return 0;
	}

	if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
		NAME_BUFFER_SIZE) {
		dev_err(&fwu->rmi4_data->i2c_client->dev,
			"Firmware image name exceeds max length (%d), ",
			"skipping update\n", NAME_BUFFER_SIZE);
		return 0;
	}

	if (fwu->ext_data_source)
		fw_image = fwu->ext_data_source;
	else {
		fwu->firmware_name = kcalloc(NAME_BUFFER_SIZE,
			sizeof(char), GFP_KERNEL);
		if (!fwu->firmware_name) {
			retval = -ENOMEM;
			goto memory_exit;
		}

		snprintf(fwu->firmware_name, NAME_BUFFER_SIZE, "%s",
			fwu->rmi4_data->fw_image_name);
		dev_info(&fwu->rmi4_data->i2c_client->dev,
@@ -1338,8 +1237,7 @@ static int fwu_start_reflash(void)
					"%s: Firmware image %s not available\n",
					__func__,
					fwu->firmware_name);
			retval = -EINVAL;
			goto exit;
			return -EINVAL;
		}

		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
@@ -1410,13 +1308,11 @@ static int fwu_start_reflash(void)
		goto exit;
	}

exit:
	if (fw_entry)
		release_firmware(fw_entry);

	pr_notice("%s: End of reflash process\n", __func__);
exit:
	kfree(fwu->firmware_name);
memory_exit:
	return retval;
}

@@ -1430,10 +1326,19 @@ int synaptics_fw_updater(unsigned char *fw_data)
	if (!fwu->initialized)
		return -ENODEV;

	fwu->rmi4_data->fw_updating = true;
	if (fwu->rmi4_data->touch_stopped == true) {
		fwu->rmi4_data->fw_updating = false;
		dev_err(&fwu->rmi4_data->i2c_client->dev,
			"Cannot start fw upgrade while device is in suspend\n");
		return -EBUSY;
	}

	fwu->ext_data_source = fw_data;
	fwu->config_area = UI_CONFIG_AREA;

	retval = fwu_start_reflash();
	fwu->rmi4_data->fw_updating = false;

	return retval;
}
@@ -1470,6 +1375,40 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file,
	return count;
}

static ssize_t fwu_sysfs_fw_name_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
	char *strptr;

	if (count >= NAME_BUFFER_SIZE) {
		dev_err(&rmi4_data->i2c_client->dev,
			"Input over %d characters long\n", NAME_BUFFER_SIZE);
		return -EINVAL;
	}

	strptr = strnstr(buf, ".img",
			count);
	if (!strptr) {
		dev_err(&rmi4_data->i2c_client->dev,
			"Input is not valid .img file\n");
		return -EINVAL;
	}

	strlcpy(rmi4_data->fw_image_name, buf, count);
	return count;
}

static ssize_t fwu_sysfs_fw_name_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
		return snprintf(buf, PAGE_SIZE, "%s\n",
			fwu->rmi4_data->fw_image_name);
	else
		return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
}

static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
@@ -1685,6 +1624,62 @@ static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
		fwu_read_f34_flash_status();
}

static struct bin_attribute dev_attr_data = {
	.attr = {
		.name = "data",
		.mode = (S_IRUGO | S_IWUGO),
	},
	.size = 0,
	.read = fwu_sysfs_show_image,
	.write = fwu_sysfs_store_image,
};

static struct device_attribute attrs[] = {
	__ATTR(fw_name, S_IWUGO | S_IRUGO,
			fwu_sysfs_fw_name_show,
			fwu_sysfs_fw_name_store),
	__ATTR(force_update_fw, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_force_reflash_store),
	__ATTR(update_fw, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_do_reflash_store),
	__ATTR(writeconfig, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_write_config_store),
	__ATTR(readconfig, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_read_config_store),
	__ATTR(configarea, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_config_area_store),
	__ATTR(imagesize, S_IWUGO,
			synaptics_rmi4_show_error,
			fwu_sysfs_image_size_store),
	__ATTR(blocksize, S_IRUGO,
			fwu_sysfs_block_size_show,
			synaptics_rmi4_store_error),
	__ATTR(fwblockcount, S_IRUGO,
			fwu_sysfs_firmware_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(configblockcount, S_IRUGO,
			fwu_sysfs_configuration_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(permconfigblockcount, S_IRUGO,
			fwu_sysfs_perm_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(blconfigblockcount, S_IRUGO,
			fwu_sysfs_bl_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(dispconfigblockcount, S_IRUGO,
			fwu_sysfs_disp_config_block_count_show,
			synaptics_rmi4_store_error),
	__ATTR(config_id, S_IRUGO,
			fwu_sysfs_config_id_show,
			synaptics_rmi4_store_error),
};


static void synaptics_rmi4_fwu_work(struct work_struct *work)
{
	fwu_start_reflash();
+19 −13
Original line number Diff line number Diff line
@@ -2046,6 +2046,7 @@ static int synaptics_rmi4_probe(struct i2c_client *client,
	rmi4_data->touch_stopped = false;
	rmi4_data->sensor_sleep = false;
	rmi4_data->irq_enabled = false;
	rmi4_data->fw_updating = false;

	rmi4_data->i2c_read = synaptics_rmi4_i2c_read;
	rmi4_data->i2c_write = synaptics_rmi4_i2c_write;
@@ -2055,7 +2056,9 @@ static int synaptics_rmi4_probe(struct i2c_client *client,
	rmi4_data->flip_x = rmi4_data->board->x_flip;
	rmi4_data->flip_y = rmi4_data->board->y_flip;

	rmi4_data->fw_image_name = rmi4_data->board->fw_image_name;
	if (rmi4_data->board->fw_image_name)
		snprintf(rmi4_data->fw_image_name, NAME_BUFFER_SIZE, "%s",
			rmi4_data->board->fw_image_name);

	rmi4_data->input_dev->name = DRIVER_NAME;
	rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
@@ -2577,6 +2580,7 @@ static int synaptics_rmi4_suspend(struct device *dev)
	struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
	int retval;

	if (!rmi4_data->fw_updating) {
		if (!rmi4_data->sensor_sleep) {
			rmi4_data->touch_stopped = true;
			wake_up(&rmi4_data->wait);
@@ -2589,7 +2593,9 @@ static int synaptics_rmi4_suspend(struct device *dev)
			dev_err(dev, "failed to enter low power mode\n");
			return retval;
		}

	} else
		dev_err(dev,
			"Firmware updating, cannot go into suspend mode\n");
	return 0;
}

+5 −1
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@
#define MASK_2BIT 0x03
#define MASK_1BIT 0x01

#define NAME_BUFFER_SIZE 128

/*
 * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT
 * @query_base_addr: base address for query registers
@@ -183,6 +185,7 @@ struct synaptics_rmi4_device_info {
 * @fingers_on_2d: flag to indicate presence of fingers in 2d area
 * @flip_x: set to TRUE if desired to flip direction on x-axis
 * @flip_y: set to TRUE if desired to flip direction on y-axis
 * @fw_updating: firmware is updating flag
 * @sensor_sleep: flag to indicate sleep state of sensor
 * @wait: wait queue for touch data polling in interrupt thread
 * @i2c_read: pointer to i2c read function
@@ -202,7 +205,7 @@ struct synaptics_rmi4_data {
#ifdef CONFIG_HAS_EARLYSUSPEND
	struct early_suspend early_suspend;
#endif
	const char *fw_image_name;
	char fw_image_name[NAME_BUFFER_SIZE];
	unsigned char current_page;
	unsigned char button_0d_enabled;
	unsigned char full_pm_cycle;
@@ -224,6 +227,7 @@ struct synaptics_rmi4_data {
	bool sensor_sleep;
	bool flip_x;
	bool flip_y;
	bool fw_updating;
	wait_queue_head_t wait;
	int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
			unsigned char *data, unsigned short length);