OSDN Git Service

staging/comedi/drivers/usbduxsigma.c: added support for ehci drivers
authorBernd Porr <mail@berndporr.me.uk>
Wed, 22 Jul 2015 17:46:39 +0000 (18:46 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Jul 2015 03:54:38 +0000 (20:54 -0700)
urb->interval is deprecated and thus I've changed the driver
that it now always assumes interval=1 which means every frame
in USB 1.1 and every uframe in USB 2.0. However we still need
to have different sampling rates which are still multiples
of the interval which is now transmitted to the firmware.
The firmware transmits either zero length packets or none every (u)frame.
This is checked in the completion handler and any packet
at zero length is discarded so that comedi again sees the data
coming in at the interval specified. This also then gives the ADC
the necessary time to convert. For example 16 channels require
about 700us and in this period no packet could be transmitted.
In this case this is padded up to 1ms so that we have then 7 zero
length packets and one packet with the ADC data.

Signed-off-by: Bernd Porr <mail@berndporr.me.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/usbduxsigma.c

index 2c27eb2..51846ad 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * usbduxsigma.c
- * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk
+ * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
  * Description: University of Stirling USB DAQ & INCITE Technology Limited
  * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma)
  * Author: Bernd Porr <mail@berndporr.me.uk>
- * Updated: 10 Oct 2014
+ * Updated: 20 July 2015
  * Status: stable
  */
 
@@ -39,6 +39,7 @@
  *   0.4: fixed D/A voltage range
  *   0.5: various bug fixes, health check at startup
  *   0.6: corrected wrong input range
+ *   0.7: rewrite code that urb->interval is always 1
  */
 
 #include <linux/kernel.h>
 #define RETRIES 10
 
 /* bulk transfer commands to usbduxsigma */
-#define USBBUXSIGMA_AD_CMD             0
+#define USBBUXSIGMA_AD_CMD             9
 #define USBDUXSIGMA_DA_CMD             1
 #define USBDUXSIGMA_DIO_CFG_CMD                2
 #define USBDUXSIGMA_DIO_BITS_CMD       3
@@ -217,24 +218,28 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev,
        int ret;
        int i;
 
-       devpriv->ai_counter--;
-       if (devpriv->ai_counter == 0) {
-               devpriv->ai_counter = devpriv->ai_timer;
-
-               /* get the data from the USB bus and hand it over to comedi */
-               for (i = 0; i < cmd->chanlist_len; i++) {
-                       /* transfer data, note first byte is the DIO state */
-                       val = be32_to_cpu(devpriv->in_buf[i+1]);
-                       val &= 0x00ffffff;      /* strip status byte */
-                       val ^= 0x00800000;      /* convert to unsigned */
+       if ((urb->actual_length > 0) && (urb->status != -EXDEV)) {
+               devpriv->ai_counter--;
+               if (devpriv->ai_counter == 0) {
+                       devpriv->ai_counter = devpriv->ai_timer;
+
+                       /* get the data from the USB bus
+                          and hand it over to comedi */
+                       for (i = 0; i < cmd->chanlist_len; i++) {
+                               /* transfer data,
+                                  note first byte is the DIO state */
+                               val = be32_to_cpu(devpriv->in_buf[i+1]);
+                               val &= 0x00ffffff; /* strip status byte */
+                               val ^= 0x00800000; /* convert to unsigned */
+
+                               if (!comedi_buf_write_samples(s, &val, 1))
+                                       return;
+                       }
 
-                       if (!comedi_buf_write_samples(s, &val, 1))
-                               return;
+                       if (cmd->stop_src == TRIG_COUNT &&
+                           async->scans_done >= cmd->stop_arg)
+                               async->events |= COMEDI_CB_EOA;
                }
-
-               if (cmd->stop_src == TRIG_COUNT &&
-                   async->scans_done >= cmd->stop_arg)
-                       async->events |= COMEDI_CB_EOA;
        }
 
        /* if command is still running, resubmit urb */
@@ -374,10 +379,7 @@ static void usbduxsigma_ao_handle_urb(struct comedi_device *dev,
                urb->transfer_buffer_length = SIZEOUTBUF;
                urb->dev = comedi_to_usb_dev(dev);
                urb->status = 0;
-               if (devpriv->high_speed)
-                       urb->interval = 8;      /* uframes */
-               else
-                       urb->interval = 1;      /* frames */
+               urb->interval = 1;      /* (u)frames */
                urb->number_of_packets = 1;
                urb->iso_frame_desc[0].offset = 0;
                urb->iso_frame_desc[0].length = SIZEOUTBUF;
@@ -441,7 +443,6 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev,
                                   int input_urb)
 {
        struct usb_device *usb = comedi_to_usb_dev(dev);
-       struct usbduxsigma_private *devpriv = dev->private;
        struct urb *urb;
        int ret;
        int i;
@@ -452,7 +453,7 @@ static int usbduxsigma_submit_urbs(struct comedi_device *dev,
 
                /* in case of a resubmission after an unlink... */
                if (input_urb)
-                       urb->interval = devpriv->ai_interval;
+                       urb->interval = 1;
                urb->context = dev;
                urb->dev = usb;
                urb->status = 0;
@@ -674,13 +675,14 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev,
                create_adc_command(chan, &muxsg0, &muxsg1);
        }
 
-       devpriv->dux_commands[1] = len;  /* num channels per time step */
-       devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
-       devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
-       devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
-       devpriv->dux_commands[5] = muxsg0;
-       devpriv->dux_commands[6] = muxsg1;
-       devpriv->dux_commands[7] = sysred;
+       devpriv->dux_commands[1] = devpriv->ai_interval;
+       devpriv->dux_commands[2] = len;  /* num channels per time step */
+       devpriv->dux_commands[3] = 0x12; /* CONFIG0 */
+       devpriv->dux_commands[4] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
+       devpriv->dux_commands[5] = 0x00; /* CONFIG3: diff. channels off */
+       devpriv->dux_commands[6] = muxsg0;
+       devpriv->dux_commands[7] = muxsg1;
+       devpriv->dux_commands[8] = sysred;
 
        ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
        if (ret < 0) {
@@ -1427,10 +1429,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
                urb->transfer_buffer_length = SIZEOUTBUF;
                urb->iso_frame_desc[0].offset = 0;
                urb->iso_frame_desc[0].length = SIZEOUTBUF;
-               if (devpriv->high_speed)
-                       urb->interval = 8;      /* uframes */
-               else
-                       urb->interval = 1;      /* frames */
+               urb->interval = 1;      /* (u)frames */
        }
 
        if (devpriv->pwm_buf_sz) {