]>
Commit | Line | Data |
---|---|---|
b662f809 DB |
1 | /* |
2 | * The Industrial I/O core, software trigger functions | |
3 | * | |
4 | * Copyright (c) 2015 Intel Corporation | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License version 2 as published by | |
8 | * the Free Software Foundation. | |
9 | */ | |
10 | ||
11 | #include <linux/module.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/kmod.h> | |
14 | #include <linux/list.h> | |
15 | #include <linux/slab.h> | |
16 | ||
17 | #include <linux/iio/sw_trigger.h> | |
8d6c16dd | 18 | #include <linux/iio/configfs.h> |
b662f809 DB |
19 | #include <linux/configfs.h> |
20 | ||
21 | static struct config_group *iio_triggers_group; | |
612a462a | 22 | static const struct config_item_type iio_trigger_type_group_type; |
b662f809 | 23 | |
612a462a | 24 | static const struct config_item_type iio_triggers_group_type = { |
b662f809 DB |
25 | .ct_owner = THIS_MODULE, |
26 | }; | |
27 | ||
28 | static LIST_HEAD(iio_trigger_types_list); | |
29 | static DEFINE_MUTEX(iio_trigger_types_lock); | |
30 | ||
31 | static | |
32 | struct iio_sw_trigger_type *__iio_find_sw_trigger_type(const char *name, | |
33 | unsigned len) | |
34 | { | |
35 | struct iio_sw_trigger_type *t = NULL, *iter; | |
36 | ||
37 | list_for_each_entry(iter, &iio_trigger_types_list, list) | |
38 | if (!strcmp(iter->name, name)) { | |
39 | t = iter; | |
40 | break; | |
41 | } | |
42 | ||
43 | return t; | |
44 | } | |
45 | ||
46 | int iio_register_sw_trigger_type(struct iio_sw_trigger_type *t) | |
47 | { | |
48 | struct iio_sw_trigger_type *iter; | |
49 | int ret = 0; | |
50 | ||
51 | mutex_lock(&iio_trigger_types_lock); | |
52 | iter = __iio_find_sw_trigger_type(t->name, strlen(t->name)); | |
53 | if (iter) | |
54 | ret = -EBUSY; | |
55 | else | |
56 | list_add_tail(&t->list, &iio_trigger_types_list); | |
57 | mutex_unlock(&iio_trigger_types_lock); | |
58 | ||
59 | if (ret) | |
60 | return ret; | |
61 | ||
62 | t->group = configfs_register_default_group(iio_triggers_group, t->name, | |
63 | &iio_trigger_type_group_type); | |
64 | if (IS_ERR(t->group)) | |
65 | ret = PTR_ERR(t->group); | |
66 | ||
67 | return ret; | |
68 | } | |
69 | EXPORT_SYMBOL(iio_register_sw_trigger_type); | |
70 | ||
71 | void iio_unregister_sw_trigger_type(struct iio_sw_trigger_type *t) | |
72 | { | |
73 | struct iio_sw_trigger_type *iter; | |
74 | ||
75 | mutex_lock(&iio_trigger_types_lock); | |
76 | iter = __iio_find_sw_trigger_type(t->name, strlen(t->name)); | |
77 | if (iter) | |
78 | list_del(&t->list); | |
79 | mutex_unlock(&iio_trigger_types_lock); | |
80 | ||
81 | configfs_unregister_default_group(t->group); | |
82 | } | |
83 | EXPORT_SYMBOL(iio_unregister_sw_trigger_type); | |
84 | ||
85 | static | |
86 | struct iio_sw_trigger_type *iio_get_sw_trigger_type(const char *name) | |
87 | { | |
88 | struct iio_sw_trigger_type *t; | |
89 | ||
90 | mutex_lock(&iio_trigger_types_lock); | |
91 | t = __iio_find_sw_trigger_type(name, strlen(name)); | |
92 | if (t && !try_module_get(t->owner)) | |
93 | t = NULL; | |
94 | mutex_unlock(&iio_trigger_types_lock); | |
95 | ||
96 | return t; | |
97 | } | |
98 | ||
99 | struct iio_sw_trigger *iio_sw_trigger_create(const char *type, const char *name) | |
100 | { | |
101 | struct iio_sw_trigger *t; | |
102 | struct iio_sw_trigger_type *tt; | |
103 | ||
104 | tt = iio_get_sw_trigger_type(type); | |
105 | if (!tt) { | |
106 | pr_err("Invalid trigger type: %s\n", type); | |
107 | return ERR_PTR(-EINVAL); | |
108 | } | |
109 | t = tt->ops->probe(name); | |
110 | if (IS_ERR(t)) | |
111 | goto out_module_put; | |
112 | ||
113 | t->trigger_type = tt; | |
114 | ||
115 | return t; | |
116 | out_module_put: | |
117 | module_put(tt->owner); | |
118 | return t; | |
119 | } | |
120 | EXPORT_SYMBOL(iio_sw_trigger_create); | |
121 | ||
122 | void iio_sw_trigger_destroy(struct iio_sw_trigger *t) | |
123 | { | |
124 | struct iio_sw_trigger_type *tt = t->trigger_type; | |
125 | ||
126 | tt->ops->remove(t); | |
127 | module_put(tt->owner); | |
128 | } | |
129 | EXPORT_SYMBOL(iio_sw_trigger_destroy); | |
130 | ||
131 | static struct config_group *trigger_make_group(struct config_group *group, | |
132 | const char *name) | |
133 | { | |
134 | struct iio_sw_trigger *t; | |
135 | ||
136 | t = iio_sw_trigger_create(group->cg_item.ci_name, name); | |
137 | if (IS_ERR(t)) | |
138 | return ERR_CAST(t); | |
139 | ||
140 | config_item_set_name(&t->group.cg_item, "%s", name); | |
141 | ||
142 | return &t->group; | |
143 | } | |
144 | ||
145 | static void trigger_drop_group(struct config_group *group, | |
146 | struct config_item *item) | |
147 | { | |
148 | struct iio_sw_trigger *t = to_iio_sw_trigger(item); | |
149 | ||
150 | iio_sw_trigger_destroy(t); | |
151 | config_item_put(item); | |
152 | } | |
153 | ||
154 | static struct configfs_group_operations trigger_ops = { | |
155 | .make_group = &trigger_make_group, | |
156 | .drop_item = &trigger_drop_group, | |
157 | }; | |
158 | ||
612a462a | 159 | static const struct config_item_type iio_trigger_type_group_type = { |
b662f809 DB |
160 | .ct_group_ops = &trigger_ops, |
161 | .ct_owner = THIS_MODULE, | |
162 | }; | |
163 | ||
164 | static int __init iio_sw_trigger_init(void) | |
165 | { | |
166 | iio_triggers_group = | |
167 | configfs_register_default_group(&iio_configfs_subsys.su_group, | |
168 | "triggers", | |
169 | &iio_triggers_group_type); | |
f9ed89e1 | 170 | return PTR_ERR_OR_ZERO(iio_triggers_group); |
b662f809 DB |
171 | } |
172 | module_init(iio_sw_trigger_init); | |
173 | ||
174 | static void __exit iio_sw_trigger_exit(void) | |
175 | { | |
176 | configfs_unregister_default_group(iio_triggers_group); | |
177 | } | |
178 | module_exit(iio_sw_trigger_exit); | |
179 | ||
180 | MODULE_AUTHOR("Daniel Baluta <[email protected]>"); | |
181 | MODULE_DESCRIPTION("Industrial I/O software triggers support"); | |
182 | MODULE_LICENSE("GPL v2"); |