brintos

brintos / linux-shallow public Read only

0
0
Text · 17.4 KiB · db06501 Raw
672 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Industrial I/O event handling3 *4 * Copyright (c) 2008 Jonathan Cameron5 *6 * Based on elements of hwmon and input subsystems.7 */8 9#include <linux/anon_inodes.h>10#include <linux/device.h>11#include <linux/fs.h>12#include <linux/kernel.h>13#include <linux/kfifo.h>14#include <linux/module.h>15#include <linux/poll.h>16#include <linux/sched.h>17#include <linux/slab.h>18#include <linux/uaccess.h>19#include <linux/wait.h>20#include <linux/iio/iio.h>21#include <linux/iio/iio-opaque.h>22#include "iio_core.h"23#include <linux/iio/sysfs.h>24#include <linux/iio/events.h>25 26/**27 * struct iio_event_interface - chrdev interface for an event line28 * @wait:		wait queue to allow blocking reads of events29 * @det_events:		list of detected events30 * @dev_attr_list:	list of event interface sysfs attribute31 * @flags:		file operations related flags including busy flag.32 * @group:		event interface sysfs attribute group33 * @read_lock:		lock to protect kfifo read operations34 * @ioctl_handler:	handler for event ioctl() calls35 */36struct iio_event_interface {37	wait_queue_head_t	wait;38	DECLARE_KFIFO(det_events, struct iio_event_data, 16);39 40	struct list_head	dev_attr_list;41	unsigned long		flags;42	struct attribute_group	group;43	struct mutex		read_lock;44	struct iio_ioctl_handler	ioctl_handler;45};46 47bool iio_event_enabled(const struct iio_event_interface *ev_int)48{49	return !!test_bit(IIO_BUSY_BIT_POS, &ev_int->flags);50}51 52/**53 * iio_push_event() - try to add event to the list for userspace reading54 * @indio_dev:		IIO device structure55 * @ev_code:		What event56 * @timestamp:		When the event occurred57 *58 * Note: The caller must make sure that this function is not running59 * concurrently for the same indio_dev more than once.60 *61 * This function may be safely used as soon as a valid reference to iio_dev has62 * been obtained via iio_device_alloc(), but any events that are submitted63 * before iio_device_register() has successfully completed will be silently64 * discarded.65 **/66int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)67{68	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);69	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;70	struct iio_event_data ev;71	int copied;72 73	if (!ev_int)74		return 0;75 76	/* Does anyone care? */77	if (iio_event_enabled(ev_int)) {78 79		ev.id = ev_code;80		ev.timestamp = timestamp;81 82		copied = kfifo_put(&ev_int->det_events, ev);83		if (copied != 0)84			wake_up_poll(&ev_int->wait, EPOLLIN);85	}86 87	return 0;88}89EXPORT_SYMBOL(iio_push_event);90 91/**92 * iio_event_poll() - poll the event queue to find out if it has data93 * @filep:	File structure pointer to identify the device94 * @wait:	Poll table pointer to add the wait queue on95 *96 * Return: (EPOLLIN | EPOLLRDNORM) if data is available for reading97 *	   or a negative error code on failure98 */99static __poll_t iio_event_poll(struct file *filep,100			     struct poll_table_struct *wait)101{102	struct iio_dev *indio_dev = filep->private_data;103	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);104	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;105	__poll_t events = 0;106 107	if (!indio_dev->info)108		return events;109 110	poll_wait(filep, &ev_int->wait, wait);111 112	if (!kfifo_is_empty(&ev_int->det_events))113		events = EPOLLIN | EPOLLRDNORM;114 115	return events;116}117 118static ssize_t iio_event_chrdev_read(struct file *filep,119				     char __user *buf,120				     size_t count,121				     loff_t *f_ps)122{123	struct iio_dev *indio_dev = filep->private_data;124	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);125	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;126	unsigned int copied;127	int ret;128 129	if (!indio_dev->info)130		return -ENODEV;131 132	if (count < sizeof(struct iio_event_data))133		return -EINVAL;134 135	do {136		if (kfifo_is_empty(&ev_int->det_events)) {137			if (filep->f_flags & O_NONBLOCK)138				return -EAGAIN;139 140			ret = wait_event_interruptible(ev_int->wait,141					!kfifo_is_empty(&ev_int->det_events) ||142					indio_dev->info == NULL);143			if (ret)144				return ret;145			if (indio_dev->info == NULL)146				return -ENODEV;147		}148 149		if (mutex_lock_interruptible(&ev_int->read_lock))150			return -ERESTARTSYS;151		ret = kfifo_to_user(&ev_int->det_events, buf, count, &copied);152		mutex_unlock(&ev_int->read_lock);153 154		if (ret)155			return ret;156 157		/*158		 * If we couldn't read anything from the fifo (a different159		 * thread might have been faster) we either return -EAGAIN if160		 * the file descriptor is non-blocking, otherwise we go back to161		 * sleep and wait for more data to arrive.162		 */163		if (copied == 0 && (filep->f_flags & O_NONBLOCK))164			return -EAGAIN;165 166	} while (copied == 0);167 168	return copied;169}170 171static int iio_event_chrdev_release(struct inode *inode, struct file *filep)172{173	struct iio_dev *indio_dev = filep->private_data;174	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);175	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;176 177	clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);178 179	iio_device_put(indio_dev);180 181	return 0;182}183 184static const struct file_operations iio_event_chrdev_fileops = {185	.read =  iio_event_chrdev_read,186	.poll =  iio_event_poll,187	.release = iio_event_chrdev_release,188	.owner = THIS_MODULE,189	.llseek = noop_llseek,190};191 192static int iio_event_getfd(struct iio_dev *indio_dev)193{194	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);195	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;196	int fd;197 198	if (ev_int == NULL)199		return -ENODEV;200 201	fd = mutex_lock_interruptible(&iio_dev_opaque->mlock);202	if (fd)203		return fd;204 205	if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {206		fd = -EBUSY;207		goto unlock;208	}209 210	iio_device_get(indio_dev);211 212	fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,213				indio_dev, O_RDONLY | O_CLOEXEC);214	if (fd < 0) {215		clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);216		iio_device_put(indio_dev);217	} else {218		kfifo_reset_out(&ev_int->det_events);219	}220 221unlock:222	mutex_unlock(&iio_dev_opaque->mlock);223	return fd;224}225 226static const char * const iio_ev_type_text[] = {227	[IIO_EV_TYPE_THRESH] = "thresh",228	[IIO_EV_TYPE_MAG] = "mag",229	[IIO_EV_TYPE_ROC] = "roc",230	[IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",231	[IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",232	[IIO_EV_TYPE_CHANGE] = "change",233	[IIO_EV_TYPE_MAG_REFERENCED] = "mag_referenced",234	[IIO_EV_TYPE_GESTURE] = "gesture",235};236 237static const char * const iio_ev_dir_text[] = {238	[IIO_EV_DIR_EITHER] = "either",239	[IIO_EV_DIR_RISING] = "rising",240	[IIO_EV_DIR_FALLING] = "falling",241	[IIO_EV_DIR_SINGLETAP] = "singletap",242	[IIO_EV_DIR_DOUBLETAP] = "doubletap",243};244 245static const char * const iio_ev_info_text[] = {246	[IIO_EV_INFO_ENABLE] = "en",247	[IIO_EV_INFO_VALUE] = "value",248	[IIO_EV_INFO_HYSTERESIS] = "hysteresis",249	[IIO_EV_INFO_PERIOD] = "period",250	[IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db",251	[IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db",252	[IIO_EV_INFO_TIMEOUT] = "timeout",253	[IIO_EV_INFO_RESET_TIMEOUT] = "reset_timeout",254	[IIO_EV_INFO_TAP2_MIN_DELAY] = "tap2_min_delay",255	[IIO_EV_INFO_RUNNING_PERIOD] = "runningperiod",256	[IIO_EV_INFO_RUNNING_COUNT] = "runningcount",257};258 259static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)260{261	return attr->c->event_spec[attr->address & 0xffff].dir;262}263 264static enum iio_event_type iio_ev_attr_type(struct iio_dev_attr *attr)265{266	return attr->c->event_spec[attr->address & 0xffff].type;267}268 269static enum iio_event_info iio_ev_attr_info(struct iio_dev_attr *attr)270{271	return (attr->address >> 16) & 0xffff;272}273 274static ssize_t iio_ev_state_store(struct device *dev,275				  struct device_attribute *attr,276				  const char *buf,277				  size_t len)278{279	struct iio_dev *indio_dev = dev_to_iio_dev(dev);280	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);281	int ret;282	bool val;283 284	ret = kstrtobool(buf, &val);285	if (ret < 0)286		return ret;287 288	if (!indio_dev->info->write_event_config)289		return -EINVAL;290 291	ret = indio_dev->info->write_event_config(indio_dev,292		this_attr->c, iio_ev_attr_type(this_attr),293		iio_ev_attr_dir(this_attr), val);294 295	return (ret < 0) ? ret : len;296}297 298static ssize_t iio_ev_state_show(struct device *dev,299				 struct device_attribute *attr,300				 char *buf)301{302	struct iio_dev *indio_dev = dev_to_iio_dev(dev);303	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);304	int val;305 306	if (!indio_dev->info->read_event_config)307		return -EINVAL;308 309	val = indio_dev->info->read_event_config(indio_dev,310		this_attr->c, iio_ev_attr_type(this_attr),311		iio_ev_attr_dir(this_attr));312	if (val < 0)313		return val;314	else315		return sysfs_emit(buf, "%d\n", val);316}317 318static ssize_t iio_ev_value_show(struct device *dev,319				 struct device_attribute *attr,320				 char *buf)321{322	struct iio_dev *indio_dev = dev_to_iio_dev(dev);323	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);324	int val, val2, val_arr[2];325	int ret;326 327	if (!indio_dev->info->read_event_value)328		return -EINVAL;329 330	ret = indio_dev->info->read_event_value(indio_dev,331		this_attr->c, iio_ev_attr_type(this_attr),332		iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),333		&val, &val2);334	if (ret < 0)335		return ret;336	val_arr[0] = val;337	val_arr[1] = val2;338	return iio_format_value(buf, ret, 2, val_arr);339}340 341static ssize_t iio_ev_value_store(struct device *dev,342				  struct device_attribute *attr,343				  const char *buf,344				  size_t len)345{346	struct iio_dev *indio_dev = dev_to_iio_dev(dev);347	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);348	int val, val2;349	int ret;350 351	if (!indio_dev->info->write_event_value)352		return -EINVAL;353 354	ret = iio_str_to_fixpoint(buf, 100000, &val, &val2);355	if (ret)356		return ret;357	ret = indio_dev->info->write_event_value(indio_dev,358		this_attr->c, iio_ev_attr_type(this_attr),359		iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),360		val, val2);361	if (ret < 0)362		return ret;363 364	return len;365}366 367static ssize_t iio_ev_label_show(struct device *dev,368				 struct device_attribute *attr,369				 char *buf)370{371	struct iio_dev *indio_dev = dev_to_iio_dev(dev);372	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);373 374	if (indio_dev->info->read_event_label)375		return indio_dev->info->read_event_label(indio_dev,376				 this_attr->c, iio_ev_attr_type(this_attr),377				 iio_ev_attr_dir(this_attr), buf);378 379	return -EINVAL;380}381 382static int iio_device_add_event(struct iio_dev *indio_dev,383	const struct iio_chan_spec *chan, unsigned int spec_index,384	enum iio_event_type type, enum iio_event_direction dir,385	enum iio_shared_by shared_by, const unsigned long *mask)386{387	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);388	ssize_t (*show)(struct device *dev, struct device_attribute *attr,389		char *buf);390	ssize_t (*store)(struct device *dev, struct device_attribute *attr,391		const char *buf, size_t len);392	unsigned int attrcount = 0;393	unsigned int i;394	char *postfix;395	int ret;396 397	for_each_set_bit(i, mask, sizeof(*mask)*8) {398		if (i >= ARRAY_SIZE(iio_ev_info_text))399			return -EINVAL;400		if (dir != IIO_EV_DIR_NONE)401			postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",402					iio_ev_type_text[type],403					iio_ev_dir_text[dir],404					iio_ev_info_text[i]);405		else406			postfix = kasprintf(GFP_KERNEL, "%s_%s",407					iio_ev_type_text[type],408					iio_ev_info_text[i]);409		if (postfix == NULL)410			return -ENOMEM;411 412		if (i == IIO_EV_INFO_ENABLE) {413			show = iio_ev_state_show;414			store = iio_ev_state_store;415		} else {416			show = iio_ev_value_show;417			store = iio_ev_value_store;418		}419 420		ret = __iio_add_chan_devattr(postfix, chan, show, store,421			 (i << 16) | spec_index, shared_by, &indio_dev->dev,422			 NULL,423			&iio_dev_opaque->event_interface->dev_attr_list);424		kfree(postfix);425 426		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))427			continue;428 429		if (ret)430			return ret;431 432		attrcount++;433	}434 435	return attrcount;436}437 438static int iio_device_add_event_label(struct iio_dev *indio_dev,439				      const struct iio_chan_spec *chan,440				      unsigned int spec_index,441				      enum iio_event_type type,442				      enum iio_event_direction dir)443{444	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);445	char *postfix;446	int ret;447 448	if (!indio_dev->info->read_event_label)449		return 0;450 451	if (dir != IIO_EV_DIR_NONE)452		postfix = kasprintf(GFP_KERNEL, "%s_%s_label",453				iio_ev_type_text[type],454				iio_ev_dir_text[dir]);455	else456		postfix = kasprintf(GFP_KERNEL, "%s_label",457				iio_ev_type_text[type]);458	if (postfix == NULL)459		return -ENOMEM;460 461	ret = __iio_add_chan_devattr(postfix, chan, &iio_ev_label_show, NULL,462				spec_index, IIO_SEPARATE, &indio_dev->dev, NULL,463				&iio_dev_opaque->event_interface->dev_attr_list);464 465	kfree(postfix);466 467	if (ret < 0)468		return ret;469 470	return 1;471}472 473static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,474	struct iio_chan_spec const *chan)475{476	int ret = 0, i, attrcount = 0;477	enum iio_event_direction dir;478	enum iio_event_type type;479 480	for (i = 0; i < chan->num_event_specs; i++) {481		type = chan->event_spec[i].type;482		dir = chan->event_spec[i].dir;483 484		ret = iio_device_add_event(indio_dev, chan, i, type, dir,485			IIO_SEPARATE, &chan->event_spec[i].mask_separate);486		if (ret < 0)487			return ret;488		attrcount += ret;489 490		ret = iio_device_add_event(indio_dev, chan, i, type, dir,491			IIO_SHARED_BY_TYPE,492			&chan->event_spec[i].mask_shared_by_type);493		if (ret < 0)494			return ret;495		attrcount += ret;496 497		ret = iio_device_add_event(indio_dev, chan, i, type, dir,498			IIO_SHARED_BY_DIR,499			&chan->event_spec[i].mask_shared_by_dir);500		if (ret < 0)501			return ret;502		attrcount += ret;503 504		ret = iio_device_add_event(indio_dev, chan, i, type, dir,505			IIO_SHARED_BY_ALL,506			&chan->event_spec[i].mask_shared_by_all);507		if (ret < 0)508			return ret;509		attrcount += ret;510 511		ret = iio_device_add_event_label(indio_dev, chan, i, type, dir);512		if (ret < 0)513			return ret;514		attrcount += ret;515	}516	ret = attrcount;517	return ret;518}519 520static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)521{522	int j, ret, attrcount = 0;523 524	/* Dynamically created from the channels array */525	for (j = 0; j < indio_dev->num_channels; j++) {526		ret = iio_device_add_event_sysfs(indio_dev,527						 &indio_dev->channels[j]);528		if (ret < 0)529			return ret;530		attrcount += ret;531	}532	return attrcount;533}534 535static bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)536{537	int j;538 539	for (j = 0; j < indio_dev->num_channels; j++) {540		if (indio_dev->channels[j].num_event_specs != 0)541			return true;542	}543	return false;544}545 546static void iio_setup_ev_int(struct iio_event_interface *ev_int)547{548	INIT_KFIFO(ev_int->det_events);549	init_waitqueue_head(&ev_int->wait);550	mutex_init(&ev_int->read_lock);551}552 553static long iio_event_ioctl(struct iio_dev *indio_dev, struct file *filp,554			    unsigned int cmd, unsigned long arg)555{556	int __user *ip = (int __user *)arg;557	int fd;558 559	if (cmd == IIO_GET_EVENT_FD_IOCTL) {560		fd = iio_event_getfd(indio_dev);561		if (fd < 0)562			return fd;563		if (copy_to_user(ip, &fd, sizeof(fd)))564			return -EFAULT;565		return 0;566	}567 568	return IIO_IOCTL_UNHANDLED;569}570 571static const char *iio_event_group_name = "events";572int iio_device_register_eventset(struct iio_dev *indio_dev)573{574	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);575	struct iio_event_interface *ev_int;576	struct iio_dev_attr *p;577	int ret = 0, attrcount_orig = 0, attrcount, attrn;578	struct attribute **attr;579 580	if (!(indio_dev->info->event_attrs ||581	      iio_check_for_dynamic_events(indio_dev)))582		return 0;583 584	ev_int = kzalloc(sizeof(*ev_int), GFP_KERNEL);585	if (!ev_int)586		return -ENOMEM;587 588	iio_dev_opaque->event_interface = ev_int;589 590	INIT_LIST_HEAD(&ev_int->dev_attr_list);591 592	iio_setup_ev_int(ev_int);593	if (indio_dev->info->event_attrs != NULL) {594		attr = indio_dev->info->event_attrs->attrs;595		while (*attr++ != NULL)596			attrcount_orig++;597	}598	attrcount = attrcount_orig;599	if (indio_dev->channels) {600		ret = __iio_add_event_config_attrs(indio_dev);601		if (ret < 0)602			goto error_free_setup_event_lines;603		attrcount += ret;604	}605 606	ev_int->group.name = iio_event_group_name;607	ev_int->group.attrs = kcalloc(attrcount + 1,608				      sizeof(ev_int->group.attrs[0]),609				      GFP_KERNEL);610	if (ev_int->group.attrs == NULL) {611		ret = -ENOMEM;612		goto error_free_setup_event_lines;613	}614	if (indio_dev->info->event_attrs)615		memcpy(ev_int->group.attrs,616		       indio_dev->info->event_attrs->attrs,617		       sizeof(ev_int->group.attrs[0]) * attrcount_orig);618	attrn = attrcount_orig;619	/* Add all elements from the list. */620	list_for_each_entry(p, &ev_int->dev_attr_list, l)621		ev_int->group.attrs[attrn++] = &p->dev_attr.attr;622 623	ret = iio_device_register_sysfs_group(indio_dev, &ev_int->group);624	if (ret)625		goto error_free_group_attrs;626 627	ev_int->ioctl_handler.ioctl = iio_event_ioctl;628	iio_device_ioctl_handler_register(&iio_dev_opaque->indio_dev,629					  &ev_int->ioctl_handler);630 631	return 0;632 633error_free_group_attrs:634	kfree(ev_int->group.attrs);635error_free_setup_event_lines:636	iio_free_chan_devattr_list(&ev_int->dev_attr_list);637	kfree(ev_int);638	iio_dev_opaque->event_interface = NULL;639	return ret;640}641 642/**643 * iio_device_wakeup_eventset - Wakes up the event waitqueue644 * @indio_dev: The IIO device645 *646 * Wakes up the event waitqueue used for poll() and blocking read().647 * Should usually be called when the device is unregistered.648 */649void iio_device_wakeup_eventset(struct iio_dev *indio_dev)650{651	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);652 653	if (iio_dev_opaque->event_interface == NULL)654		return;655	wake_up(&iio_dev_opaque->event_interface->wait);656}657 658void iio_device_unregister_eventset(struct iio_dev *indio_dev)659{660	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);661	struct iio_event_interface *ev_int = iio_dev_opaque->event_interface;662 663	if (ev_int == NULL)664		return;665 666	iio_device_ioctl_handler_unregister(&ev_int->ioctl_handler);667	iio_free_chan_devattr_list(&ev_int->dev_attr_list);668	kfree(ev_int->group.attrs);669	kfree(ev_int);670	iio_dev_opaque->event_interface = NULL;671}672