|
@@ -9,15 +9,84 @@
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/slab.h>
|
|
|
+#include <linux/list.h>
|
|
|
|
|
|
#include "../iio.h"
|
|
|
#include "../trigger.h"
|
|
|
|
|
|
+struct iio_sysfs_trig {
|
|
|
+ struct iio_trigger *trig;
|
|
|
+ int id;
|
|
|
+ struct list_head l;
|
|
|
+};
|
|
|
+
|
|
|
+static LIST_HEAD(iio_sysfs_trig_list);
|
|
|
+static DEFINE_MUTEX(iio_syfs_trig_list_mut);
|
|
|
+
|
|
|
+static int iio_sysfs_trigger_probe(int id);
|
|
|
+static ssize_t iio_sysfs_trig_add(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ const char *buf,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ unsigned long input;
|
|
|
+
|
|
|
+ ret = strict_strtoul(buf, 10, &input);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ ret = iio_sysfs_trigger_probe(input);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ return len;
|
|
|
+}
|
|
|
+static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
|
|
|
+
|
|
|
+static int iio_sysfs_trigger_remove(int id);
|
|
|
+static ssize_t iio_sysfs_trig_remove(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ const char *buf,
|
|
|
+ size_t len)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ unsigned long input;
|
|
|
+
|
|
|
+ ret = strict_strtoul(buf, 10, &input);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ ret = iio_sysfs_trigger_remove(input);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
+static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
|
|
|
+
|
|
|
+static struct attribute *iio_sysfs_trig_attrs[] = {
|
|
|
+ &dev_attr_add_trigger.attr,
|
|
|
+ &dev_attr_remove_trigger.attr,
|
|
|
+ NULL,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct attribute_group iio_sysfs_trig_group = {
|
|
|
+ .attrs = iio_sysfs_trig_attrs,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct attribute_group *iio_sysfs_trig_groups[] = {
|
|
|
+ &iio_sysfs_trig_group,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+static struct device iio_sysfs_trig_dev = {
|
|
|
+ .bus = &iio_bus_type,
|
|
|
+ .groups = iio_sysfs_trig_groups,
|
|
|
+};
|
|
|
+
|
|
|
static ssize_t iio_sysfs_trigger_poll(struct device *dev,
|
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
|
{
|
|
|
struct iio_trigger *trig = dev_get_drvdata(dev);
|
|
|
- iio_trigger_poll(trig, 0);
|
|
|
+ iio_trigger_poll_chained(trig, 0);
|
|
|
|
|
|
return count;
|
|
|
}
|
|
@@ -35,70 +104,101 @@ static const struct attribute_group iio_sysfs_trigger_attr_group = {
|
|
|
.attrs = iio_sysfs_trigger_attrs,
|
|
|
};
|
|
|
|
|
|
-static int __devinit iio_sysfs_trigger_probe(struct platform_device *pdev)
|
|
|
+static int iio_sysfs_trigger_probe(int id)
|
|
|
{
|
|
|
- struct iio_trigger *trig;
|
|
|
+ struct iio_sysfs_trig *t;
|
|
|
int ret;
|
|
|
+ char *name;
|
|
|
+ bool foundit = false;
|
|
|
+ mutex_lock(&iio_syfs_trig_list_mut);
|
|
|
+ list_for_each_entry(t, &iio_sysfs_trig_list, l)
|
|
|
+ if (id == t->id) {
|
|
|
+ foundit = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (foundit) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out1;
|
|
|
+ }
|
|
|
|
|
|
- trig = iio_allocate_trigger();
|
|
|
- if (!trig) {
|
|
|
+ name = kasprintf(GFP_KERNEL, "sysfstrig%d", id);
|
|
|
+ if (name == NULL) {
|
|
|
ret = -ENOMEM;
|
|
|
goto out1;
|
|
|
}
|
|
|
-
|
|
|
- trig->control_attrs = &iio_sysfs_trigger_attr_group;
|
|
|
- trig->owner = THIS_MODULE;
|
|
|
- trig->name = kasprintf(GFP_KERNEL, "sysfstrig%d", pdev->id);
|
|
|
- if (trig->name == NULL) {
|
|
|
+ t = kmalloc(sizeof(*t), GFP_KERNEL);
|
|
|
+ if (t == NULL) {
|
|
|
ret = -ENOMEM;
|
|
|
- goto out2;
|
|
|
+ goto free_name;
|
|
|
+ }
|
|
|
+ t->id = id;
|
|
|
+ t->trig = iio_allocate_trigger_named(name);
|
|
|
+ if (!t->trig) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto free_t;
|
|
|
}
|
|
|
|
|
|
- ret = iio_trigger_register(trig);
|
|
|
- if (ret)
|
|
|
- goto out3;
|
|
|
-
|
|
|
- platform_set_drvdata(pdev, trig);
|
|
|
+ t->trig->control_attrs = &iio_sysfs_trigger_attr_group;
|
|
|
+ t->trig->owner = THIS_MODULE;
|
|
|
+ t->trig->dev.parent = &iio_sysfs_trig_dev;
|
|
|
|
|
|
+ ret = iio_trigger_register(t->trig);
|
|
|
+ if (ret)
|
|
|
+ goto out2;
|
|
|
+ list_add(&t->l, &iio_sysfs_trig_list);
|
|
|
+ __module_get(THIS_MODULE);
|
|
|
+ mutex_unlock(&iio_syfs_trig_list_mut);
|
|
|
return 0;
|
|
|
-out3:
|
|
|
- kfree(trig->name);
|
|
|
+
|
|
|
out2:
|
|
|
- iio_put_trigger(trig);
|
|
|
+ iio_put_trigger(t->trig);
|
|
|
+free_t:
|
|
|
+ kfree(t);
|
|
|
+free_name:
|
|
|
+ kfree(name);
|
|
|
out1:
|
|
|
-
|
|
|
+ mutex_unlock(&iio_syfs_trig_list_mut);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int __devexit iio_sysfs_trigger_remove(struct platform_device *pdev)
|
|
|
+static int iio_sysfs_trigger_remove(int id)
|
|
|
{
|
|
|
- struct iio_trigger *trig = platform_get_drvdata(pdev);
|
|
|
+ bool foundit = false;
|
|
|
+ struct iio_sysfs_trig *t;
|
|
|
+ mutex_lock(&iio_syfs_trig_list_mut);
|
|
|
+ list_for_each_entry(t, &iio_sysfs_trig_list, l)
|
|
|
+ if (id == t->id) {
|
|
|
+ foundit = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!foundit) {
|
|
|
+ mutex_unlock(&iio_syfs_trig_list_mut);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
- iio_trigger_unregister(trig);
|
|
|
- kfree(trig->name);
|
|
|
- iio_put_trigger(trig);
|
|
|
+ iio_trigger_unregister(t->trig);
|
|
|
+ kfree(t->trig->name);
|
|
|
+ iio_free_trigger(t->trig);
|
|
|
|
|
|
+ list_del(&t->l);
|
|
|
+ kfree(t);
|
|
|
+ module_put(THIS_MODULE);
|
|
|
+ mutex_unlock(&iio_syfs_trig_list_mut);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static struct platform_driver iio_sysfs_trigger_driver = {
|
|
|
- .driver = {
|
|
|
- .name = "iio_sysfs_trigger",
|
|
|
- .owner = THIS_MODULE,
|
|
|
- },
|
|
|
- .probe = iio_sysfs_trigger_probe,
|
|
|
- .remove = __devexit_p(iio_sysfs_trigger_remove),
|
|
|
-};
|
|
|
|
|
|
static int __init iio_sysfs_trig_init(void)
|
|
|
{
|
|
|
- return platform_driver_register(&iio_sysfs_trigger_driver);
|
|
|
+ device_initialize(&iio_sysfs_trig_dev);
|
|
|
+ dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
|
|
|
+ return device_add(&iio_sysfs_trig_dev);
|
|
|
}
|
|
|
module_init(iio_sysfs_trig_init);
|
|
|
|
|
|
static void __exit iio_sysfs_trig_exit(void)
|
|
|
{
|
|
|
- platform_driver_unregister(&iio_sysfs_trigger_driver);
|
|
|
+ device_unregister(&iio_sysfs_trig_dev);
|
|
|
}
|
|
|
module_exit(iio_sysfs_trig_exit);
|
|
|
|