[PATCH 01/62] staging: comedi: add a 'readback' member to comedi_subdevice

H Hartley Sweeten hsweeten at visionengravers.com
Mon Aug 25 23:03:54 UTC 2014


The analog output hardware in most comedi drivers does not provide a
way to readback to last values written to the channels. In order to
provide an (*insn_read) for the analog output subdevice, the comedi
drivers save the last values for each channel in the private data.

Add a new member, 'readback', to the comedi_subdevice definition to
provide a common way to save these values.

Introduce a comedi core function, comedi_alloc_subdev_readback(), to
allocate the memory needed to save the values. This memory will be
automatically kfree'd when the driver is detached.

Introduce a comedi core function, comedi_readback_insn_read(), that
the comedi drivers can use for the (*insn_read) of a subdevice to
return the saved values for each channel.

This will allow removing the boilerplate in the comedi drivers to
return the saved values. In some drivers it will also allow removing
the private data completely.

Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 drivers/staging/comedi/comedidev.h |  6 ++++++
 drivers/staging/comedi/drivers.c   | 42 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 58e58a3..a883862 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -88,6 +88,8 @@ struct comedi_subdevice {
 
 	struct device *class_dev;
 	int minor;
+
+	unsigned int *readback;
 };
 
 struct comedi_buf_page {
@@ -448,6 +450,10 @@ unsigned int comedi_dio_update_state(struct comedi_subdevice *,
 
 void *comedi_alloc_devpriv(struct comedi_device *, size_t);
 int comedi_alloc_subdevices(struct comedi_device *, int);
+int comedi_alloc_subdev_readback(struct comedi_subdevice *);
+
+int comedi_readback_insn_read(struct comedi_device *, struct comedi_subdevice *,
+			      struct comedi_insn *, unsigned int *data);
 
 int comedi_load_firmware(struct comedi_device *, struct device *,
 			 const char *name,
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 9ada130..c4ed8fd 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -96,6 +96,22 @@ int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
 }
 EXPORT_SYMBOL_GPL(comedi_alloc_subdevices);
 
+/**
+ * comedi_alloc_subdev_readback() - Allocate memory for the subdevice readback.
+ * @s: comedi_subdevice struct
+ */
+int comedi_alloc_subdev_readback(struct comedi_subdevice *s)
+{
+	if (!s->n_chan)
+		return -EINVAL;
+
+	s->readback = kcalloc(s->n_chan, sizeof(*s->readback), GFP_KERNEL);
+	if (!s->readback)
+		return -ENOMEM;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_alloc_subdev_readback);
+
 static void comedi_device_detach_cleanup(struct comedi_device *dev)
 {
 	int i;
@@ -111,6 +127,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev)
 				comedi_buf_alloc(dev, s, 0);
 				kfree(s->async);
 			}
+			kfree(s->readback);
 		}
 		kfree(dev->subdevices);
 		dev->subdevices = NULL;
@@ -157,6 +174,31 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
 }
 
 /**
+ * comedi_readback_insn_read() - A generic (*insn_read) for subdevice readback.
+ * @dev: comedi_device struct
+ * @s: comedi_subdevice struct
+ * @insn: comedi_insn struct
+ * @data: pointer to return the readback data
+ */
+int comedi_readback_insn_read(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
+{
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
+
+	if (!s->readback)
+		return -EINVAL;
+
+	for (i = 0; i < insn->n; i++)
+		data[i] = s->readback[chan];
+
+	return insn->n;
+}
+EXPORT_SYMBOL_GPL(comedi_readback_insn_read);
+
+/**
  * comedi_timeout() - busy-wait for a driver condition to occur.
  * @dev: comedi_device struct
  * @s: comedi_subdevice struct
-- 
2.0.3



More information about the devel mailing list