Correct number of channels on DIO subdevice. Correct operation of
authorIan Abbott <abbotti@mev.co.uk>
Fri, 7 Aug 2009 14:00:01 +0000 (14:00 +0000)
committerIan Abbott <abbotti@mev.co.uk>
Fri, 7 Aug 2009 14:00:01 +0000 (14:00 +0000)
INSN_CONFIG_DIO_INPUT and INSN_CONFIG_DIO_OUTPUT and support
INSN_CONFIG_DIO_QUERY.
Thanks to Alessio Margan for some testing.

comedi/drivers/s526.c

index 332c1f0a072c7e4d7c3ffe7110d17364c64c64ef..c0e3a95bd520933e5b2a390ae5b3f05e9206b162 100644 (file)
@@ -367,7 +367,7 @@ static int s526_attach(comedi_device * dev, comedi_devconfig * it)
        if (thisboard->have_dio) {
                s->type = COMEDI_SUBD_DIO;
                s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = 2;
+               s->n_chan = 8;
                s->maxdata = 1;
                s->range_table = &range_digital;
                s->insn_bits = s526_dio_insn_bits;
@@ -933,7 +933,7 @@ static int s526_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
        data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;        // low 8 bits are the data
        /* or we could just return the software copy of the output values if
         * it was a purely digital output subdevice */
-       //data[1]=s->state;
+       //data[1]=s->state & 0xFF;
 
        return 2;
 }
@@ -942,28 +942,33 @@ static int s526_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
        comedi_insn * insn, lsampl_t * data)
 {
        int chan = CR_CHAN(insn->chanspec);
-       sampl_t value;
+       int group, mask;
 
        printk("S526 DIO insn_config\n");
 
-       if (insn->n != 1)
-               return -EINVAL;
-
-       value = inw(ADDR_REG(REG_DIO));
-
        /* The input or output configuration of each digital line is
         * configured by a special insn_config instruction.  chanspec
         * contains the channel to be changed, and data[0] contains the
         * value COMEDI_INPUT or COMEDI_OUTPUT. */
 
-       if (data[0] == COMEDI_OUTPUT) {
-               value |= 1 << (chan + 10);      // bit 10/11 set the group 1/2's mode
-               s->io_bits |= (0xF << chan);
-       } else {
-               value &= ~(1 << (chan + 10));   // 1 is output, 0 is input.
-               s->io_bits &= ~(0xF << chan);
+       group = chan >> 2;
+       mask = 0xF << (group << 2);
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->state |= 1 << (group + 10);  // bit 10/11 set the group 1/2's mode
+               s->io_bits |= mask;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
+               s->io_bits &= ~mask;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
        }
-       outw(value, ADDR_REG(REG_DIO));
+       outw(s->state, ADDR_REG(REG_DIO));
 
        return 1;
 }