.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* Industrial I/O event handling |
---|
2 | 3 | * |
---|
3 | 4 | * 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 | 5 | * |
---|
9 | 6 | * Based on elements of hwmon and input subsystems. |
---|
10 | 7 | */ |
---|
.. | .. |
---|
21 | 18 | #include <linux/uaccess.h> |
---|
22 | 19 | #include <linux/wait.h> |
---|
23 | 20 | #include <linux/iio/iio.h> |
---|
| 21 | +#include <linux/iio/iio-opaque.h> |
---|
24 | 22 | #include "iio_core.h" |
---|
25 | 23 | #include <linux/iio/sysfs.h> |
---|
26 | 24 | #include <linux/iio/events.h> |
---|
.. | .. |
---|
65 | 63 | **/ |
---|
66 | 64 | int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp) |
---|
67 | 65 | { |
---|
68 | | - struct iio_event_interface *ev_int = indio_dev->event_interface; |
---|
| 66 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 67 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
69 | 68 | struct iio_event_data ev; |
---|
70 | 69 | int copied; |
---|
71 | 70 | |
---|
.. | .. |
---|
99 | 98 | struct poll_table_struct *wait) |
---|
100 | 99 | { |
---|
101 | 100 | struct iio_dev *indio_dev = filep->private_data; |
---|
102 | | - struct iio_event_interface *ev_int = indio_dev->event_interface; |
---|
| 101 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 102 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
103 | 103 | __poll_t events = 0; |
---|
104 | 104 | |
---|
105 | 105 | if (!indio_dev->info) |
---|
.. | .. |
---|
119 | 119 | loff_t *f_ps) |
---|
120 | 120 | { |
---|
121 | 121 | struct iio_dev *indio_dev = filep->private_data; |
---|
122 | | - struct iio_event_interface *ev_int = indio_dev->event_interface; |
---|
| 122 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 123 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
123 | 124 | unsigned int copied; |
---|
124 | 125 | int ret; |
---|
125 | 126 | |
---|
.. | .. |
---|
168 | 169 | static int iio_event_chrdev_release(struct inode *inode, struct file *filep) |
---|
169 | 170 | { |
---|
170 | 171 | struct iio_dev *indio_dev = filep->private_data; |
---|
171 | | - struct iio_event_interface *ev_int = indio_dev->event_interface; |
---|
| 172 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 173 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
172 | 174 | |
---|
173 | 175 | clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); |
---|
174 | 176 | |
---|
.. | .. |
---|
187 | 189 | |
---|
188 | 190 | int iio_event_getfd(struct iio_dev *indio_dev) |
---|
189 | 191 | { |
---|
190 | | - struct iio_event_interface *ev_int = indio_dev->event_interface; |
---|
| 192 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 193 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
191 | 194 | int fd; |
---|
192 | 195 | |
---|
193 | 196 | if (ev_int == NULL) |
---|
.. | .. |
---|
225 | 228 | [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", |
---|
226 | 229 | [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", |
---|
227 | 230 | [IIO_EV_TYPE_CHANGE] = "change", |
---|
| 231 | +#ifdef CONFIG_NO_GKI |
---|
| 232 | + [IIO_EV_TYPE_FIFO_FLUSH] = "fifo_flush", |
---|
| 233 | +#endif |
---|
228 | 234 | }; |
---|
229 | 235 | |
---|
230 | 236 | static const char * const iio_ev_dir_text[] = { |
---|
231 | 237 | [IIO_EV_DIR_EITHER] = "either", |
---|
232 | 238 | [IIO_EV_DIR_RISING] = "rising", |
---|
233 | | - [IIO_EV_DIR_FALLING] = "falling" |
---|
| 239 | + [IIO_EV_DIR_FALLING] = "falling", |
---|
| 240 | +#ifdef CONFIG_NO_GKI |
---|
| 241 | + [IIO_EV_DIR_FIFO_EMPTY] = "empty", |
---|
| 242 | + [IIO_EV_DIR_FIFO_DATA] = "data", |
---|
| 243 | +#endif |
---|
234 | 244 | }; |
---|
235 | 245 | |
---|
236 | 246 | static const char * const iio_ev_info_text[] = { |
---|
.. | .. |
---|
346 | 356 | enum iio_event_type type, enum iio_event_direction dir, |
---|
347 | 357 | enum iio_shared_by shared_by, const unsigned long *mask) |
---|
348 | 358 | { |
---|
| 359 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
349 | 360 | ssize_t (*show)(struct device *, struct device_attribute *, char *); |
---|
350 | 361 | ssize_t (*store)(struct device *, struct device_attribute *, |
---|
351 | 362 | const char *, size_t); |
---|
.. | .. |
---|
379 | 390 | |
---|
380 | 391 | ret = __iio_add_chan_devattr(postfix, chan, show, store, |
---|
381 | 392 | (i << 16) | spec_index, shared_by, &indio_dev->dev, |
---|
382 | | - &indio_dev->event_interface->dev_attr_list); |
---|
| 393 | + &iio_dev_opaque->event_interface->dev_attr_list); |
---|
383 | 394 | kfree(postfix); |
---|
384 | 395 | |
---|
385 | 396 | if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE)) |
---|
.. | .. |
---|
472 | 483 | static const char *iio_event_group_name = "events"; |
---|
473 | 484 | int iio_device_register_eventset(struct iio_dev *indio_dev) |
---|
474 | 485 | { |
---|
| 486 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 487 | + struct iio_event_interface *ev_int; |
---|
475 | 488 | struct iio_dev_attr *p; |
---|
476 | 489 | int ret = 0, attrcount_orig = 0, attrcount, attrn; |
---|
477 | 490 | struct attribute **attr; |
---|
.. | .. |
---|
480 | 493 | iio_check_for_dynamic_events(indio_dev))) |
---|
481 | 494 | return 0; |
---|
482 | 495 | |
---|
483 | | - indio_dev->event_interface = |
---|
484 | | - kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); |
---|
485 | | - if (indio_dev->event_interface == NULL) |
---|
| 496 | + ev_int = kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); |
---|
| 497 | + if (ev_int == NULL) |
---|
486 | 498 | return -ENOMEM; |
---|
487 | 499 | |
---|
488 | | - INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list); |
---|
| 500 | + iio_dev_opaque->event_interface = ev_int; |
---|
489 | 501 | |
---|
490 | | - iio_setup_ev_int(indio_dev->event_interface); |
---|
| 502 | + INIT_LIST_HEAD(&ev_int->dev_attr_list); |
---|
| 503 | + |
---|
| 504 | + iio_setup_ev_int(ev_int); |
---|
491 | 505 | if (indio_dev->info->event_attrs != NULL) { |
---|
492 | 506 | attr = indio_dev->info->event_attrs->attrs; |
---|
493 | 507 | while (*attr++ != NULL) |
---|
.. | .. |
---|
501 | 515 | attrcount += ret; |
---|
502 | 516 | } |
---|
503 | 517 | |
---|
504 | | - indio_dev->event_interface->group.name = iio_event_group_name; |
---|
505 | | - indio_dev->event_interface->group.attrs = kcalloc(attrcount + 1, |
---|
506 | | - sizeof(indio_dev->event_interface->group.attrs[0]), |
---|
507 | | - GFP_KERNEL); |
---|
508 | | - if (indio_dev->event_interface->group.attrs == NULL) { |
---|
| 518 | + ev_int->group.name = iio_event_group_name; |
---|
| 519 | + ev_int->group.attrs = kcalloc(attrcount + 1, |
---|
| 520 | + sizeof(ev_int->group.attrs[0]), |
---|
| 521 | + GFP_KERNEL); |
---|
| 522 | + if (ev_int->group.attrs == NULL) { |
---|
509 | 523 | ret = -ENOMEM; |
---|
510 | 524 | goto error_free_setup_event_lines; |
---|
511 | 525 | } |
---|
512 | 526 | if (indio_dev->info->event_attrs) |
---|
513 | | - memcpy(indio_dev->event_interface->group.attrs, |
---|
| 527 | + memcpy(ev_int->group.attrs, |
---|
514 | 528 | indio_dev->info->event_attrs->attrs, |
---|
515 | | - sizeof(indio_dev->event_interface->group.attrs[0]) |
---|
516 | | - *attrcount_orig); |
---|
| 529 | + sizeof(ev_int->group.attrs[0]) * attrcount_orig); |
---|
517 | 530 | attrn = attrcount_orig; |
---|
518 | 531 | /* Add all elements from the list. */ |
---|
519 | | - list_for_each_entry(p, |
---|
520 | | - &indio_dev->event_interface->dev_attr_list, |
---|
521 | | - l) |
---|
522 | | - indio_dev->event_interface->group.attrs[attrn++] = |
---|
523 | | - &p->dev_attr.attr; |
---|
524 | | - indio_dev->groups[indio_dev->groupcounter++] = |
---|
525 | | - &indio_dev->event_interface->group; |
---|
| 532 | + list_for_each_entry(p, &ev_int->dev_attr_list, l) |
---|
| 533 | + ev_int->group.attrs[attrn++] = &p->dev_attr.attr; |
---|
| 534 | + indio_dev->groups[indio_dev->groupcounter++] = &ev_int->group; |
---|
526 | 535 | |
---|
527 | 536 | return 0; |
---|
528 | 537 | |
---|
529 | 538 | error_free_setup_event_lines: |
---|
530 | | - iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); |
---|
531 | | - kfree(indio_dev->event_interface); |
---|
532 | | - indio_dev->event_interface = NULL; |
---|
| 539 | + iio_free_chan_devattr_list(&ev_int->dev_attr_list); |
---|
| 540 | + kfree(ev_int); |
---|
| 541 | + iio_dev_opaque->event_interface = NULL; |
---|
533 | 542 | return ret; |
---|
534 | 543 | } |
---|
535 | 544 | |
---|
.. | .. |
---|
542 | 551 | */ |
---|
543 | 552 | void iio_device_wakeup_eventset(struct iio_dev *indio_dev) |
---|
544 | 553 | { |
---|
545 | | - if (indio_dev->event_interface == NULL) |
---|
| 554 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 555 | + |
---|
| 556 | + if (iio_dev_opaque->event_interface == NULL) |
---|
546 | 557 | return; |
---|
547 | | - wake_up(&indio_dev->event_interface->wait); |
---|
| 558 | + wake_up(&iio_dev_opaque->event_interface->wait); |
---|
548 | 559 | } |
---|
549 | 560 | |
---|
550 | 561 | void iio_device_unregister_eventset(struct iio_dev *indio_dev) |
---|
551 | 562 | { |
---|
552 | | - if (indio_dev->event_interface == NULL) |
---|
| 563 | + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
---|
| 564 | + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; |
---|
| 565 | + |
---|
| 566 | + if (ev_int == NULL) |
---|
553 | 567 | return; |
---|
554 | | - iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list); |
---|
555 | | - kfree(indio_dev->event_interface->group.attrs); |
---|
556 | | - kfree(indio_dev->event_interface); |
---|
| 568 | + iio_free_chan_devattr_list(&ev_int->dev_attr_list); |
---|
| 569 | + kfree(ev_int->group.attrs); |
---|
| 570 | + kfree(ev_int); |
---|
| 571 | + iio_dev_opaque->event_interface = NULL; |
---|
557 | 572 | } |
---|