Re: [Uclinux-dist-devel] IIO ring buffer

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

 



An example(adis16209) to use the new ring/trigger:
1. adis16209_ring.c and adis16209_trigger.c are not necessary and use common api
2. provide callback for set_irq and hw_read_ring to common ring/trigger module

Index: drivers/staging/iio/accel/adis16209_ring.c
===================================================================
--- drivers/staging/iio/accel/adis16209_ring.c	(revision 8893)
+++ drivers/staging/iio/accel/adis16209_ring.c	(working copy)
@@ -1,267 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../ring_sw.h"
-#include "accel.h"
-#include "../trigger.h"
-#include "adis16209.h"
-
-/**
- * combine_8_to_16() utility function to munge to u8s into u16
- **/
-static inline u16 combine_8_to_16(u8 lower, u8 upper)
-{
-	u16 _lower = lower;
-	u16 _upper = upper;
-	return _lower | (_upper << 8);
-}
-
-static IIO_SCAN_EL_C(supply, ADIS16209_SCAN_SUPPLY, IIO_UNSIGNED(14),
-		     ADIS16209_SUPPLY_OUT, NULL);
-static IIO_SCAN_EL_C(accel_x, ADIS16209_SCAN_ACC_X, IIO_SIGNED(14),
-		     ADIS16209_XACCL_OUT, NULL);
-static IIO_SCAN_EL_C(accel_y, ADIS16209_SCAN_ACC_Y, IIO_SIGNED(14),
-		     ADIS16209_YACCL_OUT, NULL);
-static IIO_SCAN_EL_C(aux_adc, ADIS16209_SCAN_AUX_ADC, IIO_UNSIGNED(12),
-		     ADIS16209_AUX_ADC, NULL);
-static IIO_SCAN_EL_C(temp, ADIS16209_SCAN_TEMP, IIO_UNSIGNED(12),
-		     ADIS16209_TEMP_OUT, NULL);
-static IIO_SCAN_EL_C(incli_x, ADIS16209_SCAN_INCLI_X, IIO_SIGNED(14),
-		     ADIS16209_XINCL_OUT, NULL);
-static IIO_SCAN_EL_C(incli_y, ADIS16209_SCAN_INCLI_Y, IIO_SIGNED(14),
-		     ADIS16209_YINCL_OUT, NULL);
-static IIO_SCAN_EL_C(rot, ADIS16209_SCAN_ROT, IIO_SIGNED(14),
-		     ADIS16209_ROT_OUT, NULL);
-
-static IIO_SCAN_EL_TIMESTAMP(8);
-
-static struct attribute *adis16209_scan_el_attrs[] = {
-	&iio_scan_el_supply.dev_attr.attr,
-	&iio_scan_el_accel_x.dev_attr.attr,
-	&iio_scan_el_accel_y.dev_attr.attr,
-	&iio_scan_el_aux_adc.dev_attr.attr,
-	&iio_scan_el_temp.dev_attr.attr,
-	&iio_scan_el_incli_x.dev_attr.attr,
-	&iio_scan_el_incli_y.dev_attr.attr,
-	&iio_scan_el_rot.dev_attr.attr,
-	&iio_scan_el_timestamp.dev_attr.attr,
-	NULL,
-};
-
-static struct attribute_group adis16209_scan_el_group = {
-	.attrs = adis16209_scan_el_attrs,
-	.name = "scan_elements",
-};
-
-/**
- * adis16209_poll_func_th() top half interrupt handler called by trigger
- * @private_data:	iio_dev
- **/
-static void adis16209_poll_func_th(struct iio_dev *indio_dev)
-{
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
-	st->last_timestamp = indio_dev->trig->timestamp;
-	schedule_work(&st->work_trigger_to_ring);
-}
-
-/**
- * adis16209_read_ring_data() read data registers which will be
placed into ring
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read
- **/
-static int adis16209_read_ring_data(struct device *dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
-	int ret;
-	int i;
-
-	mutex_lock(&st->buf_lock);
-
-	spi_message_init(&msg);
-
-	memset(xfers, 0, sizeof(xfers));
-	for (i = 0; i <= ADIS16209_OUTPUTS; i++) {
-		xfers[i].bits_per_word = 8;
-		xfers[i].cs_change = 1;
-		xfers[i].len = 2;
-		xfers[i].delay_usecs = 30;
-		xfers[i].tx_buf = st->tx + 2 * i;
-		st->tx[2 * i]
-			= ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i);
-		st->tx[2 * i + 1] = 0;
-		if (i >= 1)
-			xfers[i].rx_buf = rx + 2 * (i - 1);
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device
- * specific to be rolled into the core.
- */
-static void adis16209_trigger_bh_to_ring(struct work_struct *work_s)
-{
-	struct adis16209_state *st
-		= container_of(work_s, struct adis16209_state,
-			       work_trigger_to_ring);
-
-	int i = 0;
-	s16 *data;
-	size_t datasize = st->indio_dev
-		->ring->access.get_bpd(st->indio_dev->ring);
-
-	data = kmalloc(datasize , GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed in ring bh");
-		return;
-	}
-
-	if (st->indio_dev->scan_count)
-		if (adis16209_read_ring_data(&st->indio_dev->dev, st->rx) >= 0)
-			for (; i < st->indio_dev->scan_count; i++) {
-				data[i] = combine_8_to_16(st->rx[i*2+1],
-							  st->rx[i*2]);
-			}
-
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (st->indio_dev->scan_timestamp)
-		*((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
-
-	st->indio_dev->ring->access.store_to(st->indio_dev->ring,
-					    (u8 *)data,
-					    st->last_timestamp);
-
-	iio_trigger_notify_done(st->indio_dev->trig);
-	kfree(data);
-
-	return;
-}
-
-/* in these circumstances is it better to go with unaligned packing and
- * deal with the cost?*/
-static int adis16209_data_rdy_ring_preenable(struct iio_dev *indio_dev)
-{
-	size_t size;
-	dev_dbg(&indio_dev->dev, "%s\n", __func__);
-	/* Check if there are any scan elements enabled, if not fail*/
-	if (!(indio_dev->scan_count || indio_dev->scan_timestamp))
-		return -EINVAL;
-
-	if (indio_dev->ring->access.set_bpd) {
-		if (indio_dev->scan_timestamp)
-			if (indio_dev->scan_count)
-				/* Timestamp (aligned to s64) and data */
-				size = (((indio_dev->scan_count * sizeof(s16))
-					 + sizeof(s64) - 1)
-					& ~(sizeof(s64) - 1))
-					+ sizeof(s64);
-			else /* Timestamp only  */
-				size = sizeof(s64);
-		else /* Data only */
-			size = indio_dev->scan_count*sizeof(s16);
-		indio_dev->ring->access.set_bpd(indio_dev->ring, size);
-	}
-
-	return 0;
-}
-
-static int adis16209_data_rdy_ring_postenable(struct iio_dev *indio_dev)
-{
-	return indio_dev->trig
-		? iio_trigger_attach_poll_func(indio_dev->trig,
-					       indio_dev->pollfunc)
-		: 0;
-}
-
-static int adis16209_data_rdy_ring_predisable(struct iio_dev *indio_dev)
-{
-	return indio_dev->trig
-		? iio_trigger_dettach_poll_func(indio_dev->trig,
-						indio_dev->pollfunc)
-		: 0;
-}
-
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-	kfree(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->ring);
-}
-
-int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-	int ret = 0;
-	struct adis16209_state *st = indio_dev->dev_data;
-	struct iio_ring_buffer *ring;
-	INIT_WORK(&st->work_trigger_to_ring, adis16209_trigger_bh_to_ring);
-	/* Set default scan mode */
-
-	iio_scan_mask_set(indio_dev, iio_scan_el_supply.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_rot.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_accel_x.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_accel_y.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_temp.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_aux_adc.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_incli_x.number);
-	iio_scan_mask_set(indio_dev, iio_scan_el_incli_y.number);
-	indio_dev->scan_timestamp = true;
-
-	indio_dev->scan_el_attrs = &adis16209_scan_el_group;
-
-	ring = iio_sw_rb_allocate(indio_dev);
-	if (!ring) {
-		ret = -ENOMEM;
-		return ret;
-	}
-	indio_dev->ring = ring;
-	/* Effectively select the ring buffer implementation */
-	iio_ring_sw_register_funcs(&ring->access);
-	ring->preenable = &adis16209_data_rdy_ring_preenable;
-	ring->postenable = &adis16209_data_rdy_ring_postenable;
-	ring->predisable = &adis16209_data_rdy_ring_predisable;
-	ring->owner = THIS_MODULE;
-
-	indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
-	if (indio_dev->pollfunc == NULL) {
-		ret = -ENOMEM;
-		goto error_iio_sw_rb_free;;
-	}
-	indio_dev->pollfunc->poll_func_main = &adis16209_poll_func_th;
-	indio_dev->pollfunc->private_data = indio_dev;
-	indio_dev->modes |= INDIO_RING_TRIGGERED;
-	return 0;
-
-error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->ring);
-	return ret;
-}
-
-int adis16209_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return iio_ring_buffer_register(ring, 0);
-}
-
-void adis16209_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-	iio_ring_buffer_unregister(ring);
-}
Index: drivers/staging/iio/accel/adis16209_trigger.c
===================================================================
--- drivers/staging/iio/accel/adis16209_trigger.c	(revision 8893)
+++ drivers/staging/iio/accel/adis16209_trigger.c	(working copy)
@@ -1,124 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/spi/spi.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "../trigger.h"
-#include "adis16209.h"
-
-/**
- * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static int adis16209_data_rdy_trig_poll(struct iio_dev *dev_info,
-				       int index,
-				       s64 timestamp,
-				       int no_test)
-{
-	struct adis16209_state *st = iio_dev_get_devdata(dev_info);
-	struct iio_trigger *trig = st->trig;
-
-	trig->timestamp = timestamp;
-	iio_trigger_poll(trig);
-
-	return IRQ_HANDLED;
-}
-
-IIO_EVENT_SH(data_rdy_trig, &adis16209_data_rdy_trig_poll);
-
-static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
-
-static struct attribute *adis16209_trigger_attrs[] = {
-	&dev_attr_name.attr,
-	NULL,
-};
-
-static const struct attribute_group adis16209_trigger_attr_group = {
-	.attrs = adis16209_trigger_attrs,
-};
-
-/**
- * adis16209_data_rdy_trigger_set_state() set datardy interrupt state
- **/
-static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig,
-						bool state)
-{
-	struct adis16209_state *st = trig->private_data;
-	struct iio_dev *indio_dev = st->indio_dev;
-	int ret = 0;
-
-	dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
-	ret = adis16209_set_irq(&st->indio_dev->dev, state);
-	if (state == false) {
-		iio_remove_event_from_list(&iio_event_data_rdy_trig,
-					   &indio_dev->interrupts[0]
-					   ->ev_list);
-		flush_scheduled_work();
-	} else {
-		iio_add_event_to_list(&iio_event_data_rdy_trig,
-				      &indio_dev->interrupts[0]->ev_list);
-	}
-	return ret;
-}
-
-/**
- * adis16209_trig_try_reen() try renabling irq for data rdy trigger
- * @trig:	the datardy trigger
- **/
-static int adis16209_trig_try_reen(struct iio_trigger *trig)
-{
-	struct adis16209_state *st = trig->private_data;
-	enable_irq(st->us->irq);
-	return 0;
-}
-
-int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-	int ret;
-	struct adis16209_state *st = indio_dev->dev_data;
-
-	st->trig = iio_allocate_trigger();
-	st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
-	if (!st->trig->name) {
-		ret = -ENOMEM;
-		goto error_free_trig;
-	}
-	snprintf((char *)st->trig->name,
-		 IIO_TRIGGER_NAME_LENGTH,
-		 "adis16209-dev%d", indio_dev->id);
-	st->trig->dev.parent = &st->us->dev;
-	st->trig->owner = THIS_MODULE;
-	st->trig->private_data = st;
-	st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state;
-	st->trig->try_reenable = &adis16209_trig_try_reen;
-	st->trig->control_attrs = &adis16209_trigger_attr_group;
-	ret = iio_trigger_register(st->trig);
-
-	/* select default trigger */
-	indio_dev->trig = st->trig;
-	if (ret)
-		goto error_free_trig_name;
-
-	return 0;
-
-error_free_trig_name:
-	kfree(st->trig->name);
-error_free_trig:
-	iio_free_trigger(st->trig);
-
-	return ret;
-}
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-	struct adis16209_state *state = indio_dev->dev_data;
-
-	iio_trigger_unregister(state->trig);
-	kfree(state->trig->name);
-	iio_free_trigger(state->trig);
-}
Index: drivers/staging/iio/accel/adis16209.h
===================================================================
--- drivers/staging/iio/accel/adis16209.h	(revision 8893)
+++ drivers/staging/iio/accel/adis16209.h	(working copy)
@@ -101,33 +101,6 @@

 #define ADIS16209_ERROR_ACTIVE          (1<<14)

-/**
- * struct adis16209_state - device instance specific data
- * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @work_cont_thresh: CLEAN
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16209_state {
-	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	struct iio_work_cont		work_cont_thresh;
-	s64				last_timestamp;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
-};
-
-int adis16209_set_irq(struct device *dev, bool enable);
-
 #ifdef CONFIG_IIO_RING_BUFFER
 enum adis16209_scan {
 	ADIS16209_SCAN_SUPPLY,
@@ -139,55 +112,5 @@
 	ADIS16209_SCAN_INCLI_Y,
 	ADIS16209_SCAN_ROT,
 };
-
-void adis16209_remove_trigger(struct iio_dev *indio_dev);
-int adis16209_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16209_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-int adis16209_configure_ring(struct iio_dev *indio_dev);
-void adis16209_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16209_initialize_ring(struct iio_ring_buffer *ring);
-void adis16209_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16209_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16209_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16209_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16209_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16209_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16209_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16209_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
 #endif /* CONFIG_IIO_RING_BUFFER */
 #endif /* SPI_ADIS16209_H_ */
Index: drivers/staging/iio/accel/adis16209_core.c
===================================================================
--- drivers/staging/iio/accel/adis16209_core.c	(revision 8893)
+++ drivers/staging/iio/accel/adis16209_core.c	(working copy)
@@ -22,6 +22,9 @@
 #include "../sysfs.h"
 #include "accel.h"
 #include "inclinometer.h"
+#include "../trigger.h"
+#include "../ring_generic.h"
+#include "../common-ring-trigger.h"
 #include "../gyro/gyro.h"
 #include "../adc/adc.h"

@@ -43,13 +46,14 @@
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct iio_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_device *spi = iio_state_get_privdata(st);

 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADIS16209_WRITE_REG(reg_address);
 	st->tx[1] = val;

-	ret = spi_write(st->us, st->tx, 2);
+	ret = spi_write(spi, st->tx, 2);
 	mutex_unlock(&st->buf_lock);

 	return ret;
@@ -69,7 +73,8 @@
 	int ret;
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct iio_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_device *spi = iio_state_get_privdata(st);
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -95,7 +100,7 @@
 	spi_message_init(&msg);
 	spi_message_add_tail(&xfers[0], &msg);
 	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_sync(spi, &msg);
 	mutex_unlock(&st->buf_lock);

 	return ret;
@@ -114,7 +119,8 @@
 {
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16209_state *st = iio_dev_get_devdata(indio_dev);
+	struct iio_state *st = iio_dev_get_devdata(indio_dev);
+	struct spi_device *spi = iio_state_get_privdata(st);
 	int ret;
 	struct spi_transfer xfers[] = {
 		{
@@ -139,9 +145,9 @@
 	spi_message_init(&msg);
 	spi_message_add_tail(&xfers[0], &msg);
 	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_sync(spi, &msg);
 	if (ret) {
-		dev_err(&st->us->dev,
+		dev_err(&spi->dev,
 			"problem when reading 16 bit register 0x%02X",
 			lower_reg_address);
 		goto error_ret;
@@ -285,12 +291,12 @@
 	return -EINVAL;
 }

-int adis16209_set_irq(struct device *dev, bool enable)
+static int adis16209_set_irq(struct iio_state *st, bool enable)
 {
 	int ret = 0;
 	u16 msc;

-	ret = adis16209_spi_read_reg_16(dev, ADIS16209_MSC_CTRL, &msc);
+	ret = adis16209_spi_read_reg_16(&st->indio_dev->dev,
ADIS16209_MSC_CTRL, &msc);
 	if (ret)
 		goto error_ret;

@@ -301,7 +307,7 @@
 	else
 		msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN;

-	ret = adis16209_spi_write_reg_16(dev, ADIS16209_MSC_CTRL, msc);
+	ret = adis16209_spi_write_reg_16(&st->indio_dev->dev,
ADIS16209_MSC_CTRL, msc);

 error_ret:
 	return ret;
@@ -351,13 +357,55 @@
 	return ret;
 }

-static int adis16209_initial_setup(struct adis16209_state *st)
+/**
+ * adis16209_read_ring_data() read data registers which will be
placed into ring
+ * @dev: device associated with child of actual device (iio_dev or iio_trig)
+ * @rx: somewhere to pass back the value read
+ **/
+static int adis16209_read_ring_data(struct iio_state *st, u8 *rx)
 {
+	struct spi_device *spi = iio_state_get_privdata(st);
+	struct spi_message msg;
+	struct spi_transfer xfers[ADIS16209_OUTPUTS + 1];
 	int ret;
+	int i;
+
+	mutex_lock(&st->buf_lock);
+
+	spi_message_init(&msg);
+
+	memset(xfers, 0, sizeof(xfers));
+	for (i = 0; i <= ADIS16209_OUTPUTS; i++) {
+		xfers[i].bits_per_word = 8;
+		xfers[i].cs_change = 1;
+		xfers[i].len = 2;
+		xfers[i].delay_usecs = 30;
+		xfers[i].tx_buf = st->tx + 2 * i;
+		st->tx[2 * i]
+			= ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i);
+		st->tx[2 * i + 1] = 0;
+		if (i >= 1)
+			xfers[i].rx_buf = rx + 2 * (i - 1);
+		spi_message_add_tail(&xfers[i], &msg);
+	}
+
+	ret = spi_sync(spi, &msg);
+	if (ret)
+		dev_err(&spi->dev, "problem when burst reading");
+
+	mutex_unlock(&st->buf_lock);
+
+	return ret;
+}
+
+static int adis16209_initial_setup(struct iio_state *st)
+{
+	int ret;
+	struct spi_device *spi = iio_state_get_privdata(st);
 	struct device *dev = &st->indio_dev->dev;

 	/* Disable IRQ */
-	ret = adis16209_set_irq(dev, false);
+	ret = adis16209_set_irq(st, false);
 	if (ret) {
 		dev_err(dev, "disable irq failed");
 		goto err_ret;
@@ -384,7 +432,7 @@
 	}

 	printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
-			st->us->chip_select, st->us->irq);
+			spi->chip_select, spi->irq);

 err_ret:
 	return ret;
@@ -472,16 +520,54 @@
 	.attrs = adis16209_attributes,
 };

+static IIO_SCAN_EL_C(supply, ADIS16209_SCAN_SUPPLY, IIO_UNSIGNED(14),
+		     ADIS16209_SUPPLY_OUT, NULL);
+static IIO_SCAN_EL_C(accel_x, ADIS16209_SCAN_ACC_X, IIO_SIGNED(14),
+		     ADIS16209_XACCL_OUT, NULL);
+static IIO_SCAN_EL_C(accel_y, ADIS16209_SCAN_ACC_Y, IIO_SIGNED(14),
+		     ADIS16209_YACCL_OUT, NULL);
+static IIO_SCAN_EL_C(aux_adc, ADIS16209_SCAN_AUX_ADC, IIO_UNSIGNED(12),
+		     ADIS16209_AUX_ADC, NULL);
+static IIO_SCAN_EL_C(temp, ADIS16209_SCAN_TEMP, IIO_UNSIGNED(12),
+		     ADIS16209_TEMP_OUT, NULL);
+static IIO_SCAN_EL_C(incli_x, ADIS16209_SCAN_INCLI_X, IIO_SIGNED(14),
+		     ADIS16209_XINCL_OUT, NULL);
+static IIO_SCAN_EL_C(incli_y, ADIS16209_SCAN_INCLI_Y, IIO_SIGNED(14),
+		     ADIS16209_YINCL_OUT, NULL);
+static IIO_SCAN_EL_C(rot, ADIS16209_SCAN_ROT, IIO_SIGNED(14),
+		     ADIS16209_ROT_OUT, NULL);
+
+static IIO_SCAN_EL_TIMESTAMP(8);
+
+static struct attribute *adis16209_scan_el_attrs[] = {
+	&iio_scan_el_supply.dev_attr.attr,
+	&iio_scan_el_accel_x.dev_attr.attr,
+	&iio_scan_el_accel_y.dev_attr.attr,
+	&iio_scan_el_aux_adc.dev_attr.attr,
+	&iio_scan_el_temp.dev_attr.attr,
+	&iio_scan_el_incli_x.dev_attr.attr,
+	&iio_scan_el_incli_y.dev_attr.attr,
+	&iio_scan_el_rot.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group adis16209_scan_el_group = {
+	.attrs = adis16209_scan_el_attrs,
+	.name = "scan_elements",
+};
+
 static int __devinit adis16209_probe(struct spi_device *spi)
 {
 	int ret, regdone = 0;
-	struct adis16209_state *st = kzalloc(sizeof *st, GFP_KERNEL);
+	struct iio_state *st = kzalloc(sizeof *st, GFP_KERNEL);
 	if (!st) {
 		ret =  -ENOMEM;
 		goto error_ret;
 	}
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, st);
+	iio_state_set_privdata(st, spi);

 	/* Allocate the comms buffers */
 	st->rx = kzalloc(sizeof(*st->rx)*ADIS16209_MAX_RX, GFP_KERNEL);
@@ -494,7 +580,12 @@
 		ret = -ENOMEM;
 		goto error_free_rx;
 	}
-	st->us = spi;
+
+	st->irq = spi->irq;
+	st->set_irq = adis16209_set_irq;
+	st->hw_read_ring = adis16209_read_ring_data;
+	st->parent_dev = &spi->dev;
+
 	mutex_init(&st->buf_lock);
 	/* setup the industrialio driver allocated elements */
 	st->indio_dev = iio_allocate_device();
@@ -511,7 +602,18 @@
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;

-	ret = adis16209_configure_ring(st->indio_dev);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_supply.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_rot.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_accel_x.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_accel_y.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_temp.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_aux_adc.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_incli_x.number);
+	iio_scan_mask_set(st->indio_dev, iio_scan_el_incli_y.number);
+	st->indio_dev->scan_timestamp = true;
+	st->indio_dev->scan_el_attrs = &adis16209_scan_el_group;
+
+	ret = iio_configure_common_ring(st->indio_dev);
 	if (ret)
 		goto error_free_dev;

@@ -520,7 +622,7 @@
 		goto error_unreg_ring_funcs;
 	regdone = 1;

-	ret = adis16209_initialize_ring(st->indio_dev->ring);
+	ret = iio_initialize_common_ring(st->indio_dev->ring);
 	if (ret) {
 		printk(KERN_ERR "failed to initialize the ring\n");
 		goto error_unreg_ring_funcs;
@@ -533,9 +635,9 @@
 				IRQF_TRIGGER_RISING,
 				"adis16209");
 		if (ret)
-			goto error_uninitialize_ring;
+			goto error_uninitialize_common_ring;

-		ret = adis16209_probe_trigger(st->indio_dev);
+		ret = iio_probe_common_trigger(st->indio_dev);
 		if (ret)
 			goto error_unregister_line;
 	}
@@ -543,18 +645,18 @@
 	/* Get the device into a sane initial state */
 	ret = adis16209_initial_setup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_remove_common_trigger;
 	return 0;

-error_remove_trigger:
-	adis16209_remove_trigger(st->indio_dev);
+error_remove_common_trigger:
+	iio_remove_common_trigger(st->indio_dev);
 error_unregister_line:
 	if (spi->irq)
 		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	adis16209_uninitialize_ring(st->indio_dev->ring);
+error_uninitialize_common_ring:
+	iio_uninitialize_common_ring(st->indio_dev->ring);
 error_unreg_ring_funcs:
-	adis16209_unconfigure_ring(st->indio_dev);
+	iio_unconfigure_common_ring(st->indio_dev);
 error_free_dev:
 	if (regdone)
 		iio_device_unregister(st->indio_dev);
@@ -572,18 +674,18 @@

 static int adis16209_remove(struct spi_device *spi)
 {
-	struct adis16209_state *st = spi_get_drvdata(spi);
+	struct iio_state *st = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = st->indio_dev;

 	flush_scheduled_work();

-	adis16209_remove_trigger(indio_dev);
+	iio_remove_common_trigger(indio_dev);
 	if (spi->irq)
 		iio_unregister_interrupt_line(indio_dev, 0);

-	adis16209_uninitialize_ring(indio_dev->ring);
+	iio_uninitialize_common_ring(indio_dev->ring);
 	iio_device_unregister(indio_dev);
-	adis16209_unconfigure_ring(indio_dev);
+	iio_unconfigure_common_ring(indio_dev);
 	kfree(st->tx);
 	kfree(st->rx);
 	kfree(st);
Index: drivers/staging/iio/accel/Makefile
===================================================================
--- drivers/staging/iio/accel/Makefile	(revision 8893)
+++ drivers/staging/iio/accel/Makefile	(working copy)
@@ -15,7 +15,6 @@
 obj-$(CONFIG_ADIS16204) += adis16204.o

 adis16209-y             := adis16209_core.o
-adis16209-$(CONFIG_IIO_RING_BUFFER) += adis16209_ring.o adis16209_trigger.o
 obj-$(CONFIG_ADIS16209) += adis16209.o

 adis16220-y             := adis16220_core.o


On Thu, Jun 10, 2010 at 12:48 PM, Barry Song <21cnbao@xxxxxxxxx> wrote:
> Just RFC for discussion. It is not the last patch To keep the change
> lest, i extract the common factor for most iio devices to a common
> ring trigger module. Most devices can use the interfaces in this
> module directly. So copy-paste for ring and trigger is not necessary
> now.
>
> For iio core changes:
> 1. extract xxx_state to iio_state and add a private data to contain
> chip-specific data
> 2. extract all xxx_ring/xxx_trigger api to common api
>
> Index: drivers/staging/iio/iio.h
> ===================================================================
> --- drivers/staging/iio/iio.h   (revision 8893)
> +++ drivers/staging/iio/iio.h   (working copy)
> @@ -447,4 +447,46 @@
>
>  int iio_get_new_idr_val(struct idr *this_idr);
>  void iio_free_idr_val(struct idr *this_idr, int id);
> +
> +/**
> + * struct iio_state - hardware level hooks for iio device
> + * @work_trigger_to_ring: bh for triggered event handling
> + * @work_cont_thresh: CLEAN
> + * @inter:             used to check if new interrupt has been triggered
> + * @last_timestamp:    passing timestamp from th to bh of interrupt handler
> + * @indio_dev:         industrial I/O device structure
> + * @trig:              data ready trigger registered with iio
> + * @tx:                        transmit buffer
> + * @rx:                        recieve buffer
> + * @buf_lock:          mutex to protect tx and rx
> + * @irq:                interrupt number
> + * @set_irq:            control the disable/enable of external interrupt
> + * @hw_read_ring:       read ring data from hardware by spi/i2c.
> + **/
> +struct iio_state {
> +       struct device                   *parent_dev;
> +       struct work_struct              work_trigger_to_ring;
> +       struct iio_work_cont            work_cont_thresh;
> +       s64                             last_timestamp;
> +       struct iio_dev                  *indio_dev;
> +       struct iio_trigger              *trig;
> +       u8                              *tx;
> +       u8                              *rx;
> +       struct mutex                    buf_lock;
> +       int                             irq;
> +       int (*set_irq)(struct iio_state *st, bool enable);
> +       int (*hw_read_ring)(struct iio_state *st, u8 *rx);
> +       void *priv;
> +};
> +
> +static inline void iio_state_set_privdata(struct iio_state *st, void *data)
> +{
> +       st->priv = data;
> +}
> +
> +static inline void * iio_state_get_privdata(struct iio_state *st)
> +{
> +       return st->priv;
> +}
> +
>  #endif /* _INDUSTRIAL_IO_H_ */
> Index: drivers/staging/iio/common-ring-trigger.c
> ===================================================================
> --- drivers/staging/iio/common-ring-trigger.c   (revision 0)
> +++ drivers/staging/iio/common-ring-trigger.c   (revision 0)
> @@ -0,0 +1,277 @@
> +/* The software ring with trigger which can be used by most drivers
> + *
> + * Copyright (c) 2010 Barry Song
> + *
> + * 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.
> + *
> + */
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/fs.h>
> +#include <linux/poll.h>
> +#include <linux/module.h>
> +#include <linux/cdev.h>
> +#include <linux/slab.h>
> +
> +#include "iio.h"
> +#include "ring_generic.h"
> +#include "trigger.h"
> +#include "ring_sw.h"
> +
> +/*
> + * combine_8_to_16(): utility function to munge to u8s into u16
> + */
> +static inline u16 combine_8_to_16(u8 lower, u8 upper)
> +{
> +       u16 _lower = lower;
> +       u16 _upper = upper;
> +       return _lower | (_upper << 8);
> +}
> +
> +static void iio_common_ring_poll_func_th(struct iio_dev *indio_dev)
> +{
> +       struct iio_state *st = iio_dev_get_devdata(indio_dev);
> +       st->last_timestamp = indio_dev->trig->timestamp;
> +       schedule_work(&st->work_trigger_to_ring);
> +}
> +
> +static void iio_common_trigger_bh_to_ring(struct work_struct *work_s)
> +{
> +       struct iio_state *st
> +               = container_of(work_s, struct iio_state,
> +                               work_trigger_to_ring);
> +
> +       int i = 0;
> +       s16 *data;
> +       size_t datasize = st->indio_dev
> +               ->ring->access.get_bpd(st->indio_dev->ring);
> +
> +       data = kmalloc(datasize , GFP_KERNEL);
> +        if (data == NULL) {
> +                dev_err(st->parent_dev, "memory alloc failed in ring bh");
> +                return;
> +        }
> +
> +       if (st->indio_dev->scan_count)
> +               if (st->hw_read_ring(st, st->rx) >= 0)
> +                       for (; i < st->indio_dev->scan_count; i++) {
> +                               data[i] = combine_8_to_16(st->rx[i*2+1],
> +                                               st->rx[i*2]);
> +                       }
> +
> +        /* Guaranteed to be aligned with 8 byte boundary */
> +        if (st->indio_dev->scan_timestamp)
> +                *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp;
> +
> +        st->indio_dev->ring->access.store_to(st->indio_dev->ring,
> +                                            (u8 *)data,
> +                                            st->last_timestamp);
> +
> +        iio_trigger_notify_done(st->indio_dev->trig);
> +        kfree(data);
> +
> +        return;
> +}
> +
> +static int iio_common_ring_preenable(struct iio_dev *indio_dev)
> +{
> +       size_t size;
> +       dev_dbg(&indio_dev->dev, "%s\n", __func__);
> +       /* Check if there are any scan elements enabled, if not fail*/
> +       if (!(indio_dev->scan_count || indio_dev->scan_timestamp))
> +               return -EINVAL;
> +
> +       if (indio_dev->ring->access.set_bpd) {
> +               if (indio_dev->scan_timestamp)
> +                       if (indio_dev->scan_count)
> +                               /* Timestamp (aligned to s64) and data */
> +                               size = (((indio_dev->scan_count * sizeof(s16))
> +                                                       + sizeof(s64) - 1)
> +                                               & ~(sizeof(s64) - 1))
> +                                       + sizeof(s64);
> +                       else /* Timestamp only  */
> +                               size = sizeof(s64);
> +               else /* Data only */
> +                       size = indio_dev->scan_count*sizeof(s16);
> +               indio_dev->ring->access.set_bpd(indio_dev->ring, size);
> +       }
> +
> +       return 0;
> +}
> +
> +static int iio_common_ring_postenable(struct iio_dev *indio_dev)
> +{
> +        return indio_dev->trig
> +                ? iio_trigger_attach_poll_func(indio_dev->trig,
> +                                               indio_dev->pollfunc)
> +                : 0;
> +}
> +
> +static int iio_common_ring_predisable(struct iio_dev *indio_dev)
> +{
> +        return indio_dev->trig
> +                ? iio_trigger_dettach_poll_func(indio_dev->trig,
> +                                                indio_dev->pollfunc)
> +                : 0;
> +}
> +
> +int iio_configure_common_ring(struct iio_dev *indio_dev)
> +{
> +       int ret = 0;
> +       struct iio_state *st = indio_dev->dev_data;
> +       struct iio_ring_buffer *ring;
> +       INIT_WORK(&st->work_trigger_to_ring, iio_common_trigger_bh_to_ring);
> +
> +       ring = iio_sw_rb_allocate(indio_dev);
> +       if (!ring) {
> +               ret = -ENOMEM;
> +               return ret;
> +       }
> +       indio_dev->ring = ring;
> +
> +       iio_ring_sw_register_funcs(&ring->access);
> +       ring->preenable = &iio_common_ring_preenable;
> +       ring->postenable = &iio_common_ring_postenable;
> +       ring->predisable = &iio_common_ring_predisable;
> +       ring->owner = THIS_MODULE;
> +
> +       indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL);
> +       if (indio_dev->pollfunc == NULL) {
> +               ret = -ENOMEM;
> +               goto error_iio_sw_rb_free;;
> +       }
> +       indio_dev->pollfunc->poll_func_main = &iio_common_ring_poll_func_th;
> +       indio_dev->pollfunc->private_data = indio_dev;
> +       indio_dev->modes |= INDIO_RING_TRIGGERED;
> +       return 0;
> +
> +error_iio_sw_rb_free:
> +       iio_sw_rb_free(indio_dev->ring);
> +       return ret;
> +}
> +EXPORT_SYMBOL(iio_configure_common_ring);
> +
> +void iio_unconfigure_common_ring(struct iio_dev *indio_dev)
> +{
> +       kfree(indio_dev->pollfunc);
> +       iio_sw_rb_free(indio_dev->ring);
> +}
> +EXPORT_SYMBOL(iio_unconfigure_common_ring);
> +
> +int iio_initialize_common_ring(struct iio_ring_buffer *ring)
> +{
> +       return iio_ring_buffer_register(ring, 0);
> +}
> +EXPORT_SYMBOL(iio_initialize_common_ring);
> +
> +void iio_uninitialize_common_ring(struct iio_ring_buffer *ring)
> +{
> +       iio_ring_buffer_unregister(ring);
> +}
> +EXPORT_SYMBOL(iio_uninitialize_common_ring);
> +
> +static int iio_common_trigger_poll(struct iio_dev *dev_info,
> +                                      int index,
> +                                      s64 timestamp,
> +                                      int no_test)
> +{
> +       struct iio_state *st = iio_dev_get_devdata(dev_info);
> +       struct iio_trigger *trig = st->trig;
> +
> +       trig->timestamp = timestamp;
> +       iio_trigger_poll(trig);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +IIO_EVENT_SH(common_trig, &iio_common_trigger_poll);
> +
> +static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
> +
> +static struct attribute *iio_trigger_attrs[] = {
> +       &dev_attr_name.attr,
> +       NULL,
> +};
> +
> +static const struct attribute_group iio_trigger_attr_group = {
> +       .attrs = iio_trigger_attrs,
> +};
> +
> +static int iio_common_trigger_try_reen(struct iio_trigger *trig)
> +{
> +       struct iio_state *st = trig->private_data;
> +       enable_irq(st->irq);
> +       return 0;
> +}
> +
> +static int iio_common_trigger_set_state(struct iio_trigger *trig,
> +               bool state)
> +{
> +       struct iio_state *st = trig->private_data;
> +       struct iio_dev *indio_dev = st->indio_dev;
> +       int ret = 0;
> +
> +       dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state);
> +       ret = st->set_irq(st, state);
> +       if (state == false) {
> +               iio_remove_event_from_list(&iio_event_common_trig,
> +                               &indio_dev->interrupts[0]
> +                               ->ev_list);
> +               flush_scheduled_work();
> +       } else {
> +               iio_add_event_to_list(&iio_event_common_trig,
> +                               &indio_dev->interrupts[0]->ev_list);
> +       }
> +       return ret;
> +}
> +
> +int iio_probe_common_trigger(struct iio_dev *indio_dev)
> +{
> +       int ret;
> +       struct iio_state *st = indio_dev->dev_data;
> +
> +       st->trig = iio_allocate_trigger();
> +       st->trig->name = kmalloc(IIO_TRIGGER_NAME_LENGTH, GFP_KERNEL);
> +       if (!st->trig->name) {
> +               ret = -ENOMEM;
> +               goto error_free_trig;
> +       }
> +       snprintf((char *)st->trig->name,
> +                       IIO_TRIGGER_NAME_LENGTH,
> +                       "iio-dev%d", indio_dev->id);
> +       st->trig->dev.parent = st->parent_dev;
> +       st->trig->owner = THIS_MODULE;
> +       st->trig->private_data = st;
> +       st->trig->set_trigger_state = &iio_common_trigger_set_state;
> +       st->trig->try_reenable = &iio_common_trigger_try_reen;
> +       st->trig->control_attrs = &iio_trigger_attr_group;
> +       ret = iio_trigger_register(st->trig);
> +
> +       /* select default trigger */
> +       indio_dev->trig = st->trig;
> +       if (ret)
> +               goto error_free_trig_name;
> +
> +       return 0;
> +
> +error_free_trig_name:
> +       kfree(st->trig->name);
> +error_free_trig:
> +       iio_free_trigger(st->trig);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(iio_probe_common_trigger);
> +
> +void iio_remove_common_trigger(struct iio_dev *indio_dev)
> +{
> +       struct iio_state *state = indio_dev->dev_data;
> +
> +       iio_trigger_unregister(state->trig);
> +       kfree(state->trig->name);
> +       iio_free_trigger(state->trig);
> +}
> +EXPORT_SYMBOL(iio_remove_common_trigger);
> Index: drivers/staging/iio/common-ring-trigger.h
> ===================================================================
> --- drivers/staging/iio/common-ring-trigger.h   (revision 0)
> +++ drivers/staging/iio/common-ring-trigger.h   (revision 0)
> @@ -0,0 +1,24 @@
> +/* The industrial I/O frequently used ring with trigger
> + *
> + * Copyright (c) 2010 Barry Song
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef _IIO_COMMON_RING_TRIGGER_H_
> +#define _IIO_COMMON_RING_TRIGGER_H_
> +
> +#include "iio.h"
> +#include "ring_generic.h"
> +
> +int iio_configure_common_ring(struct iio_dev *indio_dev);
> +void iio_unconfigure_common_ring(struct iio_dev *indio_dev);
> +int iio_initialize_common_ring(struct iio_ring_buffer *ring);
> +void iio_uninitialize_common_ring(struct iio_ring_buffer *ring);
> +
> +int iio_probe_common_trigger(struct iio_dev *indio_dev);
> +void iio_remove_common_trigger(struct iio_dev *indio_dev);
> +#endif /* _IIO_COMMON_RING_TRIGGER_H_ */
> Index: drivers/staging/iio/Kconfig
> ===================================================================
> --- drivers/staging/iio/Kconfig (revision 8893)
> +++ drivers/staging/iio/Kconfig (working copy)
> @@ -38,6 +38,12 @@
>          ring buffers.  The triggers are effectively a 'capture
>          data now' interrupt.
>
> +config IIO_COMMON_RING_TRIGGER
> +       boolean "Enable frequently used ring with trigger"
> +       depends on IIO_SW_RING && IIO_TRIGGER
> +       help
> +         Provides a generic ring with trigger. I can be used by most
> +         IIO devices.
>
>  source "drivers/staging/iio/accel/Kconfig"
>  source "drivers/staging/iio/adc/Kconfig"
> Index: drivers/staging/iio/Makefile
> ===================================================================
> --- drivers/staging/iio/Makefile        (revision 8893)
> +++ drivers/staging/iio/Makefile        (working copy)
> @@ -9,6 +9,8 @@
>
>  obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
>
> +obj-$(CONFIG_IIO_COMMON_RING_TRIGGER) += common-ring-trigger.o
> +
>  obj-y += accel/
>  obj-y += adc/
>  obj-y += addac/
>
>
>
> On Wed, Jun 2, 2010 at 9:21 PM, Jonathan Cameron <jic23@xxxxxxxxx> wrote:
>> On 06/02/10 09:01, Barry Song wrote:
>>> On Mon, Feb 22, 2010 at 7:16 PM, Jonathan Cameron <jic23@xxxxxxxxx> wrote:
>>>> Hi All,
>>>>
>>>> Just for reference as I'll be doing a proper announcement later.
>>>> We now have linux-iio@xxxxxxxxxxxxxxx as a mailing list for the project.
>>>> Unless others have tracked it down it currently only has me as a member
>>>> though and I'm waiting for confirmation from marc.info of an archive.
>>>>
>>>>> Hi Jonathan,
>>>>> Now users depend on iio ring events(IIO_EVENT_CODE_RING_50/75/100_FULL)
>>>>> to read data:
>>>>>                 read_size = fread(&dat, 1, sizeof(struct
>>>>> iio_event_data),
>>>>>                                   fp_ev);
>>>>>                 switch (dat.id) {
>>>>>                 case IIO_EVENT_CODE_RING_100_FULL:
>>>>>                         toread = RingLength;
>>>>>                         break;
>>>>>                 case IIO_EVENT_CODE_RING_75_FULL:
>>>>>                         toread = RingLength*3/4;
>>>>>                         break;
>>>>>                 case IIO_EVENT_CODE_RING_50_FULL:
>>>>>                         toread = RingLength/2;
>>>>>                         break;
>>>>>                 default:
>>>>>                         printf("Unexpecteded event code\n");
>>>>>                         continue;
>>>>>                 }
>>>>>                 read_size = read(fp,
>>>>>                                  data,
>>>>>                                  toread*size_from_scanmode(NumVals,
>>>>> scan_ts));
>>>>>                 if (read_size == -EAGAIN) {
>>>>>                         printf("nothing available \n");
>>>>>                         continue;
>>>>>                 }
>>>>> And iio ring access node doesn't support blocking io too.  It seems we
>>>>> lost to let users read data once ring is not empty. And some users maybe
>>>>> not care about iio ring events at all, but just want to read data like a
>>>>> input or audio driver. So how about adding the following support in iio
>>>>> ring:
>>>>> 1. add NOT EMPTY event in IIO event nodes
>>>> Not keen.  It might lead to a storm of events (at least it might in a
>>>> cleverer ring buffer implementation or during a blocking read).  Actually
>>>> in this particular case it probably wouldn't do any harm.
>>>>> 2. add blocking io support in read function of IIO access nodes
>>>> That I agree would be a good idea.  If we support poll/select on the buffer access
>>>> chrdev then we will get the same effect per having a not empty event and cleaner
>>>> semantics for anyone not interested in the other events. Not to mention I expect
>>>> we will soon have alternative ring buffer implementations that don't supply any
>>>> events at all and hence don't event have the relevant chrdev.
>>>>
>>>> As things are, you can quite happily read whenever you like.  Now you mention it,
>>>> that example code is somewhat missleading! The issue with
>>>> this ring buffer implementation is the handling of a true blocking read is complex
>>>> as at any given time you aren't guaranteed to get what you asked for even if it was
>>>> there when you started the read. It should be possible to work around that though.
>>>>
>>>> It's possible this functionality might be better added to an alternative ring buffer
>>>> implementation. Be vary wary of that ring implementation in general! I am and I wrote it.
>>>>> If you agree with that, I can begin to add these and send you a patch.
>>>>> And a problem I don't know is what you and other people have changed to
>>>>> Greg's staging tree, and I am not sure what tree the patch should be
>>>>> againest.
>>>> Nothing has changed in this region of the code.  In fact I think all that
>>>> has gone into Greg's tree is a clean up patch form Mark Brown making a few
>>>> functions static. Right now I'm still getting the max1363 driver into
>>>> a state where it will be possible to do the ABI changes.
>>>>>
>>>>> For long term plan, is it possible for ring common level to handle more
>>>>> common work to avoid code repeating in different drivers?
>>>> I'm certainly happy for that to be the case if it becomes apparent which functionality
>>>> is shared.  I haven't seen any substantial cases as yet, but then I may well be missing
>>>> things so feel free to submit suggestions (or as ever the better option of patches).
>>>
>>> Now we have many drivers using SW ring with same
>>> preenable(),postenable(),predisable(),
>>> initialize_ring(),uninitialize_ring(),poll_func(),probe_trigger(),
>>> remove_trigger(). Can we move them to IIO common layer as a base class
>>> methods. And the derived class can overload them if they have special
>>> implement? Most devices just use the common layer and don't need to
>>> copy codes.
>> Sounds sensible. Please propose a patch.
>>
>> Jonathan
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[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