From 70ccdbb6c772d5ae7ae63f0fa5b2ac29b8d433e0 Mon Sep 17 00:00:00 2001
From: Du, Dudley <dudl@cypress.com>
Date: Thu, 25 Aug 2011 16:39:02 +0800
Subject: [PATCH 2/4] input:cyapa: add sysfs interface supported

Add interfaces for reading touchpad device driver version,
firmware version, product id, hardware version and protocol
through sysfs system.

BUG=
TEST=test on tegra2 seaboard platform with below commands:
cat /sys/bus/i2c/devices/0-0067/firmware_version
cat /sys/bus/i2c/devices/0-0067/product_id
cat /sys/bus/i2c/devices/0-0067/driver_version
cat /sys/bus/i2c/devices/0-0067/hardware_version
cat /sys/bus/i2c/devices/0-0067/protocol_version

Signed-off-by: Du, Dudley <dudl@cypress.com>
---
 drivers/input/mouse/cypress_i2c.c |   95 +++++++++++++++++++++++++++++++++++++
 1 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/drivers/input/mouse/cypress_i2c.c b/drivers/input/mouse/cypress_i2c.c
index 61d5f7f..7240632 100644
--- a/drivers/input/mouse/cypress_i2c.c
+++ b/drivers/input/mouse/cypress_i2c.c
@@ -649,6 +649,95 @@ static void cyapa_update_firmware_dispatch(struct cyapa_i2c *touch)
 }
 
 /*
+ *******************************************************************
+ * below routines export interfaces to sysfs file system.
+ * so user can get firmware/driver/hardware information using cat command.
+ * e.g.: use below command to get firmware version
+ *      cat /sys/devices/platfrom/tegra-i2c.0/i2c-0/0-0067/firmware_version
+ *******************************************************************
+ */
+ssize_t cyapa_show_fm_ver(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyapa_i2c *touch = i2c_get_clientdata(client);
+
+	ret = cyapa_get_query_data(touch);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d.%d\n", touch->fw_maj_ver, touch->fw_min_ver);
+}
+
+ssize_t cyapa_show_driver_ver(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d.%d.%d\n",
+		CYAPA_MAJOR_VER, CYAPA_MINOR_VER, CYAPA_REVISION_VER);
+}
+
+ssize_t cyapa_show_hw_ver(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyapa_i2c *touch = i2c_get_clientdata(client);
+
+	ret = cyapa_get_query_data(touch);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d.%d\n", touch->hw_maj_ver, touch->hw_min_ver);
+}
+
+ssize_t cyapa_show_product_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyapa_i2c *touch = i2c_get_clientdata(client);
+
+	ret = cyapa_get_query_data(touch);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%s\n", touch->product_id);
+}
+
+ssize_t cyapa_show_protocol_version(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cyapa_i2c *touch = i2c_get_clientdata(client);
+
+	if (cyapa_determine_firmware_gen(touch) < 0)
+		return -EINVAL;
+	cyapa_get_reg_offset(touch);
+
+	return sprintf(buf, "%d\n", touch->pdata->gen);
+}
+
+static DEVICE_ATTR(firmware_version, S_IRUGO, cyapa_show_fm_ver, NULL);
+static DEVICE_ATTR(driver_version, S_IRUGO, cyapa_show_driver_ver, NULL);
+static DEVICE_ATTR(hardware_version, S_IRUGO, cyapa_show_hw_ver, NULL);
+static DEVICE_ATTR(product_id, S_IRUGO, cyapa_show_product_id, NULL);
+static DEVICE_ATTR(protocol_version, S_IRUGO, cyapa_show_protocol_version, NULL);
+
+static struct attribute *cyapa_sysfs_entries[] = {
+	&dev_attr_firmware_version.attr,
+	&dev_attr_driver_version.attr,
+	&dev_attr_hardware_version.attr,
+	&dev_attr_product_id.attr,
+	&dev_attr_protocol_version.attr,
+	NULL,
+};
+
+static struct attribute_group cyapa_sysfs_group = {
+	.attrs = cyapa_sysfs_entries,
+};
+
+/*
  **************************************************************
  * Cypress i2c trackpad input device driver.
  **************************************************************
@@ -1431,6 +1520,10 @@ static void cyapa_probe_detect_work_handler(struct work_struct *work)
 
 	i2c_set_clientdata(client, touch);
 
+	ret = sysfs_create_group(&client->dev.kobj, &cyapa_sysfs_group);
+	if (ret)
+		pr_warning("error creating sysfs entries.\n");
+
 	spin_lock_irqsave(&touch->miscdev_spinlock, flags);
 	touch->detect_status = CYAPA_DETECT_DONE_SUCCESS;
 	if (touch->irq_enabled)
@@ -1589,6 +1682,8 @@ static int __devexit cyapa_i2c_remove(struct i2c_client *client)
 {
 	struct cyapa_i2c *touch = i2c_get_clientdata(client);
 
+	sysfs_remove_group(&client->dev.kobj, &cyapa_sysfs_group);
+
 	cancel_delayed_work_sync(&touch->dwork);
 
 	if (!touch->polling_mode_enabled) {
-- 
1.7.5.1

