Blame view

drivers/iio/industrialio-event.c 14.3 KB
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /* Industrial I/O event handling
   *
   * Copyright (c) 2008 Jonathan Cameron
   *
   * 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.
   *
   * Based on elements of hwmon and input subsystems.
   */
  
  #include <linux/anon_inodes.h>
  #include <linux/device.h>
  #include <linux/fs.h>
  #include <linux/kernel.h>
2c00193fa   Lars-Peter Clausen   staging:iio:event...
16
  #include <linux/kfifo.h>
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
17
  #include <linux/module.h>
e18045ed7   Lars-Peter Clausen   staging:iio:event...
18
  #include <linux/poll.h>
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
19
20
21
22
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/uaccess.h>
  #include <linux/wait.h>
06458e277   Jonathan Cameron   IIO: Move core he...
23
  #include <linux/iio/iio.h>
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
24
  #include "iio_core.h"
06458e277   Jonathan Cameron   IIO: Move core he...
25
26
  #include <linux/iio/sysfs.h>
  #include <linux/iio/events.h>
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
27
28
  
  /**
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
29
30
   * struct iio_event_interface - chrdev interface for an event line
   * @wait:		wait queue to allow blocking reads of events
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
31
   * @det_events:		list of detected events
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
32
33
34
   * @dev_attr_list:	list of event interface sysfs attribute
   * @flags:		file operations related flags including busy flag.
   * @group:		event interface sysfs attribute group
a316c01d5   Cristina Opriceana   iio: event: Add m...
35
   * @read_lock:		lock to protect kfifo read operations
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
36
37
38
   */
  struct iio_event_interface {
  	wait_queue_head_t	wait;
2c00193fa   Lars-Peter Clausen   staging:iio:event...
39
  	DECLARE_KFIFO(det_events, struct iio_event_data, 16);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
40
41
42
  	struct list_head	dev_attr_list;
  	unsigned long		flags;
  	struct attribute_group	group;
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
43
  	struct mutex		read_lock;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
44
  };
bc2b7dab6   Gregor Boirie   iio:core: timesta...
45
46
47
48
  bool iio_event_enabled(const struct iio_event_interface *ev_int)
  {
  	return !!test_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
  }
a7e57dce0   Sachin Kamat   iio: core: Move k...
49
50
51
52
53
  /**
   * iio_push_event() - try to add event to the list for userspace reading
   * @indio_dev:		IIO device structure
   * @ev_code:		What event
   * @timestamp:		When the event occurred
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
54
55
56
   *
   * Note: The caller must make sure that this function is not running
   * concurrently for the same indio_dev more than once.
4b1a9380a   Lars-Peter Clausen   iio: iio_push_eve...
57
58
59
60
61
   *
   * This function may be safely used as soon as a valid reference to iio_dev has
   * been obtained via iio_device_alloc(), but any events that are submitted
   * before iio_device_register() has successfully completed will be silently
   * discarded.
a7e57dce0   Sachin Kamat   iio: core: Move k...
62
   **/
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
63
64
65
  int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
  {
  	struct iio_event_interface *ev_int = indio_dev->event_interface;
2c00193fa   Lars-Peter Clausen   staging:iio:event...
66
67
  	struct iio_event_data ev;
  	int copied;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
68

4b1a9380a   Lars-Peter Clausen   iio: iio_push_eve...
69
70
  	if (!ev_int)
  		return 0;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
71
  	/* Does anyone care? */
bc2b7dab6   Gregor Boirie   iio:core: timesta...
72
  	if (iio_event_enabled(ev_int)) {
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
73

2c00193fa   Lars-Peter Clausen   staging:iio:event...
74
75
  		ev.id = ev_code;
  		ev.timestamp = timestamp;
498d319bb   Stefani Seibold   kfifo API type sa...
76
  		copied = kfifo_put(&ev_int->det_events, ev);
2c00193fa   Lars-Peter Clausen   staging:iio:event...
77
  		if (copied != 0)
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
78
  			wake_up_poll(&ev_int->wait, POLLIN);
43ba1100a   Lars-Peter Clausen   staging:iio:event...
79
  	}
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
80

2c00193fa   Lars-Peter Clausen   staging:iio:event...
81
  	return 0;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
82
83
  }
  EXPORT_SYMBOL(iio_push_event);
e18045ed7   Lars-Peter Clausen   staging:iio:event...
84
85
  /**
   * iio_event_poll() - poll the event queue to find out if it has data
a316c01d5   Cristina Opriceana   iio: event: Add m...
86
87
88
89
90
   * @filep:	File structure pointer to identify the device
   * @wait:	Poll table pointer to add the wait queue on
   *
   * Return: (POLLIN | POLLRDNORM) if data is available for reading
   *	   or a negative error code on failure
e18045ed7   Lars-Peter Clausen   staging:iio:event...
91
92
93
94
   */
  static unsigned int iio_event_poll(struct file *filep,
  			     struct poll_table_struct *wait)
  {
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
95
96
  	struct iio_dev *indio_dev = filep->private_data;
  	struct iio_event_interface *ev_int = indio_dev->event_interface;
e18045ed7   Lars-Peter Clausen   staging:iio:event...
97
  	unsigned int events = 0;
f18e7a068   Lars-Peter Clausen   iio: Return -ENOD...
98
  	if (!indio_dev->info)
41d903c00   Cristina Opriceana   iio: event: Remov...
99
  		return events;
f18e7a068   Lars-Peter Clausen   iio: Return -ENOD...
100

e18045ed7   Lars-Peter Clausen   staging:iio:event...
101
  	poll_wait(filep, &ev_int->wait, wait);
e18045ed7   Lars-Peter Clausen   staging:iio:event...
102
103
  	if (!kfifo_is_empty(&ev_int->det_events))
  		events = POLLIN | POLLRDNORM;
e18045ed7   Lars-Peter Clausen   staging:iio:event...
104
105
106
  
  	return events;
  }
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
107
108
109
110
111
  static ssize_t iio_event_chrdev_read(struct file *filep,
  				     char __user *buf,
  				     size_t count,
  				     loff_t *f_ps)
  {
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
112
113
  	struct iio_dev *indio_dev = filep->private_data;
  	struct iio_event_interface *ev_int = indio_dev->event_interface;
2c00193fa   Lars-Peter Clausen   staging:iio:event...
114
  	unsigned int copied;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
115
  	int ret;
f18e7a068   Lars-Peter Clausen   iio: Return -ENOD...
116
117
  	if (!indio_dev->info)
  		return -ENODEV;
2c00193fa   Lars-Peter Clausen   staging:iio:event...
118
  	if (count < sizeof(struct iio_event_data))
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
119
  		return -EINVAL;
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
120
121
122
123
124
125
  	do {
  		if (kfifo_is_empty(&ev_int->det_events)) {
  			if (filep->f_flags & O_NONBLOCK)
  				return -EAGAIN;
  
  			ret = wait_event_interruptible(ev_int->wait,
d2f0a48f3   Lars-Peter Clausen   iio: Wakeup poll ...
126
127
  					!kfifo_is_empty(&ev_int->det_events) ||
  					indio_dev->info == NULL);
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
128
129
130
131
  			if (ret)
  				return ret;
  			if (indio_dev->info == NULL)
  				return -ENODEV;
d2f0a48f3   Lars-Peter Clausen   iio: Wakeup poll ...
132
  		}
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
133

b91accafb   Lars-Peter Clausen   iio:event: Fix an...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  		if (mutex_lock_interruptible(&ev_int->read_lock))
  			return -ERESTARTSYS;
  		ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);
  		mutex_unlock(&ev_int->read_lock);
  
  		if (ret)
  			return ret;
  
  		/*
  		 * If we couldn't read anything from the fifo (a different
  		 * thread might have been faster) we either return -EAGAIN if
  		 * the file descriptor is non-blocking, otherwise we go back to
  		 * sleep and wait for more data to arrive.
  		 */
  		if (copied == 0 && (filep->f_flags & O_NONBLOCK))
  			return -EAGAIN;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
150

b91accafb   Lars-Peter Clausen   iio:event: Fix an...
151
  	} while (copied == 0);
43ba1100a   Lars-Peter Clausen   staging:iio:event...
152

b91accafb   Lars-Peter Clausen   iio:event: Fix an...
153
  	return copied;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
154
155
156
157
  }
  
  static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
  {
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
158
159
  	struct iio_dev *indio_dev = filep->private_data;
  	struct iio_event_interface *ev_int = indio_dev->event_interface;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
160

b91accafb   Lars-Peter Clausen   iio:event: Fix an...
161
  	clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
162

cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
163
  	iio_device_put(indio_dev);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
164
165
166
167
168
  	return 0;
  }
  
  static const struct file_operations iio_event_chrdev_fileops = {
  	.read =  iio_event_chrdev_read,
e18045ed7   Lars-Peter Clausen   staging:iio:event...
169
  	.poll =  iio_event_poll,
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
170
171
172
173
174
175
176
177
178
179
180
181
  	.release = iio_event_chrdev_release,
  	.owner = THIS_MODULE,
  	.llseek = noop_llseek,
  };
  
  int iio_event_getfd(struct iio_dev *indio_dev)
  {
  	struct iio_event_interface *ev_int = indio_dev->event_interface;
  	int fd;
  
  	if (ev_int == NULL)
  		return -ENODEV;
bc2b7dab6   Gregor Boirie   iio:core: timesta...
182
183
184
185
186
187
188
189
  	fd = mutex_lock_interruptible(&indio_dev->mlock);
  	if (fd)
  		return fd;
  
  	if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
  		fd = -EBUSY;
  		goto unlock;
  	}
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
190

cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
191
192
193
  	iio_device_get(indio_dev);
  
  	fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
e2aad1d57   Greg Kroah-Hartman   Merge 3.12-rc2 in...
194
  				indio_dev, O_RDONLY | O_CLOEXEC);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
195
  	if (fd < 0) {
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
196
  		clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
cadc2125e   Lars-Peter Clausen   iio: fix: Keep a ...
197
  		iio_device_put(indio_dev);
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
198
199
  	} else {
  		kfifo_reset_out(&ev_int->det_events);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
200
  	}
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
201

bc2b7dab6   Gregor Boirie   iio:core: timesta...
202
203
  unlock:
  	mutex_unlock(&indio_dev->mlock);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
204
205
206
207
208
209
210
211
212
  	return fd;
  }
  
  static const char * const iio_ev_type_text[] = {
  	[IIO_EV_TYPE_THRESH] = "thresh",
  	[IIO_EV_TYPE_MAG] = "mag",
  	[IIO_EV_TYPE_ROC] = "roc",
  	[IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
  	[IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
27be84236   Irina Tirdea   iio: core: Introd...
213
  	[IIO_EV_TYPE_CHANGE] = "change",
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
214
215
216
217
218
219
220
  };
  
  static const char * const iio_ev_dir_text[] = {
  	[IIO_EV_DIR_EITHER] = "either",
  	[IIO_EV_DIR_RISING] = "rising",
  	[IIO_EV_DIR_FALLING] = "falling"
  };
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
221
222
223
  static const char * const iio_ev_info_text[] = {
  	[IIO_EV_INFO_ENABLE] = "en",
  	[IIO_EV_INFO_VALUE] = "value",
ec6670ae5   Lars-Peter Clausen   iio: Add a hyster...
224
  	[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
77a533c73   Srinivas Pandruvada   iio: core : event...
225
  	[IIO_EV_INFO_PERIOD] = "period",
3f7f642b9   Martin Fuzzey   iio: core: add hi...
226
227
  	[IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db",
  	[IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db",
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  };
  
  static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
  {
  	return attr->c->event_spec[attr->address & 0xffff].dir;
  }
  
  static enum iio_event_type iio_ev_attr_type(struct iio_dev_attr *attr)
  {
  	return attr->c->event_spec[attr->address & 0xffff].type;
  }
  
  static enum iio_event_info iio_ev_attr_info(struct iio_dev_attr *attr)
  {
  	return (attr->address >> 16) & 0xffff;
  }
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
244
245
246
247
248
  static ssize_t iio_ev_state_store(struct device *dev,
  				  struct device_attribute *attr,
  				  const char *buf,
  				  size_t len)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
249
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
250
251
252
253
254
255
256
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
  	int ret;
  	bool val;
  
  	ret = strtobool(buf, &val);
  	if (ret < 0)
  		return ret;
cb955852a   Lars-Peter Clausen   iio: Remove suppo...
257
258
259
  	ret = indio_dev->info->write_event_config(indio_dev,
  		this_attr->c, iio_ev_attr_type(this_attr),
  		iio_ev_attr_dir(this_attr), val);
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
260

0a769a953   Lars-Peter Clausen   staging:iio: Fact...
261
262
263
264
265
266
267
  	return (ret < 0) ? ret : len;
  }
  
  static ssize_t iio_ev_state_show(struct device *dev,
  				 struct device_attribute *attr,
  				 char *buf)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
268
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
269
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
270
  	int val;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
271

cb955852a   Lars-Peter Clausen   iio: Remove suppo...
272
273
274
  	val = indio_dev->info->read_event_config(indio_dev,
  		this_attr->c, iio_ev_attr_type(this_attr),
  		iio_ev_attr_dir(this_attr));
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
275
276
277
278
279
280
281
282
283
284
285
  	if (val < 0)
  		return val;
  	else
  		return sprintf(buf, "%d
  ", val);
  }
  
  static ssize_t iio_ev_value_show(struct device *dev,
  				 struct device_attribute *attr,
  				 char *buf)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
286
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
287
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
288
  	int val, val2, val_arr[2];
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
289
  	int ret;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
290

cb955852a   Lars-Peter Clausen   iio: Remove suppo...
291
292
293
294
295
296
  	ret = indio_dev->info->read_event_value(indio_dev,
  		this_attr->c, iio_ev_attr_type(this_attr),
  		iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
  		&val, &val2);
  	if (ret < 0)
  		return ret;
9fbfb4b37   Srinivas Pandruvada   IIO: core: Introd...
297
298
299
  	val_arr[0] = val;
  	val_arr[1] = val2;
  	return iio_format_value(buf, ret, 2, val_arr);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
300
301
302
303
304
305
306
  }
  
  static ssize_t iio_ev_value_store(struct device *dev,
  				  struct device_attribute *attr,
  				  const char *buf,
  				  size_t len)
  {
e53f5ac52   Lars-Peter Clausen   iio: Use dev_to_i...
307
  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
308
  	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
309
  	int val, val2;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
310
  	int ret;
cb955852a   Lars-Peter Clausen   iio: Remove suppo...
311
  	if (!indio_dev->info->write_event_value)
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
312
  		return -EINVAL;
cb955852a   Lars-Peter Clausen   iio: Remove suppo...
313
314
315
316
317
318
319
  	ret = iio_str_to_fixpoint(buf, 100000, &val, &val2);
  	if (ret)
  		return ret;
  	ret = indio_dev->info->write_event_value(indio_dev,
  		this_attr->c, iio_ev_attr_type(this_attr),
  		iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
  		val, val2);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
320
321
322
323
324
  	if (ret < 0)
  		return ret;
  
  	return len;
  }
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
325
326
327
328
329
330
331
332
333
334
335
336
  static int iio_device_add_event(struct iio_dev *indio_dev,
  	const struct iio_chan_spec *chan, unsigned int spec_index,
  	enum iio_event_type type, enum iio_event_direction dir,
  	enum iio_shared_by shared_by, const unsigned long *mask)
  {
  	ssize_t (*show)(struct device *, struct device_attribute *, char *);
  	ssize_t (*store)(struct device *, struct device_attribute *,
  		const char *, size_t);
  	unsigned int attrcount = 0;
  	unsigned int i;
  	char *postfix;
  	int ret;
ef4b48565   Jonathan Cameron   iio:core: Fix bug...
337
338
339
  	for_each_set_bit(i, mask, sizeof(*mask)*8) {
  		if (i >= ARRAY_SIZE(iio_ev_info_text))
  			return -EINVAL;
1843c2f3d   Irina Tirdea   iio: core: Introd...
340
341
342
343
344
345
346
347
348
  		if (dir != IIO_EV_DIR_NONE)
  			postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
  					iio_ev_type_text[type],
  					iio_ev_dir_text[dir],
  					iio_ev_info_text[i]);
  		else
  			postfix = kasprintf(GFP_KERNEL, "%s_%s",
  					iio_ev_type_text[type],
  					iio_ev_info_text[i]);
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  		if (postfix == NULL)
  			return -ENOMEM;
  
  		if (i == IIO_EV_INFO_ENABLE) {
  			show = iio_ev_state_show;
  			store = iio_ev_state_store;
  		} else {
  			show = iio_ev_value_show;
  			store = iio_ev_value_store;
  		}
  
  		ret = __iio_add_chan_devattr(postfix, chan, show, store,
  			 (i << 16) | spec_index, shared_by, &indio_dev->dev,
  			&indio_dev->event_interface->dev_attr_list);
  		kfree(postfix);
78b332161   Srinivas Pandruvada   iio:core: Handle ...
364
365
  		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
  			continue;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
366
367
368
369
370
371
372
373
  		if (ret)
  			return ret;
  
  		attrcount++;
  	}
  
  	return attrcount;
  }
cb955852a   Lars-Peter Clausen   iio: Remove suppo...
374
  static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
375
376
377
378
379
380
381
382
383
384
385
386
387
  	struct iio_chan_spec const *chan)
  {
  	int ret = 0, i, attrcount = 0;
  	enum iio_event_direction dir;
  	enum iio_event_type type;
  
  	for (i = 0; i < chan->num_event_specs; i++) {
  		type = chan->event_spec[i].type;
  		dir = chan->event_spec[i].dir;
  
  		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
  			IIO_SEPARATE, &chan->event_spec[i].mask_separate);
  		if (ret < 0)
92825ff97   Hartmut Knaack   iio get rid of un...
388
  			return ret;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
389
390
391
392
393
394
  		attrcount += ret;
  
  		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
  			IIO_SHARED_BY_TYPE,
  			&chan->event_spec[i].mask_shared_by_type);
  		if (ret < 0)
92825ff97   Hartmut Knaack   iio get rid of un...
395
  			return ret;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
396
397
398
399
400
401
  		attrcount += ret;
  
  		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
  			IIO_SHARED_BY_DIR,
  			&chan->event_spec[i].mask_shared_by_dir);
  		if (ret < 0)
92825ff97   Hartmut Knaack   iio get rid of un...
402
  			return ret;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
403
404
405
406
407
408
  		attrcount += ret;
  
  		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
  			IIO_SHARED_BY_ALL,
  			&chan->event_spec[i].mask_shared_by_all);
  		if (ret < 0)
92825ff97   Hartmut Knaack   iio get rid of un...
409
  			return ret;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
410
411
412
  		attrcount += ret;
  	}
  	ret = attrcount;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
413
414
  	return ret;
  }
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
415
416
417
  static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
  {
  	int j, ret, attrcount = 0;
2179aabe0   Roberta Dobrescu   iio: industrialio...
418
  	/* Dynamically created from the channels array */
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
419
420
421
422
  	for (j = 0; j < indio_dev->num_channels; j++) {
  		ret = iio_device_add_event_sysfs(indio_dev,
  						 &indio_dev->channels[j]);
  		if (ret < 0)
e3db9ef6e   Julia Lawall   drivers/iio/indus...
423
  			return ret;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
424
425
426
  		attrcount += ret;
  	}
  	return attrcount;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
427
428
429
430
431
  }
  
  static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
  {
  	int j;
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
432
  	for (j = 0; j < indio_dev->num_channels; j++) {
b4e3ac0a2   Lars-Peter Clausen   iio: Extend the e...
433
434
435
  		if (indio_dev->channels[j].num_event_specs != 0)
  			return true;
  	}
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
436
437
438
439
440
  	return false;
  }
  
  static void iio_setup_ev_int(struct iio_event_interface *ev_int)
  {
2c00193fa   Lars-Peter Clausen   staging:iio:event...
441
  	INIT_KFIFO(ev_int->det_events);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
442
  	init_waitqueue_head(&ev_int->wait);
b91accafb   Lars-Peter Clausen   iio:event: Fix an...
443
  	mutex_init(&ev_int->read_lock);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  }
  
  static const char *iio_event_group_name = "events";
  int iio_device_register_eventset(struct iio_dev *indio_dev)
  {
  	struct iio_dev_attr *p;
  	int ret = 0, attrcount_orig = 0, attrcount, attrn;
  	struct attribute **attr;
  
  	if (!(indio_dev->info->event_attrs ||
  	      iio_check_for_dynamic_events(indio_dev)))
  		return 0;
  
  	indio_dev->event_interface =
  		kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
92825ff97   Hartmut Knaack   iio get rid of un...
459
460
  	if (indio_dev->event_interface == NULL)
  		return -ENOMEM;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
461

46b24311c   Sascha Hauer   iio: Fix unitiali...
462
  	INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  	iio_setup_ev_int(indio_dev->event_interface);
  	if (indio_dev->info->event_attrs != NULL) {
  		attr = indio_dev->info->event_attrs->attrs;
  		while (*attr++ != NULL)
  			attrcount_orig++;
  	}
  	attrcount = attrcount_orig;
  	if (indio_dev->channels) {
  		ret = __iio_add_event_config_attrs(indio_dev);
  		if (ret < 0)
  			goto error_free_setup_event_lines;
  		attrcount += ret;
  	}
  
  	indio_dev->event_interface->group.name = iio_event_group_name;
  	indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1,
  							  sizeof(indio_dev->event_interface->group.attrs[0]),
  							  GFP_KERNEL);
  	if (indio_dev->event_interface->group.attrs == NULL) {
  		ret = -ENOMEM;
  		goto error_free_setup_event_lines;
  	}
  	if (indio_dev->info->event_attrs)
  		memcpy(indio_dev->event_interface->group.attrs,
  		       indio_dev->info->event_attrs->attrs,
  		       sizeof(indio_dev->event_interface->group.attrs[0])
  		       *attrcount_orig);
  	attrn = attrcount_orig;
  	/* Add all elements from the list. */
  	list_for_each_entry(p,
  			    &indio_dev->event_interface->dev_attr_list,
  			    l)
  		indio_dev->event_interface->group.attrs[attrn++] =
  			&p->dev_attr.attr;
  	indio_dev->groups[indio_dev->groupcounter++] =
  		&indio_dev->event_interface->group;
  
  	return 0;
  
  error_free_setup_event_lines:
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
503
  	iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
504
  	kfree(indio_dev->event_interface);
c1b03ab5e   Martin Fuzzey   iio: core: Fix do...
505
  	indio_dev->event_interface = NULL;
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
506
507
  	return ret;
  }
d2f0a48f3   Lars-Peter Clausen   iio: Wakeup poll ...
508
509
510
511
512
513
514
515
516
517
518
519
520
  /**
   * iio_device_wakeup_eventset - Wakes up the event waitqueue
   * @indio_dev: The IIO device
   *
   * Wakes up the event waitqueue used for poll() and blocking read().
   * Should usually be called when the device is unregistered.
   */
  void iio_device_wakeup_eventset(struct iio_dev *indio_dev)
  {
  	if (indio_dev->event_interface == NULL)
  		return;
  	wake_up(&indio_dev->event_interface->wait);
  }
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
521
522
523
524
  void iio_device_unregister_eventset(struct iio_dev *indio_dev)
  {
  	if (indio_dev->event_interface == NULL)
  		return;
84088ebd1   Lars-Peter Clausen   iio: Add a helper...
525
  	iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
0a769a953   Lars-Peter Clausen   staging:iio: Fact...
526
527
528
  	kfree(indio_dev->event_interface->group.attrs);
  	kfree(indio_dev->event_interface);
  }