mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Dudley Du <dudley.dulixin@gmail.com>
To: dmitry.torokhov@gmail.com, rydberg@euromail.se
Cc: Dudley Du <dudley.dulixin@gmail.com>,
	bleung@google.com, linux-input@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v11 14/19] input: cyapa: add read firmware image debugfs interface support
Date: Wed, 19 Nov 2014 16:37:46 +0800	[thread overview]
Message-ID: <1416386271-28167-15-git-send-email-dudley.dulixin@gmail.com> (raw)
In-Reply-To: <1416386271-28167-1-git-send-email-dudley.dulixin@gmail.com>

Add read firmware image from trackpad device interface supported in cyapa
driver through debugfs read_fw interface.
Through this interface user can read out, check and backup the firmware image
of the trackpad device before any firmware update, or can use the backed image
to do firmware image recovery.
TEST=test on Chromebooks.

Signed-off-by: Dudley Du <dudley.dulixin@gmail.com>
---
 drivers/input/mouse/cyapa.c | 179 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/input/mouse/cyapa.h |  10 +++
 2 files changed, 188 insertions(+), 1 deletion(-)

diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 305dffe..2e394c0 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -14,6 +14,7 @@
  * more details.
  */
 
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
@@ -32,10 +33,14 @@
 #define CYAPA_ADAPTER_FUNC_SMBUS  2
 #define CYAPA_ADAPTER_FUNC_BOTH   3
 
+#define CYAPA_DEBUGFS_READ_FW	"read_fw"
 #define CYAPA_FW_NAME		"cyapa.bin"
 
 const char unique_str[] = "CYTRA";
 
+/* Global root node of the cyapa debugfs directory. */
+static struct dentry *cyapa_debugfs_root;
+
 /* Returns 0 on success, else negative errno on failure. */
 ssize_t cyapa_i2c_read(struct cyapa *cyapa, u8 reg, size_t len,
 					u8 *values)
@@ -497,6 +502,138 @@ static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa)
 }
 
 /*
+ **************************************************************
+ * debugfs interface
+ **************************************************************
+*/
+static int cyapa_debugfs_open(struct inode *inode, struct file *file)
+{
+	struct cyapa *cyapa = inode->i_private;
+	int error;
+
+	if (!cyapa)
+		return -ENODEV;
+
+	error = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+	if (error)
+		return error;
+
+	if (!get_device(&cyapa->client->dev)) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	file->private_data = cyapa;
+
+	if (cyapa->fw_image && cyapa->fw_image_size) {
+		error = 0;
+		goto out;
+	}
+
+	error = mutex_lock_interruptible(&cyapa->state_sync_lock);
+	if (error)
+		goto out;
+
+	/*
+	 * If firmware hasn't been read yet, read it all in one pass.
+	 * Subsequent opens will reuse the data in this same buffer.
+	 */
+	if (cyapa->ops->read_fw) {
+		cyapa_enable_irq_for_cmd(cyapa);
+		error = cyapa->ops->read_fw(cyapa);
+		cyapa_disable_irq_for_cmd(cyapa);
+
+		/*
+		 * Redetect trackpad device states because read_fw will
+		 * reset trackpad device into bootloader mode.
+		 */
+		cyapa_detect(cyapa);
+	} else {
+		error = -EPERM;
+	}
+
+	mutex_unlock(&cyapa->state_sync_lock);
+out:
+	mutex_unlock(&cyapa->debugfs_mutex);
+	return error;
+}
+
+static int cyapa_debugfs_release(struct inode *inode, struct file *file)
+{
+	struct cyapa *cyapa = file->private_data;
+	int error;
+
+	if (!cyapa)
+		return 0;
+
+	error = mutex_lock_interruptible(&cyapa->debugfs_mutex);
+	if (error)
+		return error;
+	file->private_data = NULL;
+	put_device(&cyapa->client->dev);
+	mutex_unlock(&cyapa->debugfs_mutex);
+
+	return 0;
+}
+
+/* Return some bytes from the buffered firmware image, starting from *ppos */
+static ssize_t cyapa_debugfs_read_fw(struct file *file, char __user *buffer,
+				     size_t count, loff_t *ppos)
+{
+	struct cyapa *cyapa = file->private_data;
+
+	if (!cyapa->fw_image)
+		return -EINVAL;
+
+	if (*ppos >= cyapa->fw_image_size)
+		return 0;
+
+	if (count + *ppos > cyapa->fw_image_size)
+		count = cyapa->fw_image_size - *ppos;
+
+	if (copy_to_user(buffer, &cyapa->fw_image[*ppos], count))
+		return -EFAULT;
+
+	*ppos += count;
+	return count;
+}
+
+static const struct file_operations cyapa_read_fw_fops = {
+	.open = cyapa_debugfs_open,
+	.release = cyapa_debugfs_release,
+	.read = cyapa_debugfs_read_fw
+};
+
+static int cyapa_debugfs_init(struct cyapa *cyapa)
+{
+	struct device *dev = &cyapa->client->dev;
+
+	if (!cyapa_debugfs_root)
+		return -ENODEV;
+
+	cyapa->dentry_dev = debugfs_create_dir(kobject_name(&dev->kobj),
+					       cyapa_debugfs_root);
+
+	if (!cyapa->dentry_dev)
+		return -ENODEV;
+
+	mutex_init(&cyapa->debugfs_mutex);
+
+	debugfs_create_file(CYAPA_DEBUGFS_READ_FW, S_IRUSR, cyapa->dentry_dev,
+			    cyapa, &cyapa_read_fw_fops);
+
+	return 0;
+}
+
+static void cyapa_remove_debugfs(void *data)
+{
+	struct cyapa *cyapa = data;
+
+	debugfs_remove_recursive(cyapa->dentry_dev);
+	mutex_destroy(&cyapa->debugfs_mutex);
+}
+
+/*
  * Sysfs Interface.
  */
 
@@ -1076,6 +1213,20 @@ static int cyapa_probe(struct i2c_client *client,
 		return error;
 	}
 
+	error = cyapa_debugfs_init(cyapa);
+	if (error) {
+		dev_err(dev, "failed to create debugfs entries: %d\n", error);
+		return error;
+	}
+
+	error = devm_add_action(dev, cyapa_remove_debugfs, cyapa);
+	if (error) {
+		cyapa_remove_debugfs(cyapa);
+		dev_err(dev, "failed to add debugfs cleanup action :%d\n",
+			error);
+		return error;
+	}
+
 #ifdef CONFIG_PM_SLEEP
 	if (device_can_wakeup(dev)) {
 		error = sysfs_merge_group(&client->dev.kobj,
@@ -1256,7 +1407,33 @@ static struct i2c_driver cyapa_driver = {
 	.id_table = cyapa_id_table,
 };
 
-module_i2c_driver(cyapa_driver);
+static int __init cyapa_init(void)
+{
+	int error;
+
+	/* Create a global debugfs root for all cyapa devices */
+	cyapa_debugfs_root = debugfs_create_dir("cyapa", NULL);
+	if (cyapa_debugfs_root == ERR_PTR(-ENODEV))
+		cyapa_debugfs_root = NULL;
+
+	error = i2c_add_driver(&cyapa_driver);
+	if (error) {
+		pr_err("cyapa driver register FAILED.\n");
+		return error;
+	}
+
+	return 0;
+}
+
+static void __exit cyapa_exit(void)
+{
+	debugfs_remove_recursive(cyapa_debugfs_root);
+
+	i2c_del_driver(&cyapa_driver);
+}
+
+module_init(cyapa_init);
+module_exit(cyapa_exit);
 
 MODULE_DESCRIPTION("Cypress APA I2C Trackpad Driver");
 MODULE_AUTHOR("Dudley Du <dudl@cypress.com>");
diff --git a/drivers/input/mouse/cyapa.h b/drivers/input/mouse/cyapa.h
index 0dc76d8..ceed843 100644
--- a/drivers/input/mouse/cyapa.h
+++ b/drivers/input/mouse/cyapa.h
@@ -186,6 +186,8 @@ struct cyapa_dev_ops {
 	ssize_t (*calibrate_store)(struct device *,
 			struct device_attribute *, const char *, size_t);
 
+	int (*read_fw)(struct cyapa *);
+
 	int (*initialize)(struct cyapa *cyapa);
 
 	int (*state_parse)(struct cyapa *cyapa, u8 *reg_status, int len);
@@ -298,6 +300,14 @@ struct cyapa {
 	 */
 	struct mutex state_sync_lock;
 
+	/* Per-instance debugfs root */
+	struct dentry *dentry_dev;
+
+	/* Buffer to store firmware read using debugfs */
+	struct mutex debugfs_mutex;
+	u8 *fw_image;
+	size_t fw_image_size;
+
 	const struct cyapa_dev_ops *ops;
 
 	union cyapa_cmd_states cmd_states;
-- 
1.9.1


  parent reply	other threads:[~2014-11-19  8:41 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-19  8:37 [PATCH v11 00/19] input: cyapa: instruction of cyapa patches Dudley Du
2014-11-19  8:37 ` [PATCH v11 01/19] input: cyapa: modify code to following kernel code style Dudley Du
2014-11-19  8:37 ` [PATCH v11 02/19] input: cyapa: add device resource management infrastructure support Dudley Du
2014-11-19  8:37 ` [PATCH v11 03/19] input: cyapa: re-design driver to support multi-trackpad in one driver Dudley Du
2014-11-19  8:37 ` [PATCH v11 04/19] input: cyapa: add gen5 trackpad device basic functions support Dudley Du
2014-11-19  8:37 ` [PATCH v11 05/19] input: cyapa: add power management interfaces supported for the device Dudley Du
2014-11-19  8:37 ` [PATCH v11 06/19] input: cyapa: add runtime " Dudley Du
2014-11-19  8:37 ` [PATCH v11 07/19] input: cyapa: add sysfs interfaces supported in the cyapa driver Dudley Du
2014-11-19  8:37 ` [PATCH v11 08/19] input: cyapa: add gen3 trackpad device firmware update function support Dudley Du
2014-11-19  8:37 ` [PATCH v11 09/19] input: cyapa: add gen3 trackpad device read baseline " Dudley Du
2014-11-19  8:37 ` [PATCH v11 10/19] input: cyapa: add gen3 trackpad device force re-calibrate " Dudley Du
2014-11-19  8:37 ` [PATCH v11 11/19] input: cyapa: add gen5 trackpad device firmware update " Dudley Du
2014-11-19  8:37 ` [PATCH v11 12/19] input: cyapa: add gen5 trackpad device read baseline " Dudley Du
2014-11-19  8:37 ` [PATCH v11 13/19] input: cyapa: add gen5 trackpad device force re-calibrate " Dudley Du
2014-11-19  8:37 ` Dudley Du [this message]
2014-11-19  8:37 ` [PATCH v11 15/19] input: cyapa: add gen3 trackpad device read firmware image " Dudley Du
2014-11-19  8:37 ` [PATCH v11 16/19] input: cyapa: add gen5 " Dudley Du
2014-11-19  8:37 ` [PATCH v11 17/19] input: cyapa: add read sensors raw data debugfs interface support Dudley Du
2014-11-19  8:37 ` [PATCH v11 18/19] input: cyapa: add gen5 trackpad device read raw data function support Dudley Du
2014-11-19  8:37 ` [PATCH v11 19/19] input: cyapa: add acpi device id supported Dudley Du
2014-11-21  8:56 ` [PATCH v11 00/19] input: cyapa: instruction of cyapa patches Jeremiah Mahler
2014-11-24  3:06   ` Dudley Du
2014-11-24  8:50     ` Jeremiah Mahler
2014-11-25 10:07       ` [BUG] [PATCH] next: cyapa: fix inop touchpad after resume on Acer C720 Jeremiah Mahler
2014-11-26  6:01         ` Dudley Du
2014-11-26 19:59           ` Jeremiah Mahler
2014-11-26  6:16         ` Dudley Du
2014-11-26 20:02           ` Jeremiah Mahler
2014-11-27  5:45             ` Dudley Du
2014-11-27  9:05               ` Jeremiah Mahler
2014-11-27 18:16               ` Dmitry Torokhov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1416386271-28167-15-git-send-email-dudley.dulixin@gmail.com \
    --to=dudley.dulixin@gmail.com \
    --cc=bleung@google.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rydberg@euromail.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®