staging:iio:trigger handle name attr in core, remove old alloc and register any contr...
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / iio / trigger / iio-trig-sysfs.c
blob47248cd1fa0d6e91df443cf14c90acf31f710de2
1 /*
2 * Copyright 2011 Analog Devices Inc.
4 * Licensed under the GPL-2.
6 */
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 #include <linux/list.h>
14 #include "../iio.h"
15 #include "../trigger.h"
17 struct iio_sysfs_trig {
18 struct iio_trigger *trig;
19 int id;
20 struct list_head l;
23 static LIST_HEAD(iio_sysfs_trig_list);
24 static DEFINE_MUTEX(iio_syfs_trig_list_mut);
26 static int iio_sysfs_trigger_probe(int id);
27 static ssize_t iio_sysfs_trig_add(struct device *dev,
28 struct device_attribute *attr,
29 const char *buf,
30 size_t len)
32 int ret;
33 unsigned long input;
35 ret = strict_strtoul(buf, 10, &input);
36 if (ret)
37 return ret;
38 ret = iio_sysfs_trigger_probe(input);
39 if (ret)
40 return ret;
41 return len;
43 static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
45 static int iio_sysfs_trigger_remove(int id);
46 static ssize_t iio_sysfs_trig_remove(struct device *dev,
47 struct device_attribute *attr,
48 const char *buf,
49 size_t len)
51 int ret;
52 unsigned long input;
54 ret = strict_strtoul(buf, 10, &input);
55 if (ret)
56 return ret;
57 ret = iio_sysfs_trigger_remove(input);
58 if (ret)
59 return ret;
60 return len;
63 static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
65 static struct attribute *iio_sysfs_trig_attrs[] = {
66 &dev_attr_add_trigger.attr,
67 &dev_attr_remove_trigger.attr,
68 NULL,
71 static const struct attribute_group iio_sysfs_trig_group = {
72 .attrs = iio_sysfs_trig_attrs,
75 static const struct attribute_group *iio_sysfs_trig_groups[] = {
76 &iio_sysfs_trig_group,
77 NULL
80 static struct device iio_sysfs_trig_dev = {
81 .bus = &iio_bus_type,
82 .groups = iio_sysfs_trig_groups,
85 static ssize_t iio_sysfs_trigger_poll(struct device *dev,
86 struct device_attribute *attr, const char *buf, size_t count)
88 struct iio_trigger *trig = dev_get_drvdata(dev);
89 iio_trigger_poll_chained(trig, 0);
91 return count;
94 static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
96 static struct attribute *iio_sysfs_trigger_attrs[] = {
97 &dev_attr_trigger_now.attr,
98 NULL,
101 static const struct attribute_group iio_sysfs_trigger_attr_group = {
102 .attrs = iio_sysfs_trigger_attrs,
105 static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
106 &iio_sysfs_trigger_attr_group,
107 NULL
110 static int iio_sysfs_trigger_probe(int id)
112 struct iio_sysfs_trig *t;
113 int ret;
114 bool foundit = false;
115 mutex_lock(&iio_syfs_trig_list_mut);
116 list_for_each_entry(t, &iio_sysfs_trig_list, l)
117 if (id == t->id) {
118 foundit = true;
119 break;
121 if (foundit) {
122 ret = -EINVAL;
123 goto out1;
125 t = kmalloc(sizeof(*t), GFP_KERNEL);
126 if (t == NULL) {
127 ret = -ENOMEM;
128 goto out1;
130 t->id = id;
131 t->trig = iio_allocate_trigger("sysfstrig%d", id);
132 if (!t->trig) {
133 ret = -ENOMEM;
134 goto free_t;
137 t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
138 t->trig->owner = THIS_MODULE;
139 t->trig->dev.parent = &iio_sysfs_trig_dev;
141 ret = iio_trigger_register(t->trig);
142 if (ret)
143 goto out2;
144 list_add(&t->l, &iio_sysfs_trig_list);
145 __module_get(THIS_MODULE);
146 mutex_unlock(&iio_syfs_trig_list_mut);
147 return 0;
149 out2:
150 iio_put_trigger(t->trig);
151 free_t:
152 kfree(t);
153 out1:
154 mutex_unlock(&iio_syfs_trig_list_mut);
155 return ret;
158 static int iio_sysfs_trigger_remove(int id)
160 bool foundit = false;
161 struct iio_sysfs_trig *t;
162 mutex_lock(&iio_syfs_trig_list_mut);
163 list_for_each_entry(t, &iio_sysfs_trig_list, l)
164 if (id == t->id) {
165 foundit = true;
166 break;
168 if (!foundit) {
169 mutex_unlock(&iio_syfs_trig_list_mut);
170 return -EINVAL;
173 iio_trigger_unregister(t->trig);
174 iio_free_trigger(t->trig);
176 list_del(&t->l);
177 kfree(t);
178 module_put(THIS_MODULE);
179 mutex_unlock(&iio_syfs_trig_list_mut);
180 return 0;
184 static int __init iio_sysfs_trig_init(void)
186 device_initialize(&iio_sysfs_trig_dev);
187 dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
188 return device_add(&iio_sysfs_trig_dev);
190 module_init(iio_sysfs_trig_init);
192 static void __exit iio_sysfs_trig_exit(void)
194 device_unregister(&iio_sysfs_trig_dev);
196 module_exit(iio_sysfs_trig_exit);
198 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
199 MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
200 MODULE_LICENSE("GPL v2");
201 MODULE_ALIAS("platform:iio-trig-sysfs");