Re: [PATCH v6 20/24] iio: buffer: add ioctl() to support opening extra buffers for IIO device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2/15/21 11:40 AM, Alexandru Ardelean wrote:
[...]
  /**
   * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
   * @indio_dev: The IIO device
@@ -1343,6 +1371,96 @@ static void iio_buffer_unregister_legacy_sysfs_groups(struct iio_dev *indio_dev)
  	kfree(iio_dev_opaque->legacy_scan_el_group.attrs);
  }
[...]
+static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg)
+{
+	struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
+	int __user *ival = (int __user *)arg;
+	struct iio_dev_buffer_pair *ib;
+	struct iio_buffer *buffer;
+	int fd, idx, ret;
+
+	if (copy_from_user(&idx, ival, sizeof(idx)))
+		return -EFAULT;

If we only want to pass an int, we can pass that directly, no need to pass it as a pointer.

int fd = arg;

+
+	if (idx >= iio_dev_opaque->attached_buffers_cnt)
+		return -ENODEV;
+
+	iio_device_get(indio_dev);
+
+	buffer = iio_dev_opaque->attached_buffers[idx];
+
+	if (test_and_set_bit(IIO_BUSY_BIT_POS, &buffer->flags)) {
+		ret = -EBUSY;
+		goto error_iio_dev_put;
+	}
+
+	ib = kzalloc(sizeof(*ib), GFP_KERNEL);
+	if (!ib) {
+		ret = -ENOMEM;
+		goto error_clear_busy_bit;
+	}
+
+	ib->indio_dev = indio_dev;
+	ib->buffer = buffer;
+
+	fd = anon_inode_getfd("iio:buffer", &iio_buffer_chrdev_fileops,
+			      ib, O_RDWR | O_CLOEXEC);

I wonder if we need to allow to pass flags, like e.g. O_NONBLOCK.

Something like https://elixir.bootlin.com/linux/latest/source/fs/signalfd.c#L288

+	if (fd < 0) {
+		ret = fd;
+		goto error_free_ib;
+	}
+
+	if (copy_to_user(ival, &fd, sizeof(fd))) {
+		put_unused_fd(fd);
+		ret = -EFAULT;
+		goto error_free_ib;
+	}

Here we copy back the fd, but also return it. Just return is probably enough.

+
+	return fd;
+
+error_free_ib:
+	kfree(ib);
+error_clear_busy_bit:
+	clear_bit(IIO_BUSY_BIT_POS, &buffer->flags);
+error_iio_dev_put:
+	iio_device_put(indio_dev);
+	return ret;
+}
[...]
diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
index b6ebc04af3e7..32addd5e790e 100644
--- a/include/linux/iio/iio-opaque.h
+++ b/include/linux/iio/iio-opaque.h
@@ -9,6 +9,7 @@
   * @event_interface:		event chrdevs associated with interrupt lines
   * @attached_buffers:		array of buffers statically attached by the driver
   * @attached_buffers_cnt:	number of buffers in the array of statically attached buffers
+ * @buffer_ioctl_handler:	ioctl() handler for this IIO device's buffer interface
   * @buffer_list:		list of all buffers currently attached
   * @channel_attr_list:		keep track of automatically created channel
   *				attributes
@@ -28,6 +29,7 @@ struct iio_dev_opaque {
  	struct iio_event_interface	*event_interface;
  	struct iio_buffer		**attached_buffers;
  	unsigned int			attached_buffers_cnt;
+	struct iio_ioctl_handler	*buffer_ioctl_handler;

Can we just embedded this struct so we do not have to allocate/deallocate it?

  	struct list_head		buffer_list;
  	struct list_head		channel_attr_list;
  	struct attribute_group		chan_attr_group;





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux