staging: comedi: core: introduce comedi_dio_insn_config()
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Mon, 5 Aug 2013 22:00:05 +0000 (15:00 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2013 22:04:01 +0000 (15:04 -0700)
DIO subdevices always handle the INSN_CONFIG_DIO_{INPUT,OUTPUT} instructions
to configure the dio channels. They also always handle the INSN_CONFIG_DIO_QUERY
instruction to query the configuration of a dio channel.

Introduce a helper function to handle the (*insn_config) boilerplate for
comedi DIO subdevices. This function has the same parameters as (*insn_config)
functions with an additional parameter to allow the caller to pass a 'mask'
value for grouped dio channels.

This function returns:

  0 if the instruction was successful but requires additional handling by
  the caller (INSN_CONFIG_DIO_{INPUT,OUTPUT}

  insn->n if the instruction was handled (INSN_CONFIG_DIO_QUERY)

  -EINVAL for all unhandled instructions

The caller is responsible for actually configuring the hardware based on
the configuration (s->io_bits).

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/comedidev.h
drivers/staging/comedi/drivers.c

index 98058b9097e6197883f142a588835da6666166ad..f2f75b9dfb8636dfec57355eb860f99f71a13fbd 100644 (file)
@@ -342,6 +342,10 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
 
 /* drivers.c - general comedi driver functions */
 
+int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *,
+                          struct comedi_insn *, unsigned int *data,
+                          unsigned int mask);
+
 void *comedi_alloc_devpriv(struct comedi_device *, size_t);
 int comedi_alloc_subdevices(struct comedi_device *, int);
 
index 791a26bd5f63c7fb9f937e2f2e04b055b473fb28..60fd81c71a127691edb466748900b4534d61ca5e 100644 (file)
@@ -150,6 +150,46 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
        return -EINVAL;
 }
 
+/**
+ * comedi_dio_insn_config() - boilerplate (*insn_config) for DIO subdevices.
+ * @dev: comedi_device struct
+ * @s: comedi_subdevice struct
+ * @insn: comedi_insn struct
+ * @data: parameters for the @insn
+ * @mask: io_bits mask for grouped channels
+ */
+int comedi_dio_insn_config(struct comedi_device *dev,
+                          struct comedi_subdevice *s,
+                          struct comedi_insn *insn,
+                          unsigned int *data,
+                          unsigned int mask)
+{
+       unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec);
+
+       if (!mask)
+               mask = chan_mask;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~mask;
+               break;
+
+       case INSN_CONFIG_DIO_OUTPUT:
+               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;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(comedi_dio_insn_config);
+
 static int insn_rw_emulate_bits(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)