blob: 552763bb3d4cacc959912a63982f3c345e1fa027 [file] [log] [blame]
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +01001/*
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>
Jonathan Cameron1f785682011-05-18 14:42:11 +010012#include <linux/list.h>
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +010013
Jonathan Cameron06458e22012-04-25 15:54:58 +010014#include <linux/iio/iio.h>
15#include <linux/iio/trigger.h>
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +010016
Jonathan Cameron1f785682011-05-18 14:42:11 +010017struct iio_sysfs_trig {
18 struct iio_trigger *trig;
19 int id;
20 struct list_head l;
21};
22
23static LIST_HEAD(iio_sysfs_trig_list);
24static DEFINE_MUTEX(iio_syfs_trig_list_mut);
25
26static int iio_sysfs_trigger_probe(int id);
27static 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}
43static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
44
45static int iio_sysfs_trigger_remove(int id);
46static 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
63static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
64
65static struct attribute *iio_sysfs_trig_attrs[] = {
66 &dev_attr_add_trigger.attr,
67 &dev_attr_remove_trigger.attr,
68 NULL,
69};
70
71static const struct attribute_group iio_sysfs_trig_group = {
72 .attrs = iio_sysfs_trig_attrs,
73};
74
75static const struct attribute_group *iio_sysfs_trig_groups[] = {
76 &iio_sysfs_trig_group,
77 NULL
78};
79
Jonathan Cameron9c0c22b2011-08-24 17:28:35 +010080
81/* Nothing to actually do upon release */
82static void iio_trigger_sysfs_release(struct device *dev)
83{
84}
85
Jonathan Cameron1f785682011-05-18 14:42:11 +010086static struct device iio_sysfs_trig_dev = {
87 .bus = &iio_bus_type,
88 .groups = iio_sysfs_trig_groups,
Jonathan Cameron9c0c22b2011-08-24 17:28:35 +010089 .release = &iio_trigger_sysfs_release,
Jonathan Cameron1f785682011-05-18 14:42:11 +010090};
91
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +010092static ssize_t iio_sysfs_trigger_poll(struct device *dev,
93 struct device_attribute *attr, const char *buf, size_t count)
94{
95 struct iio_trigger *trig = dev_get_drvdata(dev);
Jonathan Cameron1f785682011-05-18 14:42:11 +010096 iio_trigger_poll_chained(trig, 0);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +010097
98 return count;
99}
100
101static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100102
103static struct attribute *iio_sysfs_trigger_attrs[] = {
104 &dev_attr_trigger_now.attr,
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100105 NULL,
106};
107
108static const struct attribute_group iio_sysfs_trigger_attr_group = {
109 .attrs = iio_sysfs_trigger_attrs,
110};
111
Jonathan Cameron59c85e82011-05-18 14:42:22 +0100112static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
113 &iio_sysfs_trigger_attr_group,
114 NULL
115};
116
Jonathan Camerond29f73d2011-08-12 17:08:38 +0100117static const struct iio_trigger_ops iio_sysfs_trigger_ops = {
118 .owner = THIS_MODULE,
119};
120
Jonathan Cameron1f785682011-05-18 14:42:11 +0100121static int iio_sysfs_trigger_probe(int id)
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100122{
Jonathan Cameron1f785682011-05-18 14:42:11 +0100123 struct iio_sysfs_trig *t;
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100124 int ret;
Jonathan Cameron1f785682011-05-18 14:42:11 +0100125 bool foundit = false;
126 mutex_lock(&iio_syfs_trig_list_mut);
127 list_for_each_entry(t, &iio_sysfs_trig_list, l)
128 if (id == t->id) {
129 foundit = true;
130 break;
131 }
132 if (foundit) {
133 ret = -EINVAL;
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100134 goto out1;
135 }
Jonathan Cameron1f785682011-05-18 14:42:11 +0100136 t = kmalloc(sizeof(*t), GFP_KERNEL);
137 if (t == NULL) {
138 ret = -ENOMEM;
Jonathan Cameron59c85e82011-05-18 14:42:22 +0100139 goto out1;
Jonathan Cameron1f785682011-05-18 14:42:11 +0100140 }
141 t->id = id;
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200142 t->trig = iio_trigger_alloc("sysfstrig%d", id);
Jonathan Cameron1f785682011-05-18 14:42:11 +0100143 if (!t->trig) {
144 ret = -ENOMEM;
145 goto free_t;
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100146 }
147
Jonathan Cameron59c85e82011-05-18 14:42:22 +0100148 t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
Jonathan Camerond29f73d2011-08-12 17:08:38 +0100149 t->trig->ops = &iio_sysfs_trigger_ops;
Jonathan Cameron1f785682011-05-18 14:42:11 +0100150 t->trig->dev.parent = &iio_sysfs_trig_dev;
151
152 ret = iio_trigger_register(t->trig);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100153 if (ret)
Jonathan Cameron1f785682011-05-18 14:42:11 +0100154 goto out2;
155 list_add(&t->l, &iio_sysfs_trig_list);
156 __module_get(THIS_MODULE);
157 mutex_unlock(&iio_syfs_trig_list_mut);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100158 return 0;
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100159
Jonathan Cameron1f785682011-05-18 14:42:11 +0100160out2:
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200161 iio_trigger_put(t->trig);
Jonathan Cameron1f785682011-05-18 14:42:11 +0100162free_t:
163 kfree(t);
Jonathan Cameron1f785682011-05-18 14:42:11 +0100164out1:
165 mutex_unlock(&iio_syfs_trig_list_mut);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100166 return ret;
167}
168
Jonathan Cameron1f785682011-05-18 14:42:11 +0100169static int iio_sysfs_trigger_remove(int id)
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100170{
Jonathan Cameron1f785682011-05-18 14:42:11 +0100171 bool foundit = false;
172 struct iio_sysfs_trig *t;
173 mutex_lock(&iio_syfs_trig_list_mut);
174 list_for_each_entry(t, &iio_sysfs_trig_list, l)
175 if (id == t->id) {
176 foundit = true;
177 break;
178 }
179 if (!foundit) {
180 mutex_unlock(&iio_syfs_trig_list_mut);
181 return -EINVAL;
182 }
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100183
Jonathan Cameron1f785682011-05-18 14:42:11 +0100184 iio_trigger_unregister(t->trig);
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +0200185 iio_trigger_free(t->trig);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100186
Jonathan Cameron1f785682011-05-18 14:42:11 +0100187 list_del(&t->l);
188 kfree(t);
189 module_put(THIS_MODULE);
190 mutex_unlock(&iio_syfs_trig_list_mut);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100191 return 0;
192}
193
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100194
195static int __init iio_sysfs_trig_init(void)
196{
Jonathan Cameron1f785682011-05-18 14:42:11 +0100197 device_initialize(&iio_sysfs_trig_dev);
198 dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
199 return device_add(&iio_sysfs_trig_dev);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100200}
201module_init(iio_sysfs_trig_init);
202
203static void __exit iio_sysfs_trig_exit(void)
204{
Jonathan Cameron1f785682011-05-18 14:42:11 +0100205 device_unregister(&iio_sysfs_trig_dev);
Michael Hennerichf9a7e9b2011-02-07 11:05:46 +0100206}
207module_exit(iio_sysfs_trig_exit);
208
209MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
210MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
211MODULE_LICENSE("GPL v2");
212MODULE_ALIAS("platform:iio-trig-sysfs");