[PATCH] comedi vmk80xx: Add support for treating DIO lines as a block

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

 



If I try and use comedi_dio_bitfield2() on my shiny new VM110 board, I
just get EBUSY back permanently. Implementing the insn_bits call seems
to fix the problem and is good in its own right since I can now read and
write to all the digital lines at the same time. Tested on a K8055, but
I don't have access to a K8061.

Ali.
diff -Naurd linux-staging-2.6.32.8/drivers/staging/comedi/drivers/vmk80xx.c linux-staging-2.6.32.8-bis/drivers/staging/comedi/drivers/vmk80xx.c
--- linux-staging-2.6.32.8/drivers/staging/comedi/drivers/vmk80xx.c	2010-02-09 12:57:19.000000000 +0000
+++ linux-staging-2.6.32.8-bis/drivers/staging/comedi/drivers/vmk80xx.c	2011-05-11 14:19:37.551737828 +0100
@@ -3,6 +3,7 @@
     Velleman USB Board Low-Level Driver
 
     Copyright (C) 2009 Manuel Gebele <forensixs@xxxxxx>, Germany
+    Copyright (C) 2011 J. Ali Harlow <ali@xxxxxxxxxxxxxxx>
 
     COMEDI - Linux Control and Measurement Device Interface
     Copyright (C) 2000 David A. Schleef <ds@xxxxxxxxxxx>
@@ -27,7 +28,7 @@
 Description: Velleman USB Board Low-Level Driver
 Devices: K8055/K8061 aka VM110/VM140
 Author: Manuel Gebele <forensixs@xxxxxx>
-Updated: Sun, 10 May 2009 11:14:59 +0200
+Updated: Wed, 11 May 2011 12:44:00 +0100
 Status: works
 
 Supports:
@@ -41,6 +42,7 @@
 /*
 Changelog:
 
+0.8.81	-4-  support handling DIO lines as a block
 0.8.81	-3-  code completely rewritten (adjust driver logic)
 0.8.81  -2-  full support for K8061
 0.8.81  -1-  fix some mistaken among others the number of
@@ -555,7 +557,8 @@
 	if ((dir) & DIR_IN) {                              \
 		if (test_bit(TRANS_IN_BUSY, &dev->flags))  \
 			return -EBUSY;                     \
-	} else {  /* DIR_OUT */                            \
+	}                                                  \
+	if ((dir) & DIR_OUT) {                             \
 		if (test_bit(TRANS_OUT_BUSY, &dev->flags)) \
 			return -EBUSY;                     \
 	}                                                  \
@@ -683,6 +686,48 @@
 	return n;
 }
 
+static int vmk80xx_di_bits(struct comedi_device *cdev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn, unsigned int *data)
+{
+	struct vmk80xx_usb *dev = cdev->private;
+	unsigned char *rx_buf;
+	int reg;
+	int retval;
+
+	dbgvm("vmk80xx: %s\n", __func__);
+
+	rudimentary_check(DIR_IN);
+
+	down(&dev->limit_sem);
+
+	rx_buf = dev->usb_rx_buf;
+
+	if (dev->board.model == VMK8061_MODEL) {
+		reg = VMK8061_DI_REG;
+		dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
+	} else
+		reg = VMK8055_DI_REG;
+
+	retval = vmk80xx_read_packet(dev);
+
+	if (!retval)
+	{
+		if (dev->board.model == VMK8055_MODEL)
+			data[1] = (((rx_buf[reg] >> 4) & 0x03) |
+			          ((rx_buf[reg] << 2) & 0x04) |
+			          ((rx_buf[reg] >> 3) & 0x18));
+		else
+			data[1] = rx_buf[reg];
+
+		retval = 2;
+	}
+
+	up(&dev->limit_sem);
+
+	return retval;
+}
+
 static int vmk80xx_di_rinsn(struct comedi_device *cdev,
 			    struct comedi_subdevice *s,
 			    struct comedi_insn *insn, unsigned int *data)
@@ -811,6 +856,73 @@
 	return n;
 }
 
+static int vmk80xx_do_bits(struct comedi_device *cdev,
+			   struct comedi_subdevice *s,
+			   struct comedi_insn *insn, unsigned int *data)
+{
+	struct vmk80xx_usb *dev = cdev->private;
+	unsigned char *rx_buf, *tx_buf;
+	int dir, reg, cmd;
+	int retval;
+
+	dbgvm("vmk80xx: %s\n", __func__);
+
+	dir = 0;
+
+	if (data[0])
+		dir |= DIR_OUT;
+
+	if (dev->board.model == VMK8061_MODEL)
+		dir |= DIR_IN;
+
+	rudimentary_check(dir);
+
+	down(&dev->limit_sem);
+
+	rx_buf = dev->usb_rx_buf;
+	tx_buf = dev->usb_tx_buf;
+
+	if (data[0]) {
+		if (dev->board.model == VMK8055_MODEL) {
+			reg = VMK8055_DO_REG;
+			cmd = VMK8055_CMD_WRT_AD;
+		} else { /* VMK8061_MODEL */
+			reg = VMK8061_DO_REG;
+			cmd = VMK8061_CMD_DO;
+		}
+
+		tx_buf[reg] &= ~data[0];
+		tx_buf[reg] |= (data[0] & data[1]);
+
+		retval = vmk80xx_write_packet(dev, cmd);
+
+		if (retval)
+			goto out;
+	}
+
+	if (dev->board.model == VMK8061_MODEL) {
+		reg = VMK8061_DO_REG;
+		tx_buf[0] = VMK8061_CMD_RD_DO;
+
+		retval = vmk80xx_read_packet(dev);
+
+		if (!retval)
+		{
+			data[1] = rx_buf[reg];
+			retval = 2;
+		}
+
+	} else {
+		data[1] = tx_buf[reg];
+		retval = 2;
+	}
+
+out:
+	up(&dev->limit_sem);
+
+	return retval;
+}
+
 static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
 			     struct comedi_subdevice *s,
 			     struct comedi_insn *insn, unsigned int *data)
@@ -1094,16 +1206,18 @@
 	s->type = COMEDI_SUBD_DI;
 	s->subdev_flags = SDF_READABLE | SDF_GROUND;
 	s->n_chan = dev->board.di_chans;
-	s->maxdata = (1 << dev->board.di_bits) - 1;
+	s->maxdata = 1;
 	s->insn_read = vmk80xx_di_rinsn;
+	s->insn_bits = vmk80xx_di_bits;
 
 	/* Digital output subdevice */
 	s = cdev->subdevices + VMK80XX_SUBD_DO;
 	s->type = COMEDI_SUBD_DO;
 	s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
 	s->n_chan = dev->board.do_chans;
-	s->maxdata = (1 << dev->board.do_bits) - 1;
+	s->maxdata = 1;
 	s->insn_write = vmk80xx_do_winsn;
+	s->insn_bits = vmk80xx_do_bits;
 
 	if (dev->board.model == VMK8061_MODEL) {
 		s->subdev_flags |= SDF_READABLE;
_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/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