blob: 364964b1a81526568cb28cfc5a9118a3c7a1e3f2 [file] [log] [blame]
Jonathan Cameron847ec802009-08-18 18:06:19 +01001/* The industrial I/O core
2 *
3 * Copyright (c) 2008 Jonathan Cameron
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * Based on elements of hwmon and input subsystems.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/idr.h>
15#include <linux/kdev_t.h>
16#include <linux/err.h>
17#include <linux/device.h>
18#include <linux/fs.h>
Jonathan Cameron847ec802009-08-18 18:06:19 +010019#include <linux/poll.h>
Jonathan Cameronffc18af2009-10-12 19:18:09 +010020#include <linux/sched.h>
Jeff Mahoney4439c932009-10-12 17:10:34 -040021#include <linux/wait.h>
Jonathan Cameron847ec802009-08-18 18:06:19 +010022#include <linux/cdev.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Jonathan Cameron847ec802009-08-18 18:06:19 +010024#include "iio.h"
25#include "trigger_consumer.h"
26
27#define IIO_ID_PREFIX "device"
28#define IIO_ID_FORMAT IIO_ID_PREFIX "%d"
29
30/* IDR to assign each registered device a unique id*/
Jonathan Cameronb156cf72010-09-04 17:54:43 +010031static DEFINE_IDA(iio_ida);
Jonathan Cameron847ec802009-08-18 18:06:19 +010032/* IDR to allocate character device minor numbers */
Jonathan Cameronb156cf72010-09-04 17:54:43 +010033static DEFINE_IDA(iio_chrdev_ida);
Jonathan Cameron847ec802009-08-18 18:06:19 +010034/* Lock used to protect both of the above */
Jonathan Cameronb156cf72010-09-04 17:54:43 +010035static DEFINE_SPINLOCK(iio_ida_lock);
Jonathan Cameron847ec802009-08-18 18:06:19 +010036
37dev_t iio_devt;
38EXPORT_SYMBOL(iio_devt);
39
40#define IIO_DEV_MAX 256
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +010041struct bus_type iio_bus_type = {
Jonathan Cameron847ec802009-08-18 18:06:19 +010042 .name = "iio",
Jonathan Cameron847ec802009-08-18 18:06:19 +010043};
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +010044EXPORT_SYMBOL(iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +010045
Jonathan Cameron1d892712011-05-18 14:40:51 +010046static const char * const iio_chan_type_name_spec_shared[] = {
Jonathan Cameron1d892712011-05-18 14:40:51 +010047 [IIO_IN] = "in",
Michael Hennerichae191782011-06-10 15:40:48 +020048 [IIO_OUT] = "out",
Michael Hennerichfaf290e2011-05-18 14:42:02 +010049 [IIO_CURRENT] = "current",
50 [IIO_POWER] = "power",
Bryan Freed9bff02f2011-07-07 12:01:54 -070051 [IIO_ACCEL] = "accel",
Jonathan Cameron1d892712011-05-18 14:40:51 +010052 [IIO_IN_DIFF] = "in-in",
53 [IIO_GYRO] = "gyro",
Jonathan Cameron1d892712011-05-18 14:40:51 +010054 [IIO_MAGN] = "magn",
Bryan Freed9bff02f2011-07-07 12:01:54 -070055 [IIO_LIGHT] = "illuminance",
56 [IIO_INTENSITY] = "intensity",
Bryan Freedf09f2c82011-07-07 12:01:55 -070057 [IIO_PROXIMITY] = "proximity",
Bryan Freed9bff02f2011-07-07 12:01:54 -070058 [IIO_TEMP] = "temp",
Jonathan Cameron1d892712011-05-18 14:40:51 +010059 [IIO_INCLI] = "incli",
60 [IIO_ROT] = "rot",
Jonathan Cameron1d892712011-05-18 14:40:51 +010061 [IIO_ANGL] = "angl",
Bryan Freed9bff02f2011-07-07 12:01:54 -070062 [IIO_TIMESTAMP] = "timestamp",
Jonathan Cameron1d892712011-05-18 14:40:51 +010063};
64
65static const char * const iio_chan_type_name_spec_complex[] = {
66 [IIO_IN_DIFF] = "in%d-in%d",
67};
68
69static const char * const iio_modifier_names_light[] = {
70 [IIO_MOD_LIGHT_BOTH] = "both",
71 [IIO_MOD_LIGHT_IR] = "ir",
72};
73
74static const char * const iio_modifier_names_axial[] = {
75 [IIO_MOD_X] = "x",
76 [IIO_MOD_Y] = "y",
77 [IIO_MOD_Z] = "z",
78};
79
80/* relies on pairs of these shared then separate */
81static const char * const iio_chan_info_postfix[] = {
82 [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale",
83 [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset",
84 [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale",
85 [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
Jonathan Cameroneb7fea52011-05-18 14:41:57 +010086 [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
87 [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
Jonathan Cameron7d438172011-08-12 17:47:53 +010088 [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2]
89 = "quadrature_correction_raw",
Jonathan Cameron1d892712011-05-18 14:40:51 +010090};
91
Jonathan Cameron9aa1a162011-08-12 17:08:50 +010092/* Return a negative errno on failure */
93int iio_get_new_ida_val(struct ida *this_ida)
94{
95 int ret;
96 int val;
97
98ida_again:
99 if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
100 return -ENOMEM;
101
102 spin_lock(&iio_ida_lock);
103 ret = ida_get_new(this_ida, &val);
104 spin_unlock(&iio_ida_lock);
105 if (unlikely(ret == -EAGAIN))
106 goto ida_again;
107 else if (unlikely(ret))
108 return ret;
109
110 return val;
111}
112EXPORT_SYMBOL(iio_get_new_ida_val);
113
114void iio_free_ida_val(struct ida *this_ida, int id)
115{
116 spin_lock(&iio_ida_lock);
117 ida_remove(this_ida, id);
118 spin_unlock(&iio_ida_lock);
119}
120EXPORT_SYMBOL(iio_free_ida_val);
121
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100122int iio_push_event(struct iio_dev *dev_info,
123 int ev_line,
124 int ev_code,
125 s64 timestamp)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100126{
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100127 struct iio_event_interface *ev_int
128 = &dev_info->event_interfaces[ev_line];
Jonathan Cameron847ec802009-08-18 18:06:19 +0100129 struct iio_detected_event_list *ev;
130 int ret = 0;
131
132 /* Does anyone care? */
133 mutex_lock(&ev_int->event_list_lock);
134 if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) {
Jonathan Cameron75c80752010-01-09 16:57:34 +0000135 if (ev_int->current_events == ev_int->max_events) {
136 mutex_unlock(&ev_int->event_list_lock);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100137 return 0;
Jonathan Cameron75c80752010-01-09 16:57:34 +0000138 }
Jonathan Cameron847ec802009-08-18 18:06:19 +0100139 ev = kmalloc(sizeof(*ev), GFP_KERNEL);
140 if (ev == NULL) {
141 ret = -ENOMEM;
Jonathan Cameron75c80752010-01-09 16:57:34 +0000142 mutex_unlock(&ev_int->event_list_lock);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100143 goto error_ret;
144 }
145 ev->ev.id = ev_code;
146 ev->ev.timestamp = timestamp;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100147
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100148 list_add_tail(&ev->list, &ev_int->det_events);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100149 ev_int->current_events++;
150 mutex_unlock(&ev_int->event_list_lock);
151 wake_up_interruptible(&ev_int->wait);
152 } else
153 mutex_unlock(&ev_int->event_list_lock);
154
155error_ret:
156 return ret;
157}
Jonathan Cameron847ec802009-08-18 18:06:19 +0100158EXPORT_SYMBOL(iio_push_event);
159
Jonathan Cameron847ec802009-08-18 18:06:19 +0100160
161/* This turns up an awful lot */
162ssize_t iio_read_const_attr(struct device *dev,
163 struct device_attribute *attr,
164 char *buf)
165{
166 return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
167}
168EXPORT_SYMBOL(iio_read_const_attr);
169
Jonathan Cameron847ec802009-08-18 18:06:19 +0100170
Mark Brown77712e52010-02-18 17:19:17 +0000171static ssize_t iio_event_chrdev_read(struct file *filep,
172 char __user *buf,
173 size_t count,
174 loff_t *f_ps)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100175{
176 struct iio_event_interface *ev_int = filep->private_data;
177 struct iio_detected_event_list *el;
178 int ret;
179 size_t len;
180
181 mutex_lock(&ev_int->event_list_lock);
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100182 if (list_empty(&ev_int->det_events)) {
Jonathan Cameron847ec802009-08-18 18:06:19 +0100183 if (filep->f_flags & O_NONBLOCK) {
184 ret = -EAGAIN;
185 goto error_mutex_unlock;
186 }
187 mutex_unlock(&ev_int->event_list_lock);
188 /* Blocking on device; waiting for something to be there */
189 ret = wait_event_interruptible(ev_int->wait,
190 !list_empty(&ev_int
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100191 ->det_events));
Jonathan Cameron847ec802009-08-18 18:06:19 +0100192 if (ret)
193 goto error_ret;
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300194 /* Single access device so no one else can get the data */
Jonathan Cameron847ec802009-08-18 18:06:19 +0100195 mutex_lock(&ev_int->event_list_lock);
196 }
197
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100198 el = list_first_entry(&ev_int->det_events,
Jonathan Cameron847ec802009-08-18 18:06:19 +0100199 struct iio_detected_event_list,
200 list);
201 len = sizeof el->ev;
202 if (copy_to_user(buf, &(el->ev), len)) {
203 ret = -EFAULT;
204 goto error_mutex_unlock;
205 }
206 list_del(&el->list);
207 ev_int->current_events--;
208 mutex_unlock(&ev_int->event_list_lock);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100209 kfree(el);
210
211 return len;
212
213error_mutex_unlock:
214 mutex_unlock(&ev_int->event_list_lock);
215error_ret:
216
217 return ret;
218}
219
Mark Brown77712e52010-02-18 17:19:17 +0000220static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100221{
222 struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
223 struct iio_event_interface *ev_int = hand->private;
224 struct iio_detected_event_list *el, *t;
225
226 mutex_lock(&ev_int->event_list_lock);
227 clear_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags);
228 /*
229 * In order to maintain a clean state for reopening,
230 * clear out any awaiting events. The mask will prevent
231 * any new __iio_push_event calls running.
232 */
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100233 list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
Jonathan Cameron847ec802009-08-18 18:06:19 +0100234 list_del(&el->list);
235 kfree(el);
236 }
237 mutex_unlock(&ev_int->event_list_lock);
238
239 return 0;
240}
241
Mark Brown77712e52010-02-18 17:19:17 +0000242static int iio_event_chrdev_open(struct inode *inode, struct file *filep)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100243{
244 struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
245 struct iio_event_interface *ev_int = hand->private;
246
247 mutex_lock(&ev_int->event_list_lock);
248 if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) {
249 fops_put(filep->f_op);
250 mutex_unlock(&ev_int->event_list_lock);
251 return -EBUSY;
252 }
253 filep->private_data = hand->private;
254 mutex_unlock(&ev_int->event_list_lock);
255
256 return 0;
257}
258
259static const struct file_operations iio_event_chrdev_fileops = {
260 .read = iio_event_chrdev_read,
261 .release = iio_event_chrdev_release,
262 .open = iio_event_chrdev_open,
263 .owner = THIS_MODULE,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200264 .llseek = noop_llseek,
Jonathan Cameron847ec802009-08-18 18:06:19 +0100265};
266
267static void iio_event_dev_release(struct device *dev)
268{
269 struct iio_event_interface *ev_int
270 = container_of(dev, struct iio_event_interface, dev);
271 cdev_del(&ev_int->handler.chrdev);
272 iio_device_free_chrdev_minor(MINOR(dev->devt));
273};
274
275static struct device_type iio_event_type = {
276 .release = iio_event_dev_release,
277};
278
279int iio_device_get_chrdev_minor(void)
280{
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100281 int ret;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100282
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100283 ret = iio_get_new_ida_val(&iio_chrdev_ida);
284 if (ret < IIO_DEV_MAX) /* both errors and valid */
Jonathan Cameron847ec802009-08-18 18:06:19 +0100285 return ret;
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100286 else
Jonathan Cameron847ec802009-08-18 18:06:19 +0100287 return -ENOMEM;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100288}
289
290void iio_device_free_chrdev_minor(int val)
291{
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100292 iio_free_ida_val(&iio_chrdev_ida, val);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100293}
294
Jonathan Cameronb9d40a92011-05-18 14:40:56 +0100295static int iio_setup_ev_int(struct iio_event_interface *ev_int,
Jonathan Cameronc74b0de2011-05-18 14:42:33 +0100296 const char *dev_name,
297 int index,
298 struct module *owner,
299 struct device *dev)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100300{
301 int ret, minor;
302
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100303 ev_int->dev.bus = &iio_bus_type;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100304 ev_int->dev.parent = dev;
305 ev_int->dev.type = &iio_event_type;
306 device_initialize(&ev_int->dev);
307
308 minor = iio_device_get_chrdev_minor();
309 if (minor < 0) {
310 ret = minor;
311 goto error_device_put;
312 }
313 ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor);
Jonathan Cameronc74b0de2011-05-18 14:42:33 +0100314 dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100315
316 ret = device_add(&ev_int->dev);
317 if (ret)
318 goto error_free_minor;
319
320 cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops);
321 ev_int->handler.chrdev.owner = owner;
322
323 mutex_init(&ev_int->event_list_lock);
324 /* discussion point - make this variable? */
325 ev_int->max_events = 10;
326 ev_int->current_events = 0;
Jonathan Cameron3b8ebfb2011-05-18 14:42:21 +0100327 INIT_LIST_HEAD(&ev_int->det_events);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100328 init_waitqueue_head(&ev_int->wait);
329 ev_int->handler.private = ev_int;
330 ev_int->handler.flags = 0;
331
332 ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1);
333 if (ret)
334 goto error_unreg_device;
335
336 return 0;
337
338error_unreg_device:
339 device_unregister(&ev_int->dev);
340error_free_minor:
341 iio_device_free_chrdev_minor(minor);
342error_device_put:
343 put_device(&ev_int->dev);
344
345 return ret;
346}
347
Jonathan Cameronb9d40a92011-05-18 14:40:56 +0100348static void iio_free_ev_int(struct iio_event_interface *ev_int)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100349{
350 device_unregister(&ev_int->dev);
351 put_device(&ev_int->dev);
352}
353
Jonathan Cameron847ec802009-08-18 18:06:19 +0100354static int __init iio_init(void)
355{
356 int ret;
357
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100358 /* Register sysfs bus */
359 ret = bus_register(&iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100360 if (ret < 0) {
361 printk(KERN_ERR
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100362 "%s could not register bus type\n",
Jonathan Cameron847ec802009-08-18 18:06:19 +0100363 __FILE__);
364 goto error_nothing;
365 }
366
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100367 ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
368 if (ret < 0) {
369 printk(KERN_ERR "%s: failed to allocate char dev region\n",
370 __FILE__);
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100371 goto error_unregister_bus_type;
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100372 }
Jonathan Cameron847ec802009-08-18 18:06:19 +0100373
374 return 0;
375
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100376error_unregister_bus_type:
377 bus_unregister(&iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100378error_nothing:
379 return ret;
380}
381
382static void __exit iio_exit(void)
383{
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100384 if (iio_devt)
385 unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100386 bus_unregister(&iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100387}
388
Jonathan Cameron1d892712011-05-18 14:40:51 +0100389static ssize_t iio_read_channel_info(struct device *dev,
390 struct device_attribute *attr,
391 char *buf)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100392{
Jonathan Cameron1d892712011-05-18 14:40:51 +0100393 struct iio_dev *indio_dev = dev_get_drvdata(dev);
394 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
395 int val, val2;
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100396 int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
397 &val, &val2, this_attr->address);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100398
Jonathan Cameron1d892712011-05-18 14:40:51 +0100399 if (ret < 0)
400 return ret;
401
402 if (ret == IIO_VAL_INT)
403 return sprintf(buf, "%d\n", val);
404 else if (ret == IIO_VAL_INT_PLUS_MICRO) {
405 if (val2 < 0)
406 return sprintf(buf, "-%d.%06u\n", val, -val2);
407 else
408 return sprintf(buf, "%d.%06u\n", val, val2);
Michael Hennerich71646e22011-06-27 13:07:07 +0100409 } else if (ret == IIO_VAL_INT_PLUS_NANO) {
410 if (val2 < 0)
411 return sprintf(buf, "-%d.%09u\n", val, -val2);
412 else
413 return sprintf(buf, "%d.%09u\n", val, val2);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100414 } else
415 return 0;
416}
417
418static ssize_t iio_write_channel_info(struct device *dev,
419 struct device_attribute *attr,
420 const char *buf,
421 size_t len)
422{
423 struct iio_dev *indio_dev = dev_get_drvdata(dev);
424 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Michael Hennerich5c04af02011-06-27 13:07:10 +0100425 int ret, integer = 0, fract = 0, fract_mult = 100000;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100426 bool integer_part = true, negative = false;
427
428 /* Assumes decimal - precision based on number of digits */
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100429 if (!indio_dev->info->write_raw)
Jonathan Cameron1d892712011-05-18 14:40:51 +0100430 return -EINVAL;
Michael Hennerich5c04af02011-06-27 13:07:10 +0100431
432 if (indio_dev->info->write_raw_get_fmt)
433 switch (indio_dev->info->write_raw_get_fmt(indio_dev,
434 this_attr->c, this_attr->address)) {
435 case IIO_VAL_INT_PLUS_MICRO:
436 fract_mult = 100000;
437 break;
438 case IIO_VAL_INT_PLUS_NANO:
439 fract_mult = 100000000;
440 break;
441 default:
442 return -EINVAL;
443 }
444
Jonathan Cameron1d892712011-05-18 14:40:51 +0100445 if (buf[0] == '-') {
446 negative = true;
447 buf++;
448 }
Michael Hennerich5c04af02011-06-27 13:07:10 +0100449
Jonathan Cameron1d892712011-05-18 14:40:51 +0100450 while (*buf) {
451 if ('0' <= *buf && *buf <= '9') {
452 if (integer_part)
453 integer = integer*10 + *buf - '0';
454 else {
Michael Hennerich5c04af02011-06-27 13:07:10 +0100455 fract += fract_mult*(*buf - '0');
456 if (fract_mult == 1)
Jonathan Cameron1d892712011-05-18 14:40:51 +0100457 break;
Michael Hennerich5c04af02011-06-27 13:07:10 +0100458 fract_mult /= 10;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100459 }
460 } else if (*buf == '\n') {
461 if (*(buf + 1) == '\0')
462 break;
463 else
464 return -EINVAL;
465 } else if (*buf == '.') {
466 integer_part = false;
467 } else {
468 return -EINVAL;
469 }
470 buf++;
471 }
472 if (negative) {
473 if (integer)
474 integer = -integer;
475 else
Michael Hennerich5c04af02011-06-27 13:07:10 +0100476 fract = -fract;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100477 }
478
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100479 ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
Michael Hennerich5c04af02011-06-27 13:07:10 +0100480 integer, fract, this_attr->address);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100481 if (ret)
482 return ret;
483
484 return len;
485}
486
487static int __iio_build_postfix(struct iio_chan_spec const *chan,
488 bool generic,
489 const char *postfix,
490 char **result)
491{
492 char *all_post;
493 /* 3 options - generic, extend_name, modified - if generic, extend_name
494 * and modified cannot apply.*/
495
496 if (generic || (!chan->modified && !chan->extend_name)) {
497 all_post = kasprintf(GFP_KERNEL, "%s", postfix);
498 } else if (chan->modified) {
499 const char *intermediate;
500 switch (chan->type) {
501 case IIO_INTENSITY:
502 intermediate
503 = iio_modifier_names_light[chan->channel2];
504 break;
505 case IIO_ACCEL:
506 case IIO_GYRO:
507 case IIO_MAGN:
508 case IIO_INCLI:
509 case IIO_ROT:
510 case IIO_ANGL:
511 intermediate
512 = iio_modifier_names_axial[chan->channel2];
513 break;
514 default:
515 return -EINVAL;
516 }
517 if (chan->extend_name)
518 all_post = kasprintf(GFP_KERNEL, "%s_%s_%s",
519 intermediate,
520 chan->extend_name,
521 postfix);
522 else
523 all_post = kasprintf(GFP_KERNEL, "%s_%s",
524 intermediate,
525 postfix);
526 } else
527 all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name,
528 postfix);
529 if (all_post == NULL)
530 return -ENOMEM;
531 *result = all_post;
532 return 0;
533}
534
535int __iio_device_attr_init(struct device_attribute *dev_attr,
536 const char *postfix,
537 struct iio_chan_spec const *chan,
538 ssize_t (*readfunc)(struct device *dev,
539 struct device_attribute *attr,
540 char *buf),
541 ssize_t (*writefunc)(struct device *dev,
542 struct device_attribute *attr,
543 const char *buf,
544 size_t len),
545 bool generic)
546{
547 int ret;
548 char *name_format, *full_postfix;
549 sysfs_attr_init(&dev_attr->attr);
550 ret = __iio_build_postfix(chan, generic, postfix, &full_postfix);
551 if (ret)
552 goto error_ret;
553
554 /* Special case for types that uses both channel numbers in naming */
555 if (chan->type == IIO_IN_DIFF && !generic)
556 name_format
557 = kasprintf(GFP_KERNEL, "%s_%s",
558 iio_chan_type_name_spec_complex[chan->type],
559 full_postfix);
560 else if (generic || !chan->indexed)
561 name_format
562 = kasprintf(GFP_KERNEL, "%s_%s",
563 iio_chan_type_name_spec_shared[chan->type],
564 full_postfix);
565 else
566 name_format
567 = kasprintf(GFP_KERNEL, "%s%d_%s",
568 iio_chan_type_name_spec_shared[chan->type],
569 chan->channel,
570 full_postfix);
571
572 if (name_format == NULL) {
573 ret = -ENOMEM;
574 goto error_free_full_postfix;
575 }
576 dev_attr->attr.name = kasprintf(GFP_KERNEL,
577 name_format,
578 chan->channel,
579 chan->channel2);
580 if (dev_attr->attr.name == NULL) {
581 ret = -ENOMEM;
582 goto error_free_name_format;
583 }
584
585 if (readfunc) {
586 dev_attr->attr.mode |= S_IRUGO;
587 dev_attr->show = readfunc;
588 }
589
590 if (writefunc) {
591 dev_attr->attr.mode |= S_IWUSR;
592 dev_attr->store = writefunc;
593 }
594 kfree(name_format);
595 kfree(full_postfix);
596
597 return 0;
598
599error_free_name_format:
600 kfree(name_format);
601error_free_full_postfix:
602 kfree(full_postfix);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100603error_ret:
604 return ret;
605}
606
Jonathan Cameron1d892712011-05-18 14:40:51 +0100607void __iio_device_attr_deinit(struct device_attribute *dev_attr)
608{
609 kfree(dev_attr->attr.name);
610}
611
612int __iio_add_chan_devattr(const char *postfix,
613 const char *group,
614 struct iio_chan_spec const *chan,
615 ssize_t (*readfunc)(struct device *dev,
616 struct device_attribute *attr,
617 char *buf),
618 ssize_t (*writefunc)(struct device *dev,
619 struct device_attribute *attr,
620 const char *buf,
621 size_t len),
622 int mask,
623 bool generic,
624 struct device *dev,
625 struct list_head *attr_list)
626{
627 int ret;
628 struct iio_dev_attr *iio_attr, *t;
629
630 iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
631 if (iio_attr == NULL) {
632 ret = -ENOMEM;
633 goto error_ret;
634 }
635 ret = __iio_device_attr_init(&iio_attr->dev_attr,
636 postfix, chan,
637 readfunc, writefunc, generic);
638 if (ret)
639 goto error_iio_dev_attr_free;
640 iio_attr->c = chan;
641 iio_attr->address = mask;
642 list_for_each_entry(t, attr_list, l)
643 if (strcmp(t->dev_attr.attr.name,
644 iio_attr->dev_attr.attr.name) == 0) {
645 if (!generic)
646 dev_err(dev, "tried to double register : %s\n",
647 t->dev_attr.attr.name);
648 ret = -EBUSY;
649 goto error_device_attr_deinit;
650 }
651
652 ret = sysfs_add_file_to_group(&dev->kobj,
653 &iio_attr->dev_attr.attr, group);
654 if (ret < 0)
655 goto error_device_attr_deinit;
656
657 list_add(&iio_attr->l, attr_list);
658
659 return 0;
660
661error_device_attr_deinit:
662 __iio_device_attr_deinit(&iio_attr->dev_attr);
663error_iio_dev_attr_free:
664 kfree(iio_attr);
665error_ret:
666 return ret;
667}
668
669static int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
670 struct iio_chan_spec const *chan)
671{
672 int ret, i;
673
674
675 if (chan->channel < 0)
676 return 0;
677 if (chan->processed_val)
678 ret = __iio_add_chan_devattr("input", NULL, chan,
679 &iio_read_channel_info,
680 NULL,
681 0,
682 0,
683 &dev_info->dev,
684 &dev_info->channel_attr_list);
685 else
686 ret = __iio_add_chan_devattr("raw", NULL, chan,
687 &iio_read_channel_info,
Michael Hennerichae191782011-06-10 15:40:48 +0200688 (chan->type == IIO_OUT ?
689 &iio_write_channel_info : NULL),
Jonathan Cameron1d892712011-05-18 14:40:51 +0100690 0,
691 0,
692 &dev_info->dev,
693 &dev_info->channel_attr_list);
694 if (ret)
695 goto error_ret;
696
697 for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
698 ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
699 NULL, chan,
700 &iio_read_channel_info,
701 &iio_write_channel_info,
702 (1 << i),
703 !(i%2),
704 &dev_info->dev,
705 &dev_info->channel_attr_list);
706 if (ret == -EBUSY && (i%2 == 0)) {
707 ret = 0;
708 continue;
709 }
710 if (ret < 0)
711 goto error_ret;
712 }
713error_ret:
714 return ret;
715}
716
717static void iio_device_remove_and_free_read_attr(struct iio_dev *dev_info,
718 struct iio_dev_attr *p)
719{
720 sysfs_remove_file_from_group(&dev_info->dev.kobj,
721 &p->dev_attr.attr, NULL);
722 kfree(p->dev_attr.attr.name);
723 kfree(p);
724}
725
Jonathan Cameron1b732882011-05-18 14:41:43 +0100726static ssize_t iio_show_dev_name(struct device *dev,
727 struct device_attribute *attr,
728 char *buf)
729{
730 struct iio_dev *indio_dev = dev_get_drvdata(dev);
731 return sprintf(buf, "%s\n", indio_dev->name);
732}
733
734static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
735
Jonathan Cameronf7256872011-08-12 16:55:35 +0100736static struct attribute *iio_base_dummy_attrs[] = {
737 NULL
738};
739static struct attribute_group iio_base_dummy_group = {
740 .attrs = iio_base_dummy_attrs,
741};
742
Jonathan Cameron1d892712011-05-18 14:40:51 +0100743static int iio_device_register_sysfs(struct iio_dev *dev_info)
744{
745 int i, ret = 0;
746 struct iio_dev_attr *p, *n;
747
Jonathan Cameronf7256872011-08-12 16:55:35 +0100748 if (dev_info->info->attrs)
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100749 ret = sysfs_create_group(&dev_info->dev.kobj,
750 dev_info->info->attrs);
Jonathan Cameronf7256872011-08-12 16:55:35 +0100751 else
752 ret = sysfs_create_group(&dev_info->dev.kobj,
753 &iio_base_dummy_group);
754
755 if (ret) {
756 dev_err(dev_info->dev.parent,
757 "Failed to register sysfs hooks\n");
758 goto error_ret;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100759 }
760
761 /*
762 * New channel registration method - relies on the fact a group does
763 * not need to be initialized if it is name is NULL.
764 */
765 INIT_LIST_HEAD(&dev_info->channel_attr_list);
766 if (dev_info->channels)
767 for (i = 0; i < dev_info->num_channels; i++) {
768 ret = iio_device_add_channel_sysfs(dev_info,
769 &dev_info
770 ->channels[i]);
771 if (ret < 0)
772 goto error_clear_attrs;
773 }
Jonathan Cameronf7256872011-08-12 16:55:35 +0100774 if (dev_info->name) {
Jonathan Cameron1b732882011-05-18 14:41:43 +0100775 ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
776 &dev_attr_name.attr,
777 NULL);
778 if (ret)
779 goto error_clear_attrs;
780 }
Jonathan Cameron1d892712011-05-18 14:40:51 +0100781 return 0;
Jonathan Cameron1b732882011-05-18 14:41:43 +0100782
Jonathan Cameron1d892712011-05-18 14:40:51 +0100783error_clear_attrs:
784 list_for_each_entry_safe(p, n,
785 &dev_info->channel_attr_list, l) {
786 list_del(&p->l);
787 iio_device_remove_and_free_read_attr(dev_info, p);
788 }
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100789 if (dev_info->info->attrs)
790 sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
Jonathan Cameronf7256872011-08-12 16:55:35 +0100791 else
792 sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100793error_ret:
794 return ret;
795
796}
797
Jonathan Cameron847ec802009-08-18 18:06:19 +0100798static void iio_device_unregister_sysfs(struct iio_dev *dev_info)
799{
Jonathan Cameron1d892712011-05-18 14:40:51 +0100800
801 struct iio_dev_attr *p, *n;
Jonathan Cameron1b732882011-05-18 14:41:43 +0100802 if (dev_info->name)
803 sysfs_remove_file_from_group(&dev_info->dev.kobj,
804 &dev_attr_name.attr,
805 NULL);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100806 list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) {
807 list_del(&p->l);
808 iio_device_remove_and_free_read_attr(dev_info, p);
809 }
810
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100811 if (dev_info->info->attrs)
812 sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
Jonathan Cameronf7256872011-08-12 16:55:35 +0100813 else
814 sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100815}
816
Jonathan Cameron1d892712011-05-18 14:40:51 +0100817static const char * const iio_ev_type_text[] = {
818 [IIO_EV_TYPE_THRESH] = "thresh",
819 [IIO_EV_TYPE_MAG] = "mag",
820 [IIO_EV_TYPE_ROC] = "roc"
821};
822
823static const char * const iio_ev_dir_text[] = {
824 [IIO_EV_DIR_EITHER] = "either",
825 [IIO_EV_DIR_RISING] = "rising",
826 [IIO_EV_DIR_FALLING] = "falling"
827};
828
829static ssize_t iio_ev_state_store(struct device *dev,
830 struct device_attribute *attr,
831 const char *buf,
832 size_t len)
833{
834 struct iio_dev *indio_dev = dev_get_drvdata(dev);
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100835 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100836 int ret;
Jonathan Cameronc74b0de2011-05-18 14:42:33 +0100837 bool val;
838
839 ret = strtobool(buf, &val);
840 if (ret < 0)
841 return ret;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100842
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100843 ret = indio_dev->info->write_event_config(indio_dev,
844 this_attr->address,
845 val);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100846 return (ret < 0) ? ret : len;
847}
848
849static ssize_t iio_ev_state_show(struct device *dev,
850 struct device_attribute *attr,
851 char *buf)
852{
853 struct iio_dev *indio_dev = dev_get_drvdata(dev);
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100854 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100855 int val = indio_dev->info->read_event_config(indio_dev,
856 this_attr->address);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100857
858 if (val < 0)
859 return val;
860 else
861 return sprintf(buf, "%d\n", val);
862}
863
864static ssize_t iio_ev_value_show(struct device *dev,
865 struct device_attribute *attr,
866 char *buf)
867{
868 struct iio_dev *indio_dev = dev_get_drvdata(dev);
869 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
870 int val, ret;
871
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100872 ret = indio_dev->info->read_event_value(indio_dev,
873 this_attr->address, &val);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100874 if (ret < 0)
875 return ret;
876
877 return sprintf(buf, "%d\n", val);
878}
879
880static ssize_t iio_ev_value_store(struct device *dev,
881 struct device_attribute *attr,
882 const char *buf,
883 size_t len)
884{
885 struct iio_dev *indio_dev = dev_get_drvdata(dev);
886 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
887 unsigned long val;
888 int ret;
889
890 ret = strict_strtoul(buf, 10, &val);
891 if (ret)
892 return ret;
893
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100894 ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
895 val);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100896 if (ret < 0)
897 return ret;
898
899 return len;
900}
901
Jonathan Cameron1d892712011-05-18 14:40:51 +0100902static int iio_device_add_event_sysfs(struct iio_dev *dev_info,
903 struct iio_chan_spec const *chan)
904{
905
906 int ret = 0, i, mask;
907 char *postfix;
908 if (!chan->event_mask)
909 return 0;
910
911 for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
912 postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
913 iio_ev_type_text[i/IIO_EV_TYPE_MAX],
914 iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
915 if (postfix == NULL) {
916 ret = -ENOMEM;
917 goto error_ret;
918 }
919 switch (chan->type) {
920 /* Switch this to a table at some point */
921 case IIO_IN:
922 mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
923 i/IIO_EV_TYPE_MAX,
924 i%IIO_EV_TYPE_MAX);
925 break;
926 case IIO_ACCEL:
927 mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
928 i/IIO_EV_TYPE_MAX,
929 i%IIO_EV_TYPE_MAX);
930 break;
931 case IIO_IN_DIFF:
932 mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel,
933 chan->channel2,
934 i/IIO_EV_TYPE_MAX,
935 i%IIO_EV_TYPE_MAX);
936 break;
937 default:
938 printk(KERN_INFO "currently unhandled type of event\n");
Jonathan Cameron9076faa2011-08-12 16:55:36 +0100939 continue;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100940 }
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100941 ret = __iio_add_chan_devattr(postfix,
942 NULL,
943 chan,
944 &iio_ev_state_show,
945 iio_ev_state_store,
946 mask,
947 /*HACK. - limits us to one
948 event interface - fix by
949 extending the bitmask - but
950 how far*/
951 0,
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100952 &dev_info->event_interfaces[0].dev,
Jonathan Cameronaaf370d2011-05-18 14:41:16 +0100953 &dev_info->event_interfaces[0].
954 dev_attr_list);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100955 kfree(postfix);
956 if (ret)
957 goto error_ret;
958
959 postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
960 iio_ev_type_text[i/IIO_EV_TYPE_MAX],
961 iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
962 if (postfix == NULL) {
963 ret = -ENOMEM;
964 goto error_ret;
965 }
966 ret = __iio_add_chan_devattr(postfix, NULL, chan,
967 iio_ev_value_show,
968 iio_ev_value_store,
969 mask,
970 0,
971 &dev_info->event_interfaces[0]
972 .dev,
973 &dev_info->event_interfaces[0]
974 .dev_attr_list);
975 kfree(postfix);
976 if (ret)
977 goto error_ret;
978
979 }
980
981error_ret:
982 return ret;
983}
984
Jonathan Cameron232b9cb2011-08-12 17:08:49 +0100985static inline void __iio_remove_event_config_attrs(struct iio_dev *dev_info,
986 int i)
Jonathan Cameron1d892712011-05-18 14:40:51 +0100987{
988 struct iio_dev_attr *p, *n;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100989 list_for_each_entry_safe(p, n,
Jonathan Cameron232b9cb2011-08-12 17:08:49 +0100990 &dev_info->event_interfaces[i].
Jonathan Cameron1d892712011-05-18 14:40:51 +0100991 dev_attr_list, l) {
992 sysfs_remove_file_from_group(&dev_info
Jonathan Cameron232b9cb2011-08-12 17:08:49 +0100993 ->event_interfaces[i].dev.kobj,
Jonathan Cameron1d892712011-05-18 14:40:51 +0100994 &p->dev_attr.attr,
Jonathan Cameron232b9cb2011-08-12 17:08:49 +0100995 NULL);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100996 kfree(p->dev_attr.attr.name);
997 kfree(p);
998 }
Jonathan Cameron1d892712011-05-18 14:40:51 +0100999}
1000
Jonathan Cameron847ec802009-08-18 18:06:19 +01001001static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
1002{
Jonathan Cameron1d892712011-05-18 14:40:51 +01001003 int j;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001004 int ret;
Jonathan Cameron232b9cb2011-08-12 17:08:49 +01001005 INIT_LIST_HEAD(&dev_info->event_interfaces[i].dev_attr_list);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001006 /* Dynically created from the channels array */
1007 if (dev_info->channels) {
1008 for (j = 0; j < dev_info->num_channels; j++) {
1009 ret = iio_device_add_event_sysfs(dev_info,
1010 &dev_info
1011 ->channels[j]);
1012 if (ret)
1013 goto error_clear_attrs;
1014 }
1015 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001016 return 0;
1017
Jonathan Cameron1d892712011-05-18 14:40:51 +01001018error_clear_attrs:
Jonathan Cameron232b9cb2011-08-12 17:08:49 +01001019 __iio_remove_event_config_attrs(dev_info, i);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001020
1021 return ret;
1022}
1023
Jonathan Cameron847ec802009-08-18 18:06:19 +01001024static int iio_device_register_eventset(struct iio_dev *dev_info)
1025{
1026 int ret = 0, i, j;
1027
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001028 if (dev_info->info->num_interrupt_lines == 0)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001029 return 0;
1030
1031 dev_info->event_interfaces =
1032 kzalloc(sizeof(struct iio_event_interface)
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001033 *dev_info->info->num_interrupt_lines,
Jonathan Cameron847ec802009-08-18 18:06:19 +01001034 GFP_KERNEL);
1035 if (dev_info->event_interfaces == NULL) {
1036 ret = -ENOMEM;
1037 goto error_ret;
1038 }
1039
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001040 for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
Jonathan Cameron847ec802009-08-18 18:06:19 +01001041 ret = iio_setup_ev_int(&dev_info->event_interfaces[i],
Jonathan Cameronc74b0de2011-05-18 14:42:33 +01001042 dev_name(&dev_info->dev),
1043 i,
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001044 dev_info->info->driver_module,
Jonathan Cameron847ec802009-08-18 18:06:19 +01001045 &dev_info->dev);
1046 if (ret) {
1047 dev_err(&dev_info->dev,
1048 "Could not get chrdev interface\n");
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001049 goto error_free_setup_event_lines;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001050 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001051
Jonathan Cameron5cba2202010-05-04 14:43:01 +01001052 dev_set_drvdata(&dev_info->event_interfaces[i].dev,
1053 (void *)dev_info);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001054
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001055 if (dev_info->info->event_attrs != NULL)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001056 ret = sysfs_create_group(&dev_info
1057 ->event_interfaces[i]
1058 .dev.kobj,
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001059 &dev_info->info
1060 ->event_attrs[i]);
Jonathan Cameron5cba2202010-05-04 14:43:01 +01001061
Jonathan Cameron847ec802009-08-18 18:06:19 +01001062 if (ret) {
1063 dev_err(&dev_info->dev,
1064 "Failed to register sysfs for event attrs");
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001065 iio_free_ev_int(&dev_info->event_interfaces[i]);
1066 goto error_free_setup_event_lines;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001067 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001068 ret = __iio_add_event_config_attrs(dev_info, i);
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001069 if (ret) {
1070 if (dev_info->info->event_attrs != NULL)
1071 sysfs_remove_group(&dev_info
1072 ->event_interfaces[i]
1073 .dev.kobj,
1074 &dev_info->info
1075 ->event_attrs[i]);
1076 iio_free_ev_int(&dev_info->event_interfaces[i]);
1077 goto error_free_setup_event_lines;
1078 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001079 }
1080
1081 return 0;
1082
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001083error_free_setup_event_lines:
1084 for (j = 0; j < i; j++) {
1085 __iio_remove_event_config_attrs(dev_info, j);
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001086 if (dev_info->info->event_attrs != NULL)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001087 sysfs_remove_group(&dev_info
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001088 ->event_interfaces[j].dev.kobj,
1089 &dev_info->info->event_attrs[j]);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001090 iio_free_ev_int(&dev_info->event_interfaces[j]);
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001091 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001092 kfree(dev_info->event_interfaces);
1093error_ret:
1094
1095 return ret;
1096}
1097
1098static void iio_device_unregister_eventset(struct iio_dev *dev_info)
1099{
1100 int i;
1101
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001102 if (dev_info->info->num_interrupt_lines == 0)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001103 return;
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001104 for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
Jonathan Cameron1d892712011-05-18 14:40:51 +01001105 __iio_remove_event_config_attrs(dev_info, i);
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001106 if (dev_info->info->event_attrs != NULL)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001107 sysfs_remove_group(&dev_info
1108 ->event_interfaces[i].dev.kobj,
Jonathan Cameron6fe81352011-05-18 14:42:37 +01001109 &dev_info->info->event_attrs[i]);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001110 iio_free_ev_int(&dev_info->event_interfaces[i]);
Jonathan Cameroncc2439f2011-08-12 16:55:30 +01001111 }
Jonathan Cameron847ec802009-08-18 18:06:19 +01001112 kfree(dev_info->event_interfaces);
1113}
1114
1115static void iio_dev_release(struct device *device)
1116{
Jonathan Cameron847ec802009-08-18 18:06:19 +01001117 iio_put();
Jonathan Cameronc74b0de2011-05-18 14:42:33 +01001118 kfree(to_iio_dev(device));
Jonathan Cameron847ec802009-08-18 18:06:19 +01001119}
1120
1121static struct device_type iio_dev_type = {
1122 .name = "iio_device",
1123 .release = iio_dev_release,
1124};
1125
Jonathan Cameron6f7c8ee2011-04-15 18:55:56 +01001126struct iio_dev *iio_allocate_device(int sizeof_priv)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001127{
Jonathan Cameron6f7c8ee2011-04-15 18:55:56 +01001128 struct iio_dev *dev;
1129 size_t alloc_size;
1130
1131 alloc_size = sizeof(struct iio_dev);
1132 if (sizeof_priv) {
1133 alloc_size = ALIGN(alloc_size, IIO_ALIGN);
1134 alloc_size += sizeof_priv;
1135 }
1136 /* ensure 32-byte alignment of whole construct ? */
1137 alloc_size += IIO_ALIGN - 1;
1138
1139 dev = kzalloc(alloc_size, GFP_KERNEL);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001140
1141 if (dev) {
1142 dev->dev.type = &iio_dev_type;
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +01001143 dev->dev.bus = &iio_bus_type;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001144 device_initialize(&dev->dev);
1145 dev_set_drvdata(&dev->dev, (void *)dev);
1146 mutex_init(&dev->mlock);
1147 iio_get();
1148 }
1149
1150 return dev;
1151}
1152EXPORT_SYMBOL(iio_allocate_device);
1153
1154void iio_free_device(struct iio_dev *dev)
1155{
1156 if (dev)
1157 iio_put_device(dev);
1158}
1159EXPORT_SYMBOL(iio_free_device);
1160
1161int iio_device_register(struct iio_dev *dev_info)
1162{
1163 int ret;
1164
Jonathan Cameronc74b0de2011-05-18 14:42:33 +01001165 dev_info->id = iio_get_new_ida_val(&iio_ida);
1166 if (dev_info->id < 0) {
1167 ret = dev_info->id;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001168 dev_err(&dev_info->dev, "Failed to get id\n");
1169 goto error_ret;
1170 }
1171 dev_set_name(&dev_info->dev, "device%d", dev_info->id);
1172
1173 ret = device_add(&dev_info->dev);
1174 if (ret)
Jonathan Cameronb156cf72010-09-04 17:54:43 +01001175 goto error_free_ida;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001176 ret = iio_device_register_sysfs(dev_info);
1177 if (ret) {
1178 dev_err(dev_info->dev.parent,
1179 "Failed to register sysfs interfaces\n");
1180 goto error_del_device;
1181 }
1182 ret = iio_device_register_eventset(dev_info);
1183 if (ret) {
1184 dev_err(dev_info->dev.parent,
Roel Van Nyenc849d252010-04-29 19:27:31 +02001185 "Failed to register event set\n");
Jonathan Cameron847ec802009-08-18 18:06:19 +01001186 goto error_free_sysfs;
1187 }
1188 if (dev_info->modes & INDIO_RING_TRIGGERED)
1189 iio_device_register_trigger_consumer(dev_info);
1190
1191 return 0;
1192
1193error_free_sysfs:
1194 iio_device_unregister_sysfs(dev_info);
1195error_del_device:
1196 device_del(&dev_info->dev);
Jonathan Cameronb156cf72010-09-04 17:54:43 +01001197error_free_ida:
Jonathan Cameronc74b0de2011-05-18 14:42:33 +01001198 iio_free_ida_val(&iio_ida, dev_info->id);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001199error_ret:
1200 return ret;
1201}
1202EXPORT_SYMBOL(iio_device_register);
1203
1204void iio_device_unregister(struct iio_dev *dev_info)
1205{
1206 if (dev_info->modes & INDIO_RING_TRIGGERED)
1207 iio_device_unregister_trigger_consumer(dev_info);
1208 iio_device_unregister_eventset(dev_info);
1209 iio_device_unregister_sysfs(dev_info);
Jonathan Cameronc74b0de2011-05-18 14:42:33 +01001210 iio_free_ida_val(&iio_ida, dev_info->id);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001211 device_unregister(&dev_info->dev);
1212}
1213EXPORT_SYMBOL(iio_device_unregister);
1214
1215void iio_put(void)
1216{
1217 module_put(THIS_MODULE);
1218}
1219
1220void iio_get(void)
1221{
1222 __module_get(THIS_MODULE);
1223}
1224
1225subsys_initcall(iio_init);
1226module_exit(iio_exit);
1227
1228MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
1229MODULE_DESCRIPTION("Industrial I/O core");
1230MODULE_LICENSE("GPL");