OpenCloudOS-Kernel/drivers/iio/industrialio-event.c

558 lines
14 KiB
C
Raw Normal View History

/* 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>
#include <linux/kfifo.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/iio/iio.h>
#include "iio_core.h"
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
/**
* struct iio_event_interface - chrdev interface for an event line
* @wait: wait queue to allow blocking reads of events
* @det_events: list of detected events
* @dev_attr_list: list of event interface sysfs attribute
* @flags: file operations related flags including busy flag.
* @group: event interface sysfs attribute group
* @read_lock: lock to protect kfifo read operations
*/
struct iio_event_interface {
wait_queue_head_t wait;
DECLARE_KFIFO(det_events, struct iio_event_data, 16);
struct list_head dev_attr_list;
unsigned long flags;
struct attribute_group group;
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
struct mutex read_lock;
};
bool iio_event_enabled(const struct iio_event_interface *ev_int)
{
return !!test_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
}
/**
* 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
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
*
* Note: The caller must make sure that this function is not running
* concurrently for the same indio_dev more than once.
*
* 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.
**/
int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
{
struct iio_event_interface *ev_int = indio_dev->event_interface;
struct iio_event_data ev;
int copied;
if (!ev_int)
return 0;
/* Does anyone care? */
if (iio_event_enabled(ev_int)) {
ev.id = ev_code;
ev.timestamp = timestamp;
copied = kfifo_put(&ev_int->det_events, ev);
if (copied != 0)
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
wake_up_poll(&ev_int->wait, POLLIN);
}
return 0;
}
EXPORT_SYMBOL(iio_push_event);
/**
* iio_event_poll() - poll the event queue to find out if it has data
* @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
*/
static unsigned int iio_event_poll(struct file *filep,
struct poll_table_struct *wait)
{
struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
unsigned int events = 0;
if (!indio_dev->info)
return events;
poll_wait(filep, &ev_int->wait, wait);
if (!kfifo_is_empty(&ev_int->det_events))
events = POLLIN | POLLRDNORM;
return events;
}
static ssize_t iio_event_chrdev_read(struct file *filep,
char __user *buf,
size_t count,
loff_t *f_ps)
{
struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
unsigned int copied;
int ret;
if (!indio_dev->info)
return -ENODEV;
if (count < sizeof(struct iio_event_data))
return -EINVAL;
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
do {
if (kfifo_is_empty(&ev_int->det_events)) {
if (filep->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(ev_int->wait,
!kfifo_is_empty(&ev_int->det_events) ||
indio_dev->info == NULL);
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
if (ret)
return ret;
if (indio_dev->info == NULL)
return -ENODEV;
}
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
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;
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
} while (copied == 0);
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
return copied;
}
static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
{
struct iio_dev *indio_dev = filep->private_data;
struct iio_event_interface *ev_int = indio_dev->event_interface;
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
iio_device_put(indio_dev);
return 0;
}
static const struct file_operations iio_event_chrdev_fileops = {
.read = iio_event_chrdev_read,
.poll = iio_event_poll,
.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;
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;
}
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
iio_device_get(indio_dev);
fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
indio_dev, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
iio_device_put(indio_dev);
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
} else {
kfifo_reset_out(&ev_int->det_events);
}
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
unlock:
mutex_unlock(&indio_dev->mlock);
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",
[IIO_EV_TYPE_CHANGE] = "change",
};
static const char * const iio_ev_dir_text[] = {
[IIO_EV_DIR_EITHER] = "either",
[IIO_EV_DIR_RISING] = "rising",
[IIO_EV_DIR_FALLING] = "falling"
};
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_ENABLE] = "en",
[IIO_EV_INFO_VALUE] = "value",
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
[IIO_EV_INFO_PERIOD] = "period",
[IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db",
[IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db",
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
};
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;
}
static ssize_t iio_ev_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
bool val;
ret = strtobool(buf, &val);
if (ret < 0)
return ret;
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);
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
return (ret < 0) ? ret : len;
}
static ssize_t iio_ev_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
int val;
val = indio_dev->info->read_event_config(indio_dev,
this_attr->c, iio_ev_attr_type(this_attr),
iio_ev_attr_dir(this_attr));
if (val < 0)
return val;
else
return sprintf(buf, "%d\n", val);
}
static ssize_t iio_ev_value_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, val2, val_arr[2];
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
int ret;
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;
val_arr[0] = val;
val_arr[1] = val2;
return iio_format_value(buf, ret, 2, val_arr);
}
static ssize_t iio_ev_value_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
int val, val2;
int ret;
if (!indio_dev->info->write_event_value)
return -EINVAL;
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);
if (ret < 0)
return ret;
return len;
}
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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;
for_each_set_bit(i, mask, sizeof(*mask)*8) {
if (i >= ARRAY_SIZE(iio_ev_info_text))
return -EINVAL;
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]);
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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);
if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
continue;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
if (ret)
return ret;
attrcount++;
}
return attrcount;
}
static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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)
return ret;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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)
return ret;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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)
return ret;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
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)
return ret;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
attrcount += ret;
}
ret = attrcount;
return ret;
}
static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
{
int j, ret, attrcount = 0;
/* Dynamically created from the channels array */
for (j = 0; j < indio_dev->num_channels; j++) {
ret = iio_device_add_event_sysfs(indio_dev,
&indio_dev->channels[j]);
if (ret < 0)
return ret;
attrcount += ret;
}
return attrcount;
}
static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
{
int j;
iio: Extend the event config interface The event configuration interface of the IIO framework has not been getting the same attention as other parts. As a result it has not seen the same improvements as e.g. the channel interface has seen with the introduction of the channel spec struct. Currently all the event config callbacks take a u64 (the so called event code) to pass all the different information about for which event the callback is invoked. The callback function then has to extract the information it is interested in using some macros with rather long names. Most information encoded in the event code comes straight from the iio_chan_spec struct the event was registered for. Since we always have a handle to the channel spec when we call the event callbacks the first step is to add the channel spec as a parameter to the event callbacks. The two remaining things encoded in the event code are the type and direction of the event. Instead of passing them in one parameter, add one parameter for each of them and remove the eventcode from the event callbacks. The patch also adds a new iio_event_info parameter to the {read,write}_event_value callbacks. This makes it possible, similar to the iio_chan_info_enum for channels, to specify additional properties other than just the value for an event. Furthermore the new interface will allow to register shared events. This is e.g. useful if a device allows configuring a threshold event, but the threshold setting is the same for all channels. To implement this the patch adds a new iio_event_spec struct which is similar to the iio_chan_spec struct. It as two field to specify the type and the direction of the event. Furthermore it has a mask field for each one of the different iio_shared_by types. These mask fields holds which kind of attributes should be registered for the event. Creation of the attributes follows the same rules as the for the channel attributes. E.g. for the separate_mask there will be a attribute for each channel with this event, for the shared_by_type there will only be one attribute per channel type. The iio_chan_spec struct gets two new fields, 'event_spec' and 'num_event_specs', which is used to specify which the events for this channel. These two fields are going to replace the channel's event_mask field. For now both the old and the new event config interface coexist, but over the few patches all drivers will be converted from the old to the new interface. Once that is done all code for supporting the old interface will be removed. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2013-10-07 22:11:00 +08:00
for (j = 0; j < indio_dev->num_channels; j++) {
if (indio_dev->channels[j].num_event_specs != 0)
return true;
}
return false;
}
static void iio_setup_ev_int(struct iio_event_interface *ev_int)
{
INIT_KFIFO(ev_int->det_events);
init_waitqueue_head(&ev_int->wait);
iio:event: Fix and cleanup locking The event code currently holds a spinlock with IRQs disabled while calling kfifo_to_user(). kfifo_to_user() can generate a page fault though, which means we have to be able to sleep, which is not possible if the interrupts are disabled. The good thing is that kfifo handles concurrent read and write access just fine as long as there is only one reader and one writer, so we do not any locking to protect against concurrent access from the read and writer thread. It is possible though that userspace is trying to read from the event FIFO from multiple concurrent threads, so we need to add locking to protect against this. This is done using a mutex. The mutex will only protect the kfifo_to_user() call, it will not protect the waitqueue. This means that multiple threads can be waiting for new data and once a new event is added to the FIFO all waiting threads will be woken up. If one of those threads is unable to read any data (because another thread already read all the data) it will go back to sleep. The only remaining issue is that now that the clearing of the BUSY flag and the emptying of the FIFO does no longer happen in one atomic step it is possible that a event is added to the FIFO after it has been emptied and this sample will be visible the next time a new event file descriptor is created. To avoid this rather move the emptying of the FIFO from iio_event_chrdev_release to iio_event_getfd(). Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2014-02-15 02:49:00 +08:00
mutex_init(&ev_int->read_lock);
}
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);
if (indio_dev->event_interface == NULL)
return -ENOMEM;
INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
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:
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
kfree(indio_dev->event_interface);
indio_dev->event_interface = NULL;
return ret;
}
/**
* 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);
}
void iio_device_unregister_eventset(struct iio_dev *indio_dev)
{
if (indio_dev->event_interface == NULL)
return;
iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
kfree(indio_dev->event_interface->group.attrs);
kfree(indio_dev->event_interface);
}