diff --git a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c index 2929b1af7d87..6079f1ebd8cd 100755 --- a/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c +++ b/drivers/input/touchscreen/focaltech_0flash_mmi/focaltech_ex_fun.c @@ -1123,6 +1123,108 @@ static struct attribute_group fts_attribute_group = { .attrs = fts_attributes }; +#include +#include + +/* Attribute: path (RO) */ +static ssize_t path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_data *data = dev_get_drvdata(dev); + ssize_t blen; + const char *path; + + if (!data) { + pr_err("cannot get fts_ts_data pointer\n"); + return (ssize_t)0; + } + path = kobject_get_path(&data->spi->dev.kobj, GFP_KERNEL); + blen = scnprintf(buf, PAGE_SIZE, "%s", path ? path : "na"); + kfree(path); + return blen; +} + +/* Attribute: vendor (RO) */ +static ssize_t vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "focaltech"); +} + +static struct device_attribute touchscreen_attributes[] = { + __ATTR_RO(path), + __ATTR_RO(vendor), + __ATTR_NULL +}; + +#define TSDEV_MINOR_BASE 128 +#define TSDEV_MINOR_MAX 32 + +static int fts_sysfs_class(void *_data, bool create) +{ + struct fts_ts_data *data = _data; + struct device_attribute *attrs = touchscreen_attributes; + int i, error = 0; + static struct class *touchscreen_class; + static struct device *ts_class_dev; + static int minor; + + if (create) { + minor = input_get_new_minor(data->spi->chip_select, + 1, false); + if (minor < 0) + minor = input_get_new_minor(TSDEV_MINOR_BASE, + TSDEV_MINOR_MAX, true); + pr_info("assigned minor %d\n", minor); + + touchscreen_class = class_create(THIS_MODULE, "touchscreen"); + if (IS_ERR(touchscreen_class)) { + error = PTR_ERR(touchscreen_class); + touchscreen_class = NULL; + return error; + } + + ts_class_dev = device_create(touchscreen_class, NULL, + MKDEV(INPUT_MAJOR, minor), + data, FTS_CHIP_NAME); + if (IS_ERR(ts_class_dev)) { + error = PTR_ERR(ts_class_dev); + ts_class_dev = NULL; + return error; + } + + for (i = 0; attrs[i].attr.name != NULL; ++i) { + error = device_create_file(ts_class_dev, &attrs[i]); + if (error) + break; + } + + if (error) + goto device_destroy; + } else { + if (!touchscreen_class || !ts_class_dev) + return -ENODEV; + + for (i = 0; attrs[i].attr.name != NULL; ++i) + device_remove_file(ts_class_dev, &attrs[i]); + + device_unregister(ts_class_dev); + class_unregister(touchscreen_class); + } + + return 0; + +device_destroy: + for (--i; i >= 0; --i) + device_remove_file(ts_class_dev, &attrs[i]); + device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor)); + ts_class_dev = NULL; + class_unregister(touchscreen_class); + pr_err("error creating touchscreen class\n"); + + return -ENODEV; +} + int fts_create_sysfs(struct fts_ts_data *ts_data) { int ret = 0; @@ -1132,9 +1234,14 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) FTS_ERROR("[EX]: sysfs_create_group() failed!!"); sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); return -ENOMEM; - } else { - FTS_INFO("[EX]: sysfs_create_group() succeeded!!"); } + ret = fts_sysfs_class(ts_data, true); + if (ret) { + FTS_ERROR("[EX]: fts_sysfs_class() failed!!"); + sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); + return -ENOMEM; + } + FTS_INFO("[EX]: sysfs_create_group() succeeded!!"); return ret; } @@ -1142,5 +1249,6 @@ int fts_create_sysfs(struct fts_ts_data *ts_data) int fts_remove_sysfs(struct fts_ts_data *ts_data) { sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group); + fts_sysfs_class(ts_data, false); return 0; }