diff options
author | Daniel Baluta <daniel.baluta@intel.com> | 2016-04-25 09:15:51 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-05-04 06:43:54 -0400 |
commit | 0f3a8c3f34f728e7c96651bb7271e1c388c9aac2 (patch) | |
tree | ad4c901f99f6245a4221e446ec85ad78ca2e7364 /drivers/iio | |
parent | 0825cce21f764c04a96b719af2b491011bc6c523 (diff) |
iio: Add support for creating IIO devices via configfs
This is similar with support for creating triggers via configfs.
Devices will be hosted under:
* /config/iio/devices
We allow users to register "device types" under:
* /config/iio/devices/<device_types>/
Signed-off-by: Daniel Baluta <daniel.baluta@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/Kconfig | 8 | ||||
-rw-r--r-- | drivers/iio/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/industrialio-sw-device.c | 182 |
3 files changed, 191 insertions, 0 deletions
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 505e921f0b19..6743b18194fb 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig | |||
@@ -46,6 +46,14 @@ config IIO_CONSUMERS_PER_TRIGGER | |||
46 | This value controls the maximum number of consumers that a | 46 | This value controls the maximum number of consumers that a |
47 | given trigger may handle. Default is 2. | 47 | given trigger may handle. Default is 2. |
48 | 48 | ||
49 | config IIO_SW_DEVICE | ||
50 | tristate "Enable software IIO device support" | ||
51 | select IIO_CONFIGFS | ||
52 | help | ||
53 | Provides IIO core support for software devices. A software | ||
54 | device can be created via configfs or directly by a driver | ||
55 | using the API provided. | ||
56 | |||
49 | config IIO_SW_TRIGGER | 57 | config IIO_SW_TRIGGER |
50 | tristate "Enable software triggers support" | 58 | tristate "Enable software triggers support" |
51 | select IIO_CONFIGFS | 59 | select IIO_CONFIGFS |
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 20f649073462..87e4c4369e2f 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile | |||
@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o | |||
8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o | 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o |
9 | 9 | ||
10 | obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o | 10 | obj-$(CONFIG_IIO_CONFIGFS) += industrialio-configfs.o |
11 | obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o | ||
11 | obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o | 12 | obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o |
12 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o | 13 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o |
13 | 14 | ||
diff --git a/drivers/iio/industrialio-sw-device.c b/drivers/iio/industrialio-sw-device.c new file mode 100644 index 000000000000..81b49cfca452 --- /dev/null +++ b/drivers/iio/industrialio-sw-device.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * The Industrial I/O core, software IIO devices functions | ||
3 | * | ||
4 | * Copyright (c) 2016 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_device.h> | ||
18 | #include <linux/iio/configfs.h> | ||
19 | #include <linux/configfs.h> | ||
20 | |||
21 | static struct config_group *iio_devices_group; | ||
22 | static struct config_item_type iio_device_type_group_type; | ||
23 | |||
24 | static struct config_item_type iio_devices_group_type = { | ||
25 | .ct_owner = THIS_MODULE, | ||
26 | }; | ||
27 | |||
28 | static LIST_HEAD(iio_device_types_list); | ||
29 | static DEFINE_MUTEX(iio_device_types_lock); | ||
30 | |||
31 | static | ||
32 | struct iio_sw_device_type *__iio_find_sw_device_type(const char *name, | ||
33 | unsigned len) | ||
34 | { | ||
35 | struct iio_sw_device_type *d = NULL, *iter; | ||
36 | |||
37 | list_for_each_entry(iter, &iio_device_types_list, list) | ||
38 | if (!strcmp(iter->name, name)) { | ||
39 | d = iter; | ||
40 | break; | ||
41 | } | ||
42 | |||
43 | return d; | ||
44 | } | ||
45 | |||
46 | int iio_register_sw_device_type(struct iio_sw_device_type *d) | ||
47 | { | ||
48 | struct iio_sw_device_type *iter; | ||
49 | int ret = 0; | ||
50 | |||
51 | mutex_lock(&iio_device_types_lock); | ||
52 | iter = __iio_find_sw_device_type(d->name, strlen(d->name)); | ||
53 | if (iter) | ||
54 | ret = -EBUSY; | ||
55 | else | ||
56 | list_add_tail(&d->list, &iio_device_types_list); | ||
57 | mutex_unlock(&iio_device_types_lock); | ||
58 | |||
59 | if (ret) | ||
60 | return ret; | ||
61 | |||
62 | d->group = configfs_register_default_group(iio_devices_group, d->name, | ||
63 | &iio_device_type_group_type); | ||
64 | if (IS_ERR(d->group)) | ||
65 | ret = PTR_ERR(d->group); | ||
66 | |||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL(iio_register_sw_device_type); | ||
70 | |||
71 | void iio_unregister_sw_device_type(struct iio_sw_device_type *dt) | ||
72 | { | ||
73 | struct iio_sw_device_type *iter; | ||
74 | |||
75 | mutex_lock(&iio_device_types_lock); | ||
76 | iter = __iio_find_sw_device_type(dt->name, strlen(dt->name)); | ||
77 | if (iter) | ||
78 | list_del(&dt->list); | ||
79 | mutex_unlock(&iio_device_types_lock); | ||
80 | |||
81 | configfs_unregister_default_group(dt->group); | ||
82 | } | ||
83 | EXPORT_SYMBOL(iio_unregister_sw_device_type); | ||
84 | |||
85 | static | ||
86 | struct iio_sw_device_type *iio_get_sw_device_type(const char *name) | ||
87 | { | ||
88 | struct iio_sw_device_type *dt; | ||
89 | |||
90 | mutex_lock(&iio_device_types_lock); | ||
91 | dt = __iio_find_sw_device_type(name, strlen(name)); | ||
92 | if (dt && !try_module_get(dt->owner)) | ||
93 | dt = NULL; | ||
94 | mutex_unlock(&iio_device_types_lock); | ||
95 | |||
96 | return dt; | ||
97 | } | ||
98 | |||
99 | struct iio_sw_device *iio_sw_device_create(const char *type, const char *name) | ||
100 | { | ||
101 | struct iio_sw_device *d; | ||
102 | struct iio_sw_device_type *dt; | ||
103 | |||
104 | dt = iio_get_sw_device_type(type); | ||
105 | if (!dt) { | ||
106 | pr_err("Invalid device type: %s\n", type); | ||
107 | return ERR_PTR(-EINVAL); | ||
108 | } | ||
109 | d = dt->ops->probe(name); | ||
110 | if (IS_ERR(d)) | ||
111 | goto out_module_put; | ||
112 | |||
113 | d->device_type = dt; | ||
114 | |||
115 | return d; | ||
116 | out_module_put: | ||
117 | module_put(dt->owner); | ||
118 | return d; | ||
119 | } | ||
120 | EXPORT_SYMBOL(iio_sw_device_create); | ||
121 | |||
122 | void iio_sw_device_destroy(struct iio_sw_device *d) | ||
123 | { | ||
124 | struct iio_sw_device_type *dt = d->device_type; | ||
125 | |||
126 | dt->ops->remove(d); | ||
127 | module_put(dt->owner); | ||
128 | } | ||
129 | EXPORT_SYMBOL(iio_sw_device_destroy); | ||
130 | |||
131 | static struct config_group *device_make_group(struct config_group *group, | ||
132 | const char *name) | ||
133 | { | ||
134 | struct iio_sw_device *d; | ||
135 | |||
136 | d = iio_sw_device_create(group->cg_item.ci_name, name); | ||
137 | if (IS_ERR(d)) | ||
138 | return ERR_CAST(d); | ||
139 | |||
140 | config_item_set_name(&d->group.cg_item, "%s", name); | ||
141 | |||
142 | return &d->group; | ||
143 | } | ||
144 | |||
145 | static void device_drop_group(struct config_group *group, | ||
146 | struct config_item *item) | ||
147 | { | ||
148 | struct iio_sw_device *d = to_iio_sw_device(item); | ||
149 | |||
150 | iio_sw_device_destroy(d); | ||
151 | config_item_put(item); | ||
152 | } | ||
153 | |||
154 | static struct configfs_group_operations device_ops = { | ||
155 | .make_group = &device_make_group, | ||
156 | .drop_item = &device_drop_group, | ||
157 | }; | ||
158 | |||
159 | static struct config_item_type iio_device_type_group_type = { | ||
160 | .ct_group_ops = &device_ops, | ||
161 | .ct_owner = THIS_MODULE, | ||
162 | }; | ||
163 | |||
164 | static int __init iio_sw_device_init(void) | ||
165 | { | ||
166 | iio_devices_group = | ||
167 | configfs_register_default_group(&iio_configfs_subsys.su_group, | ||
168 | "devices", | ||
169 | &iio_devices_group_type); | ||
170 | return PTR_ERR_OR_ZERO(iio_devices_group); | ||
171 | } | ||
172 | module_init(iio_sw_device_init); | ||
173 | |||
174 | static void __exit iio_sw_device_exit(void) | ||
175 | { | ||
176 | configfs_unregister_default_group(iio_devices_group); | ||
177 | } | ||
178 | module_exit(iio_sw_device_exit); | ||
179 | |||
180 | MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | ||
181 | MODULE_DESCRIPTION("Industrial I/O software devices support"); | ||
182 | MODULE_LICENSE("GPL v2"); | ||