linux/drivers/iio/industrialio-sw-trigger.c
<<
>>
Prefs
   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>
  18#include <linux/iio/configfs.h>
  19#include <linux/configfs.h>
  20
  21static struct config_group *iio_triggers_group;
  22static struct config_item_type iio_trigger_type_group_type;
  23
  24static struct config_item_type iio_triggers_group_type = {
  25        .ct_owner = THIS_MODULE,
  26};
  27
  28static LIST_HEAD(iio_trigger_types_list);
  29static DEFINE_MUTEX(iio_trigger_types_lock);
  30
  31static
  32struct 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
  46int 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}
  69EXPORT_SYMBOL(iio_register_sw_trigger_type);
  70
  71void 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}
  83EXPORT_SYMBOL(iio_unregister_sw_trigger_type);
  84
  85static
  86struct 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
  99struct 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;
 116out_module_put:
 117        module_put(tt->owner);
 118        return t;
 119}
 120EXPORT_SYMBOL(iio_sw_trigger_create);
 121
 122void 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}
 129EXPORT_SYMBOL(iio_sw_trigger_destroy);
 130
 131static 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
 145static 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
 154static struct configfs_group_operations trigger_ops = {
 155        .make_group     = &trigger_make_group,
 156        .drop_item      = &trigger_drop_group,
 157};
 158
 159static struct config_item_type iio_trigger_type_group_type = {
 160        .ct_group_ops = &trigger_ops,
 161        .ct_owner       = THIS_MODULE,
 162};
 163
 164static 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);
 170        return PTR_ERR_OR_ZERO(iio_triggers_group);
 171}
 172module_init(iio_sw_trigger_init);
 173
 174static void __exit iio_sw_trigger_exit(void)
 175{
 176        configfs_unregister_default_group(iio_triggers_group);
 177}
 178module_exit(iio_sw_trigger_exit);
 179
 180MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
 181MODULE_DESCRIPTION("Industrial I/O software triggers support");
 182MODULE_LICENSE("GPL v2");
 183