This creates an IIO configfs subsystem named "iio", which has one default
group named "triggers". This allows us to easily create/destroy software
triggers. One must create a driver which implements iio_configfs_trigger.h
interface and then add its trigger type to IIO configfs core.
See Documentation/iio/iio_configfs.txt for more details on how configfs
support for IIO works.
Signed-off-by: Daniel Baluta <daniel.baluta@xxxxxxxxx>
diff --git a/drivers/iio/industrialio-configfs.c b/drivers/iio/industrialio-configfs.c
new file mode 100644
index 0000000..4d2133a
--- /dev/null
+++ b/drivers/iio/industrialio-configfs.c
@@ -0,0 +1,297 @@
+/*
+ * Industrial I/O configfs bits
+ *
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/iio/iio_configfs_trigger.h>
+
+static const char *trigger_types[] =
+{
+ "none",
+};
+
+struct iio_configfs_ops iio_none_ops = {
+ .get_freq = iio_none_get_freq,
+ .set_freq = iio_none_set_freq,
+ .probe = iio_none_probe,
+ .remove = iio_none_remove,
+};
+
+struct iio_trigger_item {
+ struct config_item item;
+ struct iio_configfs_trigger_info *trigger_info;
+};
+
+static
+inline struct iio_trigger_item *to_iio_trigger_item(struct config_item *item)
+{
+ if (!item)
+ return NULL;
+ return container_of(item, struct iio_trigger_item, item);
+}
+
+static unsigned int iio_trigger_get_type(const char *type_str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
+ if (!strncmp(trigger_types[i], type_str,
+ strlen(trigger_types[i])))
+ return i;
+ }
+ return -EINVAL;
+}
+
+static
+void iio_trigger_set_configfs_ops(struct iio_configfs_trigger_info *trig_info,
+ unsigned int type)
+{
+ switch (type) {
+ case IIO_TRIGGER_TYPE_NONE:
+ trig_info->configfs_ops = &iio_none_ops;
+ break;
+ default:
+ pr_err("Setting configfs ops failed! Unknown type %d\n", type);
+ break;
+ }
+}
+
+CONFIGFS_ATTR_STRUCT(iio_trigger_item);
+
+#define IIO_TRIGGER_ITEM_ATTR(_name, _mode, _show, _store) \
+struct iio_trigger_item_attribute iio_trigger_item_attr_##_name = \
+ __CONFIGFS_ATTR(_name, _mode, _show, _store)
+
+static ssize_t iio_trigger_item_type_read(struct iio_trigger_item *item,
+ char *page)
+{
+ return sprintf(page, "%s\n", trigger_types[item->trigger_info->type]);
+}
+
+static ssize_t iio_trigger_item_type_write(struct iio_trigger_item *item,
+ const char *page, size_t count)
+{
+ int type;
+
+ if (item->trigger_info->active)
+ return -EBUSY;
+
+ type = iio_trigger_get_type(page);
+ if (type < 0)
+ return -EINVAL;
+
+ item->trigger_info->type = type;
+
+ iio_trigger_set_configfs_ops(item->trigger_info, type);
+
+ return count;
+}
+
+static ssize_t iio_trigger_item_activate_read(struct iio_trigger_item *item,
+ char *page)
+{
+ return sprintf(page, "%d\n", item->trigger_info->active);
+}
+
+static ssize_t iio_trigger_item_activate_write(struct iio_trigger_item *item,
+ const char *page, size_t count)
+{
+ bool requested_action;
+ int ret;
+
+ ret = strtobool(page, &requested_action);
+ if (ret < 0)
+ return ret;
+
+ if (requested_action == item->trigger_info->active)
+ return -EINVAL;
+
+ if (requested_action)
+ item->trigger_info->configfs_ops->probe(item->trigger_info);
+ else
+ item->trigger_info->configfs_ops->remove(item->trigger_info);
+
+ item->trigger_info->active = requested_action;
+
+ return count;
+}