Blame view
drivers/iio/industrialio-event.c
14.3 KB
0a769a953 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 staging:iio:event... |
16 |
#include <linux/kfifo.h> |
0a769a953 staging:iio: Fact... |
17 |
#include <linux/module.h> |
e18045ed7 staging:iio:event... |
18 |
#include <linux/poll.h> |
0a769a953 staging:iio: Fact... |
19 20 21 22 |
#include <linux/sched.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/wait.h> |
06458e277 IIO: Move core he... |
23 |
#include <linux/iio/iio.h> |
0a769a953 staging:iio: Fact... |
24 |
#include "iio_core.h" |
06458e277 IIO: Move core he... |
25 26 |
#include <linux/iio/sysfs.h> #include <linux/iio/events.h> |
0a769a953 staging:iio: Fact... |
27 28 |
/** |
0a769a953 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 staging:iio: Fact... |
31 |
* @det_events: list of detected events |
0a769a953 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 iio: event: Add m... |
35 |
* @read_lock: lock to protect kfifo read operations |
0a769a953 staging:iio: Fact... |
36 37 38 |
*/ struct iio_event_interface { wait_queue_head_t wait; |
2c00193fa staging:iio:event... |
39 |
DECLARE_KFIFO(det_events, struct iio_event_data, 16); |
0a769a953 staging:iio: Fact... |
40 41 42 |
struct list_head dev_attr_list; unsigned long flags; struct attribute_group group; |
b91accafb iio:event: Fix an... |
43 |
struct mutex read_lock; |
0a769a953 staging:iio: Fact... |
44 |
}; |
bc2b7dab6 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 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 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 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 iio: core: Move k... |
62 |
**/ |
0a769a953 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 staging:iio:event... |
66 67 |
struct iio_event_data ev; int copied; |
0a769a953 staging:iio: Fact... |
68 |
|
4b1a9380a iio: iio_push_eve... |
69 70 |
if (!ev_int) return 0; |
0a769a953 staging:iio: Fact... |
71 |
/* Does anyone care? */ |
bc2b7dab6 iio:core: timesta... |
72 |
if (iio_event_enabled(ev_int)) { |
0a769a953 staging:iio: Fact... |
73 |
|
2c00193fa staging:iio:event... |
74 75 |
ev.id = ev_code; ev.timestamp = timestamp; |
498d319bb kfifo API type sa... |
76 |
copied = kfifo_put(&ev_int->det_events, ev); |
2c00193fa staging:iio:event... |
77 |
if (copied != 0) |
b91accafb iio:event: Fix an... |
78 |
wake_up_poll(&ev_int->wait, POLLIN); |
43ba1100a staging:iio:event... |
79 |
} |
0a769a953 staging:iio: Fact... |
80 |
|
2c00193fa staging:iio:event... |
81 |
return 0; |
0a769a953 staging:iio: Fact... |
82 83 |
} EXPORT_SYMBOL(iio_push_event); |
e18045ed7 staging:iio:event... |
84 85 |
/** * iio_event_poll() - poll the event queue to find out if it has data |
a316c01d5 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 staging:iio:event... |
91 92 93 94 |
*/ static unsigned int iio_event_poll(struct file *filep, struct poll_table_struct *wait) { |
cadc2125e 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 staging:iio:event... |
97 |
unsigned int events = 0; |
f18e7a068 iio: Return -ENOD... |
98 |
if (!indio_dev->info) |
41d903c00 iio: event: Remov... |
99 |
return events; |
f18e7a068 iio: Return -ENOD... |
100 |
|
e18045ed7 staging:iio:event... |
101 |
poll_wait(filep, &ev_int->wait, wait); |
e18045ed7 staging:iio:event... |
102 103 |
if (!kfifo_is_empty(&ev_int->det_events)) events = POLLIN | POLLRDNORM; |
e18045ed7 staging:iio:event... |
104 105 106 |
return events; } |
0a769a953 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 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 staging:iio:event... |
114 |
unsigned int copied; |
0a769a953 staging:iio: Fact... |
115 |
int ret; |
f18e7a068 iio: Return -ENOD... |
116 117 |
if (!indio_dev->info) return -ENODEV; |
2c00193fa staging:iio:event... |
118 |
if (count < sizeof(struct iio_event_data)) |
0a769a953 staging:iio: Fact... |
119 |
return -EINVAL; |
b91accafb 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 iio: Wakeup poll ... |
126 127 |
!kfifo_is_empty(&ev_int->det_events) || indio_dev->info == NULL); |
b91accafb iio:event: Fix an... |
128 129 130 131 |
if (ret) return ret; if (indio_dev->info == NULL) return -ENODEV; |
d2f0a48f3 iio: Wakeup poll ... |
132 |
} |
0a769a953 staging:iio: Fact... |
133 |
|
b91accafb 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 staging:iio: Fact... |
150 |
|
b91accafb iio:event: Fix an... |
151 |
} while (copied == 0); |
43ba1100a staging:iio:event... |
152 |
|
b91accafb iio:event: Fix an... |
153 |
return copied; |
0a769a953 staging:iio: Fact... |
154 155 156 157 |
} static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { |
cadc2125e 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 staging:iio: Fact... |
160 |
|
b91accafb iio:event: Fix an... |
161 |
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); |
0a769a953 staging:iio: Fact... |
162 |
|
cadc2125e iio: fix: Keep a ... |
163 |
iio_device_put(indio_dev); |
0a769a953 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 staging:iio:event... |
169 |
.poll = iio_event_poll, |
0a769a953 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 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 iio:event: Fix an... |
190 |
|
cadc2125e iio: fix: Keep a ... |
191 192 193 |
iio_device_get(indio_dev); fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops, |
e2aad1d57 Merge 3.12-rc2 in... |
194 |
indio_dev, O_RDONLY | O_CLOEXEC); |
0a769a953 staging:iio: Fact... |
195 |
if (fd < 0) { |
b91accafb iio:event: Fix an... |
196 |
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); |
cadc2125e iio: fix: Keep a ... |
197 |
iio_device_put(indio_dev); |
b91accafb iio:event: Fix an... |
198 199 |
} else { kfifo_reset_out(&ev_int->det_events); |
0a769a953 staging:iio: Fact... |
200 |
} |
b91accafb iio:event: Fix an... |
201 |
|
bc2b7dab6 iio:core: timesta... |
202 203 |
unlock: mutex_unlock(&indio_dev->mlock); |
0a769a953 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 iio: core: Introd... |
213 |
[IIO_EV_TYPE_CHANGE] = "change", |
0a769a953 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 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 iio: Add a hyster... |
224 |
[IIO_EV_INFO_HYSTERESIS] = "hysteresis", |
77a533c73 iio: core : event... |
225 |
[IIO_EV_INFO_PERIOD] = "period", |
3f7f642b9 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 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 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 iio: Use dev_to_i... |
249 |
struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
0a769a953 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 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 iio: Extend the e... |
260 |
|
0a769a953 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 iio: Use dev_to_i... |
268 |
struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
0a769a953 staging:iio: Fact... |
269 |
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
b4e3ac0a2 iio: Extend the e... |
270 |
int val; |
0a769a953 staging:iio: Fact... |
271 |
|
cb955852a 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 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 iio: Use dev_to_i... |
286 |
struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
0a769a953 staging:iio: Fact... |
287 |
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
9fbfb4b37 IIO: core: Introd... |
288 |
int val, val2, val_arr[2]; |
b4e3ac0a2 iio: Extend the e... |
289 |
int ret; |
0a769a953 staging:iio: Fact... |
290 |
|
cb955852a 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 IIO: core: Introd... |
297 298 299 |
val_arr[0] = val; val_arr[1] = val2; return iio_format_value(buf, ret, 2, val_arr); |
0a769a953 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 iio: Use dev_to_i... |
307 |
struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
0a769a953 staging:iio: Fact... |
308 |
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
b4e3ac0a2 iio: Extend the e... |
309 |
int val, val2; |
0a769a953 staging:iio: Fact... |
310 |
int ret; |
cb955852a iio: Remove suppo... |
311 |
if (!indio_dev->info->write_event_value) |
0a769a953 staging:iio: Fact... |
312 |
return -EINVAL; |
cb955852a 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 staging:iio: Fact... |
320 321 322 323 324 |
if (ret < 0) return ret; return len; } |
b4e3ac0a2 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 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 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 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 iio:core: Handle ... |
364 365 |
if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) continue; |
b4e3ac0a2 iio: Extend the e... |
366 367 368 369 370 371 372 373 |
if (ret) return ret; attrcount++; } return attrcount; } |
cb955852a iio: Remove suppo... |
374 |
static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, |
b4e3ac0a2 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 iio get rid of un... |
388 |
return ret; |
b4e3ac0a2 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 iio get rid of un... |
395 |
return ret; |
b4e3ac0a2 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 iio get rid of un... |
402 |
return ret; |
b4e3ac0a2 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 iio get rid of un... |
409 |
return ret; |
b4e3ac0a2 iio: Extend the e... |
410 411 412 |
attrcount += ret; } ret = attrcount; |
b4e3ac0a2 iio: Extend the e... |
413 414 |
return ret; } |
0a769a953 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 iio: industrialio... |
418 |
/* Dynamically created from the channels array */ |
0a769a953 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 drivers/iio/indus... |
423 |
return ret; |
0a769a953 staging:iio: Fact... |
424 425 426 |
attrcount += ret; } return attrcount; |
0a769a953 staging:iio: Fact... |
427 428 429 430 431 |
} static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev) { int j; |
b4e3ac0a2 iio: Extend the e... |
432 |
for (j = 0; j < indio_dev->num_channels; j++) { |
b4e3ac0a2 iio: Extend the e... |
433 434 435 |
if (indio_dev->channels[j].num_event_specs != 0) return true; } |
0a769a953 staging:iio: Fact... |
436 437 438 439 440 |
return false; } static void iio_setup_ev_int(struct iio_event_interface *ev_int) { |
2c00193fa staging:iio:event... |
441 |
INIT_KFIFO(ev_int->det_events); |
0a769a953 staging:iio: Fact... |
442 |
init_waitqueue_head(&ev_int->wait); |
b91accafb iio:event: Fix an... |
443 |
mutex_init(&ev_int->read_lock); |
0a769a953 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 iio get rid of un... |
459 460 |
if (indio_dev->event_interface == NULL) return -ENOMEM; |
0a769a953 staging:iio: Fact... |
461 |
|
46b24311c iio: Fix unitiali... |
462 |
INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); |
0a769a953 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 iio: Add a helper... |
503 |
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); |
0a769a953 staging:iio: Fact... |
504 |
kfree(indio_dev->event_interface); |
c1b03ab5e iio: core: Fix do... |
505 |
indio_dev->event_interface = NULL; |
0a769a953 staging:iio: Fact... |
506 507 |
return ret; } |
d2f0a48f3 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 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 iio: Add a helper... |
525 |
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); |
0a769a953 staging:iio: Fact... |
526 527 528 |
kfree(indio_dev->event_interface->group.attrs); kfree(indio_dev->event_interface); } |