Currently the async command support in this driver consists of just the
stubbed in functions.

Flesh out the (*do_cmdtest) function for basic support of timed analog
input acquisitions.

Signed-off-by: H Hartley Sweeten <hswee...@visionengravers.com>
Cc: Ian Abbott <abbo...@mev.co.uk>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 drivers/staging/comedi/drivers/das6402.c | 105 ++++++++++++++++++++++++++++++-
 1 file changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/comedi/drivers/das6402.c 
b/drivers/staging/comedi/drivers/das6402.c
index f3909f3..511b6b3 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -35,6 +35,7 @@
 #include <linux/interrupt.h>
 
 #include "../comedidev.h"
+#include "comedi_fc.h"
 #include "8253.h"
 
 /*
@@ -207,11 +208,113 @@ static int das6402_ai_cmd(struct comedi_device *dev,
        return -EINVAL;
 }
 
+static int das6402_ai_check_chanlist(struct comedi_device *dev,
+                                    struct comedi_subdevice *s,
+                                    struct comedi_cmd *cmd)
+{
+       unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
+       unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
+       unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
+       int i;
+
+       for (i = 1; i < cmd->chanlist_len; i++) {
+               unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+               unsigned int range = CR_RANGE(cmd->chanlist[i]);
+               unsigned int aref = CR_AREF(cmd->chanlist[i]);
+
+               if (chan != chan0 + i) {
+                       dev_dbg(dev->class_dev,
+                               "chanlist must be consecutive\n");
+                       return -EINVAL;
+               }
+
+               if (range != range0) {
+                       dev_dbg(dev->class_dev,
+                               "chanlist must have the same range\n");
+                       return -EINVAL;
+               }
+
+               if (aref != aref0) {
+                       dev_dbg(dev->class_dev,
+                               "chanlist must have the reference\n");
+                       return -EINVAL;
+               }
+
+               if (aref0 == AREF_DIFF && chan > (s->n_chan / 2)) {
+                       dev_dbg(dev->class_dev,
+                               "chanlist differential channel to large\n");
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
 static int das6402_ai_cmdtest(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_cmd *cmd)
 {
-       return -EINVAL;
+       struct das6402_private *devpriv = dev->private;
+       int err = 0;
+       unsigned int arg;
+
+       /* Step 1 : check if triggers are trivially valid */
+
+       err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+       err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
+       err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
+       err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+       err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
+
+       if (err)
+               return 1;
+
+       /* Step 2a : make sure trigger sources are unique */
+
+       err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+       /* Step 2b : and mutually compatible */
+
+       if (err)
+               return 2;
+
+       /* Step 3: check if arguments are trivially valid */
+
+       err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+       err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+       err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000);
+       err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
+       err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
+
+       if (cmd->stop_src == TRIG_COUNT)
+               err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
+       else    /* TRIG_NONE */
+               err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+       if (err)
+               return 3;
+
+       /* step 4: fix up any arguments */
+
+       if (cmd->convert_src == TRIG_TIMER) {
+               arg = cmd->convert_arg;
+               i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+                                         &devpriv->divider1,
+                                         &devpriv->divider2,
+                                         &arg, cmd->flags);
+               err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
+       }
+
+       if (err)
+               return 4;
+
+       /* Step 5: check channel list if it exists */
+       if (cmd->chanlist && cmd->chanlist_len > 0)
+               err |= das6402_ai_check_chanlist(dev, s, cmd);
+
+       if (err)
+               return 5;
+
+       return 0;
 }
 
 static int das6402_ai_cancel(struct comedi_device *dev,
-- 
2.0.3

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

Reply via email to