[PATCH 06/13] staging: comedi: pcmuio: fix pcmuio_dio_insn_bits()

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

 



This dio subdevice (*insn_bits) function does not follow the "norm"
for comedi drivers. It also _appears_ to return the incorrect state
of the channels.

Use the comedi_dio_update_state() helper to handle the boilerplate
for updating the output channel state. Due to the hardware we then
need to invert the state and mask the input channels before updating
the outputs.

Then read the hardware and invert the result to get the current true
state of the dio channels.

Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx>
Cc: Ian Abbott <abbotti@xxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
 drivers/staging/comedi/drivers/pcmuio.c | 35 +++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index fb0cbf0..2dca119 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -202,30 +202,35 @@ static unsigned int pcmuio_read(struct comedi_device *dev,
  */
 static int pcmuio_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	unsigned int mask = data[0] & s->io_bits;	/* outputs only */
-	unsigned int bits = data[1];
+	unsigned int chanmask = (1 << s->n_chan) - 1;
 	int asic = s->index / 2;
 	int port = (s->index % 2) ? 3 : 0;
+	unsigned int mask;
 	unsigned int val;
 
-	/* get inverted state of the channels from the port */
-	val = pcmuio_read(dev, asic, 0, port);
-
-	/* get the true state of the channels */
-	s->state = val ^ ((0x1 << s->n_chan) - 1);
-
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		s->state &= ~mask;
-		s->state |= (mask & bits);
-
-		/* invert the state and update the channels */
-		val = s->state ^ ((0x1 << s->n_chan) - 1);
+		/*
+		 * Outputs are inverted, invert the state and
+		 * update the channels.
+		 *
+		 * The s->io_bits mask makes sure the input channels
+		 * are '0' so that the outputs pins stay in a high
+		 * z-state.
+		 */
+		val = ~s->state & chanmask;
+		val &= s->io_bits;
 		pcmuio_write(dev, val, asic, 0, port);
 	}
 
-	data[1] = s->state;
+	/* get inverted state of the channels from the port */
+	val = pcmuio_read(dev, asic, 0, port);
+
+	/* return the true state of the channels */
+	data[1] = ~val & chanmask;
 
 	return insn->n;
 }
-- 
1.8.4.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux