]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/iio/trigger/iio-trig-sysfs.c
staging:iio:trigger handle name attr in core, remove old alloc and register any contr...
[karo-tx-linux.git] / drivers / staging / iio / trigger / iio-trig-sysfs.c
1 /*
2  * Copyright 2011 Analog Devices Inc.
3  *
4  * Licensed under the GPL-2.
5  *
6  */
7
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>
13
14 #include "../iio.h"
15 #include "../trigger.h"
16
17 struct iio_sysfs_trig {
18         struct iio_trigger *trig;
19         int id;
20         struct list_head l;
21 };
22
23 static LIST_HEAD(iio_sysfs_trig_list);
24 static DEFINE_MUTEX(iio_syfs_trig_list_mut);
25
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)
31 {
32         int ret;
33         unsigned long input;
34
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;
42 }
43 static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
44
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)
50 {
51         int ret;
52         unsigned long input;
53
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;
61 }
62
63 static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
64
65 static struct attribute *iio_sysfs_trig_attrs[] = {
66         &dev_attr_add_trigger.attr,
67         &dev_attr_remove_trigger.attr,
68         NULL,
69 };
70
71 static const struct attribute_group iio_sysfs_trig_group = {
72         .attrs = iio_sysfs_trig_attrs,
73 };
74
75 static const struct attribute_group *iio_sysfs_trig_groups[] = {
76         &iio_sysfs_trig_group,
77         NULL
78 };
79
80 static struct device iio_sysfs_trig_dev = {
81         .bus = &iio_bus_type,
82         .groups = iio_sysfs_trig_groups,
83 };
84
85 static ssize_t iio_sysfs_trigger_poll(struct device *dev,
86                 struct device_attribute *attr, const char *buf, size_t count)
87 {
88         struct iio_trigger *trig = dev_get_drvdata(dev);
89         iio_trigger_poll_chained(trig, 0);
90
91         return count;
92 }
93
94 static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
95
96 static struct attribute *iio_sysfs_trigger_attrs[] = {
97         &dev_attr_trigger_now.attr,
98         NULL,
99 };
100
101 static const struct attribute_group iio_sysfs_trigger_attr_group = {
102         .attrs = iio_sysfs_trigger_attrs,
103 };
104
105 static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
106         &iio_sysfs_trigger_attr_group,
107         NULL
108 };
109
110 static int iio_sysfs_trigger_probe(int id)
111 {
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;
120                 }
121         if (foundit) {
122                 ret = -EINVAL;
123                 goto out1;
124         }
125         t = kmalloc(sizeof(*t), GFP_KERNEL);
126         if (t == NULL) {
127                 ret = -ENOMEM;
128                 goto out1;
129         }
130         t->id = id;
131         t->trig = iio_allocate_trigger("sysfstrig%d", id);
132         if (!t->trig) {
133                 ret = -ENOMEM;
134                 goto free_t;
135         }
136
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;
140
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;
148
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;
156 }
157
158 static int iio_sysfs_trigger_remove(int id)
159 {
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;
167                 }
168         if (!foundit) {
169                 mutex_unlock(&iio_syfs_trig_list_mut);
170                 return -EINVAL;
171         }
172
173         iio_trigger_unregister(t->trig);
174         iio_free_trigger(t->trig);
175
176         list_del(&t->l);
177         kfree(t);
178         module_put(THIS_MODULE);
179         mutex_unlock(&iio_syfs_trig_list_mut);
180         return 0;
181 }
182
183
184 static int __init iio_sysfs_trig_init(void)
185 {
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);
189 }
190 module_init(iio_sysfs_trig_init);
191
192 static void __exit iio_sysfs_trig_exit(void)
193 {
194         device_unregister(&iio_sysfs_trig_dev);
195 }
196 module_exit(iio_sysfs_trig_exit);
197
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");