root/drivers/iio/trigger/iio-trig-sysfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iio_sysfs_trig_add
  2. iio_sysfs_trig_remove
  3. iio_trigger_sysfs_release
  4. iio_sysfs_trigger_work
  5. iio_sysfs_trigger_poll
  6. iio_sysfs_trigger_probe
  7. iio_sysfs_trigger_remove
  8. iio_sysfs_trig_init
  9. iio_sysfs_trig_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2011 Analog Devices Inc.
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/module.h>
   8 #include <linux/platform_device.h>
   9 #include <linux/slab.h>
  10 #include <linux/list.h>
  11 #include <linux/irq_work.h>
  12 
  13 #include <linux/iio/iio.h>
  14 #include <linux/iio/trigger.h>
  15 
  16 struct iio_sysfs_trig {
  17         struct iio_trigger *trig;
  18         struct irq_work work;
  19         int id;
  20         struct list_head l;
  21 };
  22 
  23 static LIST_HEAD(iio_sysfs_trig_list);
  24 static DEFINE_MUTEX(iio_sysfs_trig_list_mut);
  25 
  26 static int iio_sysfs_trigger_probe(int id);
  27 static 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 = kstrtoul(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 }
  43 static DEVICE_ATTR(add_trigger, S_IWUSR, NULL, &iio_sysfs_trig_add);
  44 
  45 static int iio_sysfs_trigger_remove(int id);
  46 static 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 = kstrtoul(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 
  63 static DEVICE_ATTR(remove_trigger, S_IWUSR, NULL, &iio_sysfs_trig_remove);
  64 
  65 static struct attribute *iio_sysfs_trig_attrs[] = {
  66         &dev_attr_add_trigger.attr,
  67         &dev_attr_remove_trigger.attr,
  68         NULL,
  69 };
  70 
  71 static const struct attribute_group iio_sysfs_trig_group = {
  72         .attrs = iio_sysfs_trig_attrs,
  73 };
  74 
  75 static const struct attribute_group *iio_sysfs_trig_groups[] = {
  76         &iio_sysfs_trig_group,
  77         NULL
  78 };
  79 
  80 
  81 /* Nothing to actually do upon release */
  82 static void iio_trigger_sysfs_release(struct device *dev)
  83 {
  84 }
  85 
  86 static struct device iio_sysfs_trig_dev = {
  87         .bus = &iio_bus_type,
  88         .groups = iio_sysfs_trig_groups,
  89         .release = &iio_trigger_sysfs_release,
  90 };
  91 
  92 static void iio_sysfs_trigger_work(struct irq_work *work)
  93 {
  94         struct iio_sysfs_trig *trig = container_of(work, struct iio_sysfs_trig,
  95                                                         work);
  96 
  97         iio_trigger_poll(trig->trig);
  98 }
  99 
 100 static ssize_t iio_sysfs_trigger_poll(struct device *dev,
 101                 struct device_attribute *attr, const char *buf, size_t count)
 102 {
 103         struct iio_trigger *trig = to_iio_trigger(dev);
 104         struct iio_sysfs_trig *sysfs_trig = iio_trigger_get_drvdata(trig);
 105 
 106         irq_work_queue(&sysfs_trig->work);
 107 
 108         return count;
 109 }
 110 
 111 static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
 112 
 113 static struct attribute *iio_sysfs_trigger_attrs[] = {
 114         &dev_attr_trigger_now.attr,
 115         NULL,
 116 };
 117 
 118 static const struct attribute_group iio_sysfs_trigger_attr_group = {
 119         .attrs = iio_sysfs_trigger_attrs,
 120 };
 121 
 122 static const struct attribute_group *iio_sysfs_trigger_attr_groups[] = {
 123         &iio_sysfs_trigger_attr_group,
 124         NULL
 125 };
 126 
 127 static const struct iio_trigger_ops iio_sysfs_trigger_ops = {
 128 };
 129 
 130 static int iio_sysfs_trigger_probe(int id)
 131 {
 132         struct iio_sysfs_trig *t;
 133         int ret;
 134         bool foundit = false;
 135 
 136         mutex_lock(&iio_sysfs_trig_list_mut);
 137         list_for_each_entry(t, &iio_sysfs_trig_list, l)
 138                 if (id == t->id) {
 139                         foundit = true;
 140                         break;
 141                 }
 142         if (foundit) {
 143                 ret = -EINVAL;
 144                 goto out1;
 145         }
 146         t = kmalloc(sizeof(*t), GFP_KERNEL);
 147         if (t == NULL) {
 148                 ret = -ENOMEM;
 149                 goto out1;
 150         }
 151         t->id = id;
 152         t->trig = iio_trigger_alloc("sysfstrig%d", id);
 153         if (!t->trig) {
 154                 ret = -ENOMEM;
 155                 goto free_t;
 156         }
 157 
 158         t->trig->dev.groups = iio_sysfs_trigger_attr_groups;
 159         t->trig->ops = &iio_sysfs_trigger_ops;
 160         t->trig->dev.parent = &iio_sysfs_trig_dev;
 161         iio_trigger_set_drvdata(t->trig, t);
 162 
 163         init_irq_work(&t->work, iio_sysfs_trigger_work);
 164 
 165         ret = iio_trigger_register(t->trig);
 166         if (ret)
 167                 goto out2;
 168         list_add(&t->l, &iio_sysfs_trig_list);
 169         __module_get(THIS_MODULE);
 170         mutex_unlock(&iio_sysfs_trig_list_mut);
 171         return 0;
 172 
 173 out2:
 174         iio_trigger_free(t->trig);
 175 free_t:
 176         kfree(t);
 177 out1:
 178         mutex_unlock(&iio_sysfs_trig_list_mut);
 179         return ret;
 180 }
 181 
 182 static int iio_sysfs_trigger_remove(int id)
 183 {
 184         bool foundit = false;
 185         struct iio_sysfs_trig *t;
 186 
 187         mutex_lock(&iio_sysfs_trig_list_mut);
 188         list_for_each_entry(t, &iio_sysfs_trig_list, l)
 189                 if (id == t->id) {
 190                         foundit = true;
 191                         break;
 192                 }
 193         if (!foundit) {
 194                 mutex_unlock(&iio_sysfs_trig_list_mut);
 195                 return -EINVAL;
 196         }
 197 
 198         iio_trigger_unregister(t->trig);
 199         iio_trigger_free(t->trig);
 200 
 201         list_del(&t->l);
 202         kfree(t);
 203         module_put(THIS_MODULE);
 204         mutex_unlock(&iio_sysfs_trig_list_mut);
 205         return 0;
 206 }
 207 
 208 
 209 static int __init iio_sysfs_trig_init(void)
 210 {
 211         device_initialize(&iio_sysfs_trig_dev);
 212         dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
 213         return device_add(&iio_sysfs_trig_dev);
 214 }
 215 module_init(iio_sysfs_trig_init);
 216 
 217 static void __exit iio_sysfs_trig_exit(void)
 218 {
 219         device_unregister(&iio_sysfs_trig_dev);
 220 }
 221 module_exit(iio_sysfs_trig_exit);
 222 
 223 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
 224 MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
 225 MODULE_LICENSE("GPL v2");
 226 MODULE_ALIAS("platform:iio-trig-sysfs");

/* [<][>][^][v][top][bottom][index][help] */