diff options
| author | Shantanu Jain <shjain@codeaurora.org> | 2016-03-17 16:36:09 +0530 |
|---|---|---|
| committer | Abinaya P <abinayap@codeaurora.org> | 2016-08-24 16:23:20 +0530 |
| commit | 52344fa3c6a2de9d51313ca07e4ad166f3b6bdcf (patch) | |
| tree | 11583bd0d5c3e9a9163e02191149f0ec3032e57a | |
| parent | 930440dc319d1e37c2ab7e76c5880b0d9f1b3c61 (diff) | |
input: synaptics_dsx_2.6: creation of secure touch sysfs ifiles
This patch creates two sysfs files for secure touch - secure_touch
and secure_touch_enable, which will be accessed by secure UI app.
We also define the store and show function for these sysfs files.
Change-Id: Id43118120d4a1f0682904f48b3584d3ba62ef1dd
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
3 files changed, 178 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c index 4b15935b2d4c..3334d73f0fd7 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c @@ -172,6 +172,19 @@ static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) +static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev, + struct device_attribute *attr, char *buf); +#endif + +static irqreturn_t synaptics_rmi4_irq(int irq, void *data); + struct synaptics_rmi4_f01_device_status { union { struct { @@ -617,6 +630,14 @@ static struct device_attribute attrs[] = { __ATTR(wake_gesture, (S_IRUGO | S_IWUSR | S_IWGRP), synaptics_rmi4_wake_gesture_show, synaptics_rmi4_wake_gesture_store), +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) + __ATTR(secure_touch_enable, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_secure_touch_enable_show, + synaptics_rmi4_secure_touch_enable_store), + __ATTR(secure_touch, S_IRUGO, + synaptics_rmi4_secure_touch_show, + NULL), +#endif }; static struct kobj_attribute virtual_key_map_attr = { @@ -688,6 +709,121 @@ static void synaptics_secure_touch_stop(struct synaptics_rmi4_data *rmi4_data, } #endif +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) +static ssize_t synaptics_rmi4_secure_touch_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d", + atomic_read(&rmi4_data->st_enabled)); +} +/* + * Accept only "0" and "1" valid values. + * "0" will reset the st_enabled flag, then wake up the reading process and + * the interrupt handler. + * The bus driver is notified via pm_runtime that it is not required to stay + * awake anymore. + * It will also make sure the queue of events is emptied in the controller, + * in case a touch happened in between the secure touch being disabled and + * the local ISR being ungated. + * "1" will set the st_enabled flag and clear the st_pending_irqs flag. + * The bus driver is requested via pm_runtime to stay awake. + */ +static ssize_t synaptics_rmi4_secure_touch_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned long value; + int err = 0; + + if (count > 2) + return -EINVAL; + + err = kstrtoul(buf, 10, &value); + if (err != 0) + return err; + + err = count; + + switch (value) { + case 0: + if (atomic_read(&rmi4_data->st_enabled) == 0) + break; + + synaptics_rmi4_bus_put(rmi4_data); + atomic_set(&rmi4_data->st_enabled, 0); + synaptics_secure_touch_notify(rmi4_data); + complete(&rmi4_data->st_irq_processed); + synaptics_rmi4_irq(rmi4_data->irq, rmi4_data); + complete(&rmi4_data->st_powerdown); + + break; + case 1: + if (atomic_read(&rmi4_data->st_enabled)) { + err = -EBUSY; + break; + } + + synchronize_irq(rmi4_data->irq); + + if (synaptics_rmi4_bus_get(rmi4_data) < 0) { + dev_err( + rmi4_data->pdev->dev.parent, + "synaptics_rmi4_bus_get failed\n"); + err = -EIO; + break; + } + reinit_completion(&rmi4_data->st_powerdown); + reinit_completion(&rmi4_data->st_irq_processed); + atomic_set(&rmi4_data->st_enabled, 1); + atomic_set(&rmi4_data->st_pending_irqs, 0); + break; + default: + dev_err( + rmi4_data->pdev->dev.parent, + "unsupported value: %lu\n", value); + err = -EINVAL; + break; + } + return err; +} + +/* + * This function returns whether there are pending interrupts, or + * other error conditions that need to be signaled to the userspace library, + * according tot he following logic: + * - st_enabled is 0 if secure touch is not enabled, returning -EBADF + * - st_pending_irqs is -1 to signal that secure touch is in being stopped, + * returning -EINVAL + * - st_pending_irqs is 1 to signal that there is a pending irq, returning + * the value "1" to the sysfs read operation + * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt + * has been processed, so the interrupt handler can be allowed to continue. + */ +static ssize_t synaptics_rmi4_secure_touch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + int val = 0; + + if (atomic_read(&rmi4_data->st_enabled) == 0) + return -EBADF; + + if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, -1, 0) == -1) + return -EINVAL; + + if (atomic_cmpxchg(&rmi4_data->st_pending_irqs, 1, 0) == 1) + val = 1; + else + complete(&rmi4_data->st_irq_processed); + + return scnprintf(buf, PAGE_SIZE, "%u", val); + +} +#endif + static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h index 0bab0c233a12..f0d8c124bac6 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h @@ -394,6 +394,10 @@ struct synaptics_dsx_bus_access { unsigned char *data, unsigned short length); int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, unsigned char *data, unsigned short length); +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) + int (*get)(struct synaptics_rmi4_data *rmi4_data); + void (*put)(struct synaptics_rmi4_data *rmi4_data); +#endif }; struct synaptics_dsx_hw_interface { @@ -444,6 +448,17 @@ static inline int synaptics_rmi4_reg_write( return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len); } +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) +static inline int synaptics_rmi4_bus_get(struct synaptics_rmi4_data *rmi4_data) +{ + return rmi4_data->hw_if->bus_access->get(rmi4_data); +} +static inline void synaptics_rmi4_bus_put(struct synaptics_rmi4_data *rmi4_data) +{ + rmi4_data->hw_if->bus_access->put(rmi4_data); +} +#endif + static inline ssize_t synaptics_rmi4_show_error(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c index 784de607aa08..56c5d5e1b9f2 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c @@ -497,10 +497,37 @@ exit: return retval; } +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) +static int synaptics_rmi4_i2c_get(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + retval = pm_runtime_get_sync(i2c->adapter->dev.parent); + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static void synaptics_rmi4_i2c_put(struct synaptics_rmi4_data *rmi4_data) +{ + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + pm_runtime_put_sync(i2c->adapter->dev.parent); + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); +} +#endif + static struct synaptics_dsx_bus_access bus_access = { .type = BUS_I2C, .read = synaptics_rmi4_i2c_read, .write = synaptics_rmi4_i2c_write, +#if defined(CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26) + .get = synaptics_rmi4_i2c_get, + .put = synaptics_rmi4_i2c_put, +#endif }; static void synaptics_rmi4_i2c_dev_release(struct device *dev) |
