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