mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 15:13:52 +00:00
f73f7f4da5
With this change, an ioctl() call is added to open a character device for a buffer. The ioctl() number is 'i' 0x91, which follows the IIO_GET_EVENT_FD_IOCTL ioctl. The ioctl() will return an FD for the requested buffer index. The indexes are the same from the /sys/iio/devices/iio:deviceX/bufferY (i.e. the Y variable). Since there doesn't seem to be a sane way to return the FD for buffer0 to be the same FD for the /dev/iio:deviceX, this ioctl() will return another FD for buffer0 (or the first buffer). This duplicate FD will be able to access the same buffer object (for buffer0) as accessing directly the /dev/iio:deviceX chardev. Also, there is no IIO_BUFFER_GET_BUFFER_COUNT ioctl() implemented, as the index for each buffer (and the count) can be deduced from the '/sys/bus/iio/devices/iio:deviceX/bufferY' folders (i.e the number of bufferY folders). Used following C code to test this: ------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <fcntl.h" #include <errno.h> #define IIO_BUFFER_GET_FD_IOCTL _IOWR('i', 0x91, int) int main(int argc, char *argv[]) { int fd; int fd1; int ret; if ((fd = open("/dev/iio:device0", O_RDWR))<0) { fprintf(stderr, "Error open() %d errno %d\n",fd, errno); return -1; } fprintf(stderr, "Using FD %d\n", fd); fd1 = atoi(argv[1]); ret = ioctl(fd, IIO_BUFFER_GET_FD_IOCTL, &fd1); if (ret < 0) { fprintf(stderr, "Error for buffer %d ioctl() %d errno %d\n", fd1, ret, errno); close(fd); return -1; } fprintf(stderr, "Got FD %d\n", fd1); close(fd1); close(fd); return 0; } ------------------------------------------------------------------- Results are: ------------------------------------------------------------------- # ./test 0 Using FD 3 Got FD 4 # ./test 1 Using FD 3 Got FD 4 # ./test 2 Using FD 3 Got FD 4 # ./test 3 Using FD 3 Got FD 4 # ls /sys/bus/iio/devices/iio\:device0 buffer buffer0 buffer1 buffer2 buffer3 dev in_voltage_sampling_frequency in_voltage_scale in_voltage_scale_available name of_node power scan_elements subsystem uevent ------------------------------------------------------------------- iio:device0 has some fake kfifo buffers attached to an IIO device. Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com> Link: https://lore.kernel.org/r/20210215104043.91251-21-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
108 lines
3.1 KiB
C
108 lines
3.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/* The industrial I/O core function defs.
|
|
*
|
|
* Copyright (c) 2008 Jonathan Cameron
|
|
*
|
|
* These definitions are meant for use only within the IIO core, not individual
|
|
* drivers.
|
|
*/
|
|
|
|
#ifndef _IIO_CORE_H_
|
|
#define _IIO_CORE_H_
|
|
#include <linux/kernel.h>
|
|
#include <linux/device.h>
|
|
|
|
struct iio_buffer;
|
|
struct iio_chan_spec;
|
|
struct iio_dev;
|
|
|
|
extern struct device_type iio_device_type;
|
|
|
|
struct iio_dev_buffer_pair {
|
|
struct iio_dev *indio_dev;
|
|
struct iio_buffer *buffer;
|
|
};
|
|
|
|
#define IIO_IOCTL_UNHANDLED 1
|
|
struct iio_ioctl_handler {
|
|
struct list_head entry;
|
|
long (*ioctl)(struct iio_dev *indio_dev, struct file *filp,
|
|
unsigned int cmd, unsigned long arg);
|
|
};
|
|
|
|
long iio_device_ioctl(struct iio_dev *indio_dev, struct file *filp,
|
|
unsigned int cmd, unsigned long arg);
|
|
|
|
void iio_device_ioctl_handler_register(struct iio_dev *indio_dev,
|
|
struct iio_ioctl_handler *h);
|
|
void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);
|
|
|
|
int __iio_add_chan_devattr(const char *postfix,
|
|
struct iio_chan_spec const *chan,
|
|
ssize_t (*func)(struct device *dev,
|
|
struct device_attribute *attr,
|
|
char *buf),
|
|
ssize_t (*writefunc)(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf,
|
|
size_t len),
|
|
u64 mask,
|
|
enum iio_shared_by shared_by,
|
|
struct device *dev,
|
|
struct iio_buffer *buffer,
|
|
struct list_head *attr_list);
|
|
void iio_free_chan_devattr_list(struct list_head *attr_list);
|
|
|
|
int iio_device_register_sysfs_group(struct iio_dev *indio_dev,
|
|
const struct attribute_group *group);
|
|
|
|
ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals);
|
|
|
|
/* Event interface flags */
|
|
#define IIO_BUSY_BIT_POS 1
|
|
|
|
#ifdef CONFIG_IIO_BUFFER
|
|
struct poll_table_struct;
|
|
|
|
__poll_t iio_buffer_poll_wrapper(struct file *filp,
|
|
struct poll_table_struct *wait);
|
|
ssize_t iio_buffer_read_wrapper(struct file *filp, char __user *buf,
|
|
size_t n, loff_t *f_ps);
|
|
|
|
int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
|
|
void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev);
|
|
|
|
#define iio_buffer_poll_addr (&iio_buffer_poll_wrapper)
|
|
#define iio_buffer_read_outer_addr (&iio_buffer_read_wrapper)
|
|
|
|
void iio_disable_all_buffers(struct iio_dev *indio_dev);
|
|
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
|
|
void iio_buffers_put(struct iio_dev *indio_dev);
|
|
|
|
#else
|
|
|
|
#define iio_buffer_poll_addr NULL
|
|
#define iio_buffer_read_outer_addr NULL
|
|
|
|
static inline int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) {}
|
|
|
|
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
|
|
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
|
|
static inline void iio_buffers_put(struct iio_dev *indio_dev) {}
|
|
|
|
#endif
|
|
|
|
int iio_device_register_eventset(struct iio_dev *indio_dev);
|
|
void iio_device_unregister_eventset(struct iio_dev *indio_dev);
|
|
void iio_device_wakeup_eventset(struct iio_dev *indio_dev);
|
|
|
|
struct iio_event_interface;
|
|
bool iio_event_enabled(const struct iio_event_interface *ev_int);
|
|
|
|
#endif
|