staging: comedi: usbdux: tidy up usbdux_dio_insn_config()
[linux-2.6-block.git] / drivers / staging / comedi / drivers / usbdux.c
index 279e5bd493fa8682cfa6a9d3e1095265546736cc..cdb02876a7190798e9dbcb3322fa5c432e093070 100644 (file)
@@ -78,9 +78,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
  *
  */
 
-/* generates loads of debug info */
-/* #define NOISY_DUX_DEBUGBUG */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -185,64 +182,26 @@ sampling rate. If you sample two channels you get 4kHz and so on.
 /* must have more buffers due to buggy USB ctr */
 #define NUMOFOUTBUFFERSHIGH    10
 
-/* Total number of usbdux devices */
-#define NUMUSBDUX             16
-
-/* Analogue in subdevice */
-#define SUBDEV_AD             0
-
-/* Analogue out subdevice */
-#define SUBDEV_DA             1
-
-/* Digital I/O */
-#define SUBDEV_DIO            2
-
-/* counter */
-#define SUBDEV_COUNTER        3
-
-/* timer aka pwm output */
-#define SUBDEV_PWM            4
-
 /* number of retries to get the right dux command */
 #define RETRIES 10
 
-/**************************************************/
-/* comedi constants */
-static const struct comedi_lrange range_usbdux_ai_range = { 4, {
-                                                               BIP_RANGE
-                                                               (4.096),
-                                                               BIP_RANGE(4.096
-                                                                         / 2),
-                                                               UNI_RANGE
-                                                               (4.096),
-                                                               UNI_RANGE(4.096
-                                                                         / 2)
-                                                               }
+static const struct comedi_lrange range_usbdux_ai_range = {
+       4, {
+               BIP_RANGE(4.096),
+               BIP_RANGE(4.096 / 2),
+               UNI_RANGE(4.096),
+               UNI_RANGE(4.096 / 2)
+       }
 };
 
-static const struct comedi_lrange range_usbdux_ao_range = { 2, {
-                                                               BIP_RANGE
-                                                               (4.096),
-                                                               UNI_RANGE
-                                                               (4.096),
-                                                               }
+static const struct comedi_lrange range_usbdux_ao_range = {
+       2, {
+               BIP_RANGE(4.096),
+               UNI_RANGE(4.096)
+       }
 };
 
-/*
- * private structure of one subdevice
- */
-
-/*
- * This is the structure which holds all the data of
- * this driver one sub device just now: A/D
- */
-struct usbduxsub {
-       /* attached? */
-       int attached;
-       /* is it associated with a subdevice? */
-       int probed;
-       /* pointer to the usb-device */
-       struct usb_device *usbdev;
+struct usbdux_private {
        /* actual number of in-buffers */
        int num_in_buffers;
        /* actual number of out-buffers */
@@ -264,22 +223,14 @@ struct usbduxsub {
        int16_t *insn_buffer;
        /* output buffer for single DA outputs */
        int16_t *out_buffer;
-       /* interface number */
-       int ifnum;
-       /* interface structure in 2.6 */
-       struct usb_interface *interface;
-       /* comedi device for the interrupt context */
-       struct comedi_device *comedidev;
-       /* is it USB_SPEED_HIGH or not? */
-       short int high_speed;
-       /* asynchronous command is running */
-       short int ai_cmd_running;
-       short int ao_cmd_running;
-       /* pwm is running */
-       short int pwm_cmd_running;
-       /* continous acquisition */
-       short int ai_continous;
-       short int ao_continous;
+
+       unsigned int high_speed:1;
+       unsigned int ai_cmd_running:1;
+       unsigned int ai_continous:1;
+       unsigned int ao_cmd_running:1;
+       unsigned int ao_continous:1;
+       unsigned int pwm_cmd_running:1;
+
        /* number of samples to acquire */
        int ai_sample_count;
        int ao_sample_count;
@@ -298,22 +249,11 @@ struct usbduxsub {
        struct semaphore sem;
 };
 
-/*
- * The pointer to the private usb-data of the driver is also the private data
- * for the comedi-device.  This has to be global as the usb subsystem needs
- * global variables. The other reason is that this structure must be there
- * _before_ any comedi command is issued. The usb subsystem must be initialised
- * before comedi can access it.
- */
-static struct usbduxsub usbduxsub[NUMUSBDUX];
-
-static DEFINE_SEMAPHORE(start_stop_sem);
-
 /*
  * Stops the data acquision
  * It should be safe to call this function from any context
  */
-static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_inurbs(struct usbdux_private *usbduxsub_tmp)
 {
        int i = 0;
        int err = 0;
@@ -325,98 +265,58 @@ static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp)
                                 * cancelled. */
                                usb_kill_urb(usbduxsub_tmp->urb_in[i]);
                        }
-                       dev_dbg(&usbduxsub_tmp->interface->dev,
-                               "comedi: usbdux: unlinked InURB %d, err=%d\n",
-                               i, err);
                }
        }
        return err;
 }
 
-/*
- * This will stop a running acquisition operation
- * Is called from within this driver from both the
- * interrupt context and from comedi
- */
-static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static int usbdux_ai_stop(struct comedi_device *dev, int do_unlink)
 {
+       struct usbdux_private *devpriv = dev->private;
        int ret = 0;
 
-       if (!this_usbduxsub) {
-               pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
-               return -EFAULT;
-       }
-       dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
-
-       if (do_unlink) {
-               /* stop aquistion */
-               ret = usbduxsub_unlink_inurbs(this_usbduxsub);
-       }
+       if (do_unlink)
+               ret = usbduxsub_unlink_inurbs(devpriv);
 
-       this_usbduxsub->ai_cmd_running = 0;
+       devpriv->ai_cmd_running = 0;
 
        return ret;
 }
 
-/*
- * This will cancel a running acquisition operation.
- * This is called by comedi but never from inside the driver.
- */
 static int usbdux_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
-       struct usbduxsub *this_usbduxsub;
-       int res = 0;
-
-       /* force unlink of all urbs */
-       this_usbduxsub = dev->private;
-       if (!this_usbduxsub)
-               return -EFAULT;
-
-       dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
+       struct usbdux_private *devpriv = dev->private;
+       int ret = 0;
 
        /* prevent other CPUs from submitting new commands just now */
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
+       down(&devpriv->sem);
        /* unlink only if the urb really has been submitted */
-       res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
-       up(&this_usbduxsub->sem);
-       return res;
+       ret = usbdux_ai_stop(dev, devpriv->ai_cmd_running);
+       up(&devpriv->sem);
+
+       return ret;
 }
 
 /* analogue IN - interrupt service routine */
 static void usbduxsub_ai_isoc_irq(struct urb *urb)
 {
+       struct comedi_device *dev = urb->context;
+       struct comedi_subdevice *s = dev->read_subdev;
+       struct usbdux_private *devpriv = dev->private;
        int i, err, n;
-       struct usbduxsub *this_usbduxsub;
-       struct comedi_device *this_comedidev;
-       struct comedi_subdevice *s;
-
-       /* the context variable points to the subdevice */
-       this_comedidev = urb->context;
-       /* the private structure of the subdevice is struct usbduxsub */
-       this_usbduxsub = this_comedidev->private;
-       /* subdevice which is the AD converter */
-       s = &this_comedidev->subdevices[SUBDEV_AD];
 
        /* first we test if something unusual has just happened */
        switch (urb->status) {
        case 0:
                /* copy the result in the transfer buffer */
-               memcpy(this_usbduxsub->in_buffer,
-                      urb->transfer_buffer, SIZEINBUF);
+               memcpy(devpriv->in_buffer, urb->transfer_buffer, SIZEINBUF);
                break;
        case -EILSEQ:
                /* error in the ISOchronous data */
                /* we don't copy the data into the transfer buffer */
                /* and recycle the last data byte */
-               dev_dbg(&urb->dev->dev,
-                       "comedi%d: usbdux: CRC error in ISO IN stream.\n",
-                       this_usbduxsub->comedidev->minor);
-
+               dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
                break;
 
        case -ECONNRESET:
@@ -424,29 +324,27 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
        case -ESHUTDOWN:
        case -ECONNABORTED:
                /* happens after an unlink command */
-               if (this_usbduxsub->ai_cmd_running) {
-                       /* we are still running a command */
-                       /* tell this comedi */
+               if (devpriv->ai_cmd_running) {
                        s->async->events |= COMEDI_CB_EOA;
                        s->async->events |= COMEDI_CB_ERROR;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                        /* stop the transfer w/o unlink */
-                       usbdux_ai_stop(this_usbduxsub, 0);
+                       usbdux_ai_stop(dev, 0);
                }
                return;
 
        default:
                /* a real error on the bus */
                /* pass error to comedi if we are really running a command */
-               if (this_usbduxsub->ai_cmd_running) {
-                       dev_err(&urb->dev->dev,
-                               "Non-zero urb status received in ai intr "
-                               "context: %d\n", urb->status);
+               if (devpriv->ai_cmd_running) {
+                       dev_err(dev->class_dev,
+                               "Non-zero urb status received in ai intr context: %d\n",
+                               urb->status);
                        s->async->events |= COMEDI_CB_EOA;
                        s->async->events |= COMEDI_CB_ERROR;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                        /* don't do an unlink here */
-                       usbdux_ai_stop(this_usbduxsub, 0);
+                       usbdux_ai_stop(dev, 0);
                }
                return;
        }
@@ -455,7 +353,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
         * at this point we are reasonably sure that nothing dodgy has happened
         * are we running a command?
         */
-       if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
+       if (unlikely(!devpriv->ai_cmd_running)) {
                /*
                 * not running a command, do not continue execution if no
                 * asynchronous command is running in particular not resubmit
@@ -463,44 +361,42 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
                return;
        }
 
-       urb->dev = this_usbduxsub->usbdev;
+       urb->dev = comedi_to_usb_dev(dev);
 
        /* resubmit the urb */
        err = usb_submit_urb(urb, GFP_ATOMIC);
        if (unlikely(err < 0)) {
-               dev_err(&urb->dev->dev,
-                       "comedi_: urb resubmit failed in int-context! err=%d\n",
-                       err);
+               dev_err(dev->class_dev,
+                       "urb resubmit failed in int-context! err=%d\n", err);
                if (err == -EL2NSYNC)
-                       dev_err(&urb->dev->dev,
-                               "buggy USB host controller or bug in IRQ "
-                               "handler!\n");
+                       dev_err(dev->class_dev,
+                               "buggy USB host controller or bug in IRQ handler!\n");
                s->async->events |= COMEDI_CB_EOA;
                s->async->events |= COMEDI_CB_ERROR;
-               comedi_event(this_usbduxsub->comedidev, s);
+               comedi_event(dev, s);
                /* don't do an unlink here */
-               usbdux_ai_stop(this_usbduxsub, 0);
+               usbdux_ai_stop(dev, 0);
                return;
        }
 
-       this_usbduxsub->ai_counter--;
-       if (likely(this_usbduxsub->ai_counter > 0))
+       devpriv->ai_counter--;
+       if (likely(devpriv->ai_counter > 0))
                return;
 
        /* timer zero, transfer measurements to comedi */
-       this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+       devpriv->ai_counter = devpriv->ai_timer;
 
        /* test, if we transmit only a fixed number of samples */
-       if (!(this_usbduxsub->ai_continous)) {
+       if (!devpriv->ai_continous) {
                /* not continuous, fixed number of samples */
-               this_usbduxsub->ai_sample_count--;
+               devpriv->ai_sample_count--;
                /* all samples received? */
-               if (this_usbduxsub->ai_sample_count < 0) {
+               if (devpriv->ai_sample_count < 0) {
                        /* prevent a resubmit next time */
-                       usbdux_ai_stop(this_usbduxsub, 0);
+                       usbdux_ai_stop(dev, 0);
                        /* say comedi that the acquistion is over */
                        s->async->events |= COMEDI_CB_EOA;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                        return;
                }
        }
@@ -509,26 +405,24 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb)
        for (i = 0; i < n; i++) {
                /* transfer data */
                if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
-                       err = comedi_buf_put
-                           (s->async,
-                            le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800);
+                       err = comedi_buf_put(s->async,
+                            le16_to_cpu(devpriv->in_buffer[i]) ^ 0x800);
                } else {
-                       err = comedi_buf_put
-                           (s->async,
-                            le16_to_cpu(this_usbduxsub->in_buffer[i]));
+                       err = comedi_buf_put(s->async,
+                            le16_to_cpu(devpriv->in_buffer[i]));
                }
                if (unlikely(err == 0)) {
                        /* buffer overflow */
-                       usbdux_ai_stop(this_usbduxsub, 0);
+                       usbdux_ai_stop(dev, 0);
                        return;
                }
        }
        /* tell comedi that data is there */
        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
-       comedi_event(this_usbduxsub->comedidev, s);
+       comedi_event(dev, s);
 }
 
-static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp)
 {
        int i = 0;
        int err = 0;
@@ -537,70 +431,46 @@ static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp)
                for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
                        if (usbduxsub_tmp->urb_out[i])
                                usb_kill_urb(usbduxsub_tmp->urb_out[i]);
-
-                       dev_dbg(&usbduxsub_tmp->interface->dev,
-                               "comedi: usbdux: unlinked OutURB %d: res=%d\n",
-                               i, err);
                }
        }
        return err;
 }
 
-/* This will cancel a running acquisition operation
- * in any context.
- */
-static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static int usbdux_ao_stop(struct comedi_device *dev, int do_unlink)
 {
+       struct usbdux_private *devpriv = dev->private;
        int ret = 0;
 
-       if (!this_usbduxsub)
-               return -EFAULT;
-       dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
-
        if (do_unlink)
-               ret = usbduxsub_unlink_outurbs(this_usbduxsub);
+               ret = usbduxsub_unlink_outurbs(devpriv);
 
-       this_usbduxsub->ao_cmd_running = 0;
+       devpriv->ao_cmd_running = 0;
 
        return ret;
 }
 
-/* force unlink, is called by comedi */
 static int usbdux_ao_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
-       int res = 0;
-
-       if (!this_usbduxsub)
-               return -EFAULT;
+       struct usbdux_private *devpriv = dev->private;
+       int ret = 0;
 
        /* prevent other CPUs from submitting a command just now */
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
+       down(&devpriv->sem);
        /* unlink only if it is really running */
-       res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
-       up(&this_usbduxsub->sem);
-       return res;
+       ret = usbdux_ao_stop(dev, devpriv->ao_cmd_running);
+       up(&devpriv->sem);
+
+       return ret;
 }
 
 static void usbduxsub_ao_isoc_irq(struct urb *urb)
 {
+       struct comedi_device *dev = urb->context;
+       struct comedi_subdevice *s = dev->write_subdev;
+       struct usbdux_private *devpriv = dev->private;
        int i, ret;
        int8_t *datap;
-       struct usbduxsub *this_usbduxsub;
-       struct comedi_device *this_comedidev;
-       struct comedi_subdevice *s;
-
-       /* the context variable points to the subdevice */
-       this_comedidev = urb->context;
-       /* the private structure of the subdevice is struct usbduxsub */
-       this_usbduxsub = this_comedidev->private;
-
-       s = &this_comedidev->subdevices[SUBDEV_DA];
 
        switch (urb->status) {
        case 0:
@@ -613,47 +483,47 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
        case -ECONNABORTED:
                /* after an unlink command, unplug, ... etc */
                /* no unlink needed here. Already shutting down. */
-               if (this_usbduxsub->ao_cmd_running) {
+               if (devpriv->ao_cmd_running) {
                        s->async->events |= COMEDI_CB_EOA;
-                       comedi_event(this_usbduxsub->comedidev, s);
-                       usbdux_ao_stop(this_usbduxsub, 0);
+                       comedi_event(dev, s);
+                       usbdux_ao_stop(dev, 0);
                }
                return;
 
        default:
                /* a real error */
-               if (this_usbduxsub->ao_cmd_running) {
-                       dev_err(&urb->dev->dev,
-                               "comedi_: Non-zero urb status received in ao "
-                               "intr context: %d\n", urb->status);
+               if (devpriv->ao_cmd_running) {
+                       dev_err(dev->class_dev,
+                               "Non-zero urb status received in ao intr context: %d\n",
+                               urb->status);
                        s->async->events |= COMEDI_CB_ERROR;
                        s->async->events |= COMEDI_CB_EOA;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                        /* we do an unlink if we are in the high speed mode */
-                       usbdux_ao_stop(this_usbduxsub, 0);
+                       usbdux_ao_stop(dev, 0);
                }
                return;
        }
 
        /* are we actually running? */
-       if (!(this_usbduxsub->ao_cmd_running))
+       if (!devpriv->ao_cmd_running)
                return;
 
        /* normal operation: executing a command in this subdevice */
-       this_usbduxsub->ao_counter--;
-       if ((int)this_usbduxsub->ao_counter <= 0) {
+       devpriv->ao_counter--;
+       if ((int)devpriv->ao_counter <= 0) {
                /* timer zero */
-               this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+               devpriv->ao_counter = devpriv->ao_timer;
 
                /* handle non continous acquisition */
-               if (!(this_usbduxsub->ao_continous)) {
+               if (!devpriv->ao_continous) {
                        /* fixed number of samples */
-                       this_usbduxsub->ao_sample_count--;
-                       if (this_usbduxsub->ao_sample_count < 0) {
+                       devpriv->ao_sample_count--;
+                       if (devpriv->ao_sample_count < 0) {
                                /* all samples transmitted */
-                               usbdux_ao_stop(this_usbduxsub, 0);
+                               usbdux_ao_stop(dev, 0);
                                s->async->events |= COMEDI_CB_EOA;
-                               comedi_event(this_usbduxsub->comedidev, s);
+                               comedi_event(dev, s);
                                /* no resubmit of the urb */
                                return;
                        }
@@ -673,9 +543,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
                        ret = comedi_buf_get(s->async, &temp);
                        datap[0] = temp;
                        datap[1] = temp >> 8;
-                       datap[2] = this_usbduxsub->dac_commands[i];
-                       /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
-                       /* datap[0],datap[1],datap[2]); */
+                       datap[2] = devpriv->dac_commands[i];
                        if (ret < 0) {
                                dev_err(&urb->dev->dev,
                                        "comedi: buffer underflow\n");
@@ -684,39 +552,35 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb)
                        }
                        /* transmit data to comedi */
                        s->async->events |= COMEDI_CB_BLOCK;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                }
        }
        urb->transfer_buffer_length = SIZEOUTBUF;
-       urb->dev = this_usbduxsub->usbdev;
+       urb->dev = comedi_to_usb_dev(dev);
        urb->status = 0;
-       if (this_usbduxsub->ao_cmd_running) {
-               if (this_usbduxsub->high_speed) {
-                       /* uframes */
-                       urb->interval = 8;
-               } else {
-                       /* frames */
-                       urb->interval = 1;
-               }
+       if (devpriv->ao_cmd_running) {
+               if (devpriv->high_speed)
+                       urb->interval = 8;      /* uframes */
+               else
+                       urb->interval = 1;      /* frames */
                urb->number_of_packets = 1;
                urb->iso_frame_desc[0].offset = 0;
                urb->iso_frame_desc[0].length = SIZEOUTBUF;
                urb->iso_frame_desc[0].status = 0;
                ret = usb_submit_urb(urb, GFP_ATOMIC);
                if (ret < 0) {
-                       dev_err(&urb->dev->dev,
-                               "comedi_: ao urb resubm failed in int-cont. "
-                               "ret=%d", ret);
+                       dev_err(dev->class_dev,
+                               "ao urb resubm failed in int-cont. ret=%d",
+                               ret);
                        if (ret == EL2NSYNC)
-                               dev_err(&urb->dev->dev,
-                                       "buggy USB host controller or bug in "
-                                       "IRQ handling!\n");
+                               dev_err(dev->class_dev,
+                                       "buggy USB host controller or bug in IRQ handling!\n");
 
                        s->async->events |= COMEDI_CB_EOA;
                        s->async->events |= COMEDI_CB_ERROR;
-                       comedi_event(this_usbduxsub->comedidev, s);
+                       comedi_event(dev, s);
                        /* don't do an unlink here */
-                       usbdux_ao_stop(this_usbduxsub, 0);
+                       usbdux_ao_stop(dev, 0);
                }
        }
 }
@@ -727,8 +591,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev,
                                  const u8 *data, size_t size,
                                  unsigned long context)
 {
-       struct usbduxsub *usbduxsub = dev->private;
-       struct usb_device *usb = usbduxsub->usbdev;
+       struct usb_device *usb = comedi_to_usb_dev(dev);
        uint8_t *buf;
        uint8_t *tmp;
        int ret;
@@ -737,7 +600,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev,
                return 0;
 
        if (size > FIRMWARE_MAX_LEN) {
-               dev_err(&usbduxsub->interface->dev,
+               dev_err(dev->class_dev,
                        "usbdux firmware binary it too large for FX2.\n");
                return -ENOMEM;
        }
@@ -763,8 +626,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev,
                              tmp, 1,
                              BULK_TIMEOUT);
        if (ret < 0) {
-               dev_err(&usbduxsub->interface->dev,
-                       "comedi_: can not stop firmware\n");
+               dev_err(dev->class_dev, "can not stop firmware\n");
                goto done;
        }
 
@@ -776,8 +638,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev,
                              buf, size,
                              BULK_TIMEOUT);
        if (ret < 0) {
-               dev_err(&usbduxsub->interface->dev,
-                       "comedi_: firmware upload failed\n");
+               dev_err(dev->class_dev, "firmware upload failed\n");
                goto done;
        }
 
@@ -790,8 +651,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev,
                              tmp, 1,
                              BULK_TIMEOUT);
        if (ret < 0)
-               dev_err(&usbduxsub->interface->dev,
-                       "comedi_: can not start firmware\n");
+               dev_err(dev->class_dev, "can not start firmware\n");
 
 done:
        kfree(tmp);
@@ -799,60 +659,52 @@ done:
        return ret;
 }
 
-static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_inurbs(struct comedi_device *dev)
 {
-       int i, err_flag;
-
-       if (!usbduxsub)
-               return -EFAULT;
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       struct urb *urb;
+       int ret;
+       int i;
 
        /* Submit all URBs and start the transfer on the bus */
-       for (i = 0; i < usbduxsub->num_in_buffers; i++) {
+       for (i = 0; i < devpriv->num_in_buffers; i++) {
+               urb = devpriv->urb_in[i];
+
                /* in case of a resubmission after an unlink... */
-               usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval;
-               usbduxsub->urb_in[i]->context = usbduxsub->comedidev;
-               usbduxsub->urb_in[i]->dev = usbduxsub->usbdev;
-               usbduxsub->urb_in[i]->status = 0;
-               usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP;
-               dev_dbg(&usbduxsub->interface->dev,
-                       "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
-                       usbduxsub->comedidev->minor, i,
-                       (usbduxsub->urb_in[i]->context),
-                       (usbduxsub->urb_in[i]->dev),
-                       (usbduxsub->urb_in[i]->interval));
-               err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC);
-               if (err_flag) {
-                       dev_err(&usbduxsub->interface->dev,
-                               "comedi_: ai: usb_submit_urb(%d) error %d\n",
-                               i, err_flag);
-                       return err_flag;
-               }
+               urb->interval = devpriv->ai_interval;
+               urb->context = dev;
+               urb->dev = usb;
+               urb->status = 0;
+               urb->transfer_flags = URB_ISO_ASAP;
+
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
 
-static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_outurbs(struct comedi_device *dev)
 {
-       int i, err_flag;
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       struct urb *urb;
+       int ret;
+       int i;
 
-       if (!usbduxsub)
-               return -EFAULT;
+       for (i = 0; i < devpriv->num_out_buffers; i++) {
+               urb = devpriv->urb_out[i];
 
-       for (i = 0; i < usbduxsub->num_out_buffers; i++) {
-               dev_dbg(&usbduxsub->interface->dev,
-                       "comedi_: submitting out-urb[%d]\n", i);
                /* in case of a resubmission after an unlink... */
-               usbduxsub->urb_out[i]->context = usbduxsub->comedidev;
-               usbduxsub->urb_out[i]->dev = usbduxsub->usbdev;
-               usbduxsub->urb_out[i]->status = 0;
-               usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP;
-               err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC);
-               if (err_flag) {
-                       dev_err(&usbduxsub->interface->dev,
-                               "comedi_: ao: usb_submit_urb(%d) error %d\n",
-                               i, err_flag);
-                       return err_flag;
-               }
+               urb->context = dev;
+               urb->dev = usb;
+               urb->status = 0;
+               urb->transfer_flags = URB_ISO_ASAP;
+
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -860,13 +712,10 @@ static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
 static int usbdux_ai_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int err = 0, i;
        unsigned int tmp_timer;
 
-       if (!(this_usbduxsub->probed))
-               return -ENODEV;
-
        /* Step 1 : check if triggers are trivially valid */
 
        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -968,209 +817,144 @@ static int8_t create_adc_command(unsigned int chan, int range)
 #define SENDPWMON                 7
 #define SENDPWMOFF                8
 
-static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
+static int send_dux_commands(struct comedi_device *dev, int cmd_type)
 {
-       int result, nsent;
-
-       this_usbduxsub->dux_commands[0] = cmd_type;
-#ifdef NOISY_DUX_DEBUGBUG
-       printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
-              this_usbduxsub->comedidev->minor);
-       for (result = 0; result < SIZEOFDUXBUFFER; result++)
-               printk(" %02x", this_usbduxsub->dux_commands[result]);
-       printk("\n");
-#endif
-       result = usb_bulk_msg(this_usbduxsub->usbdev,
-                             usb_sndbulkpipe(this_usbduxsub->usbdev,
-                                             COMMAND_OUT_EP),
-                             this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
-                             &nsent, BULK_TIMEOUT);
-       if (result < 0)
-               dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-                       "could not transmit dux_command to the usb-device, "
-                       "err=%d\n", this_usbduxsub->comedidev->minor, result);
-
-       return result;
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       int nsent;
+
+       devpriv->dux_commands[0] = cmd_type;
+
+       return usb_bulk_msg(usb, usb_sndbulkpipe(usb, COMMAND_OUT_EP),
+                           devpriv->dux_commands, SIZEOFDUXBUFFER,
+                           &nsent, BULK_TIMEOUT);
 }
 
-static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+static int receive_dux_commands(struct comedi_device *dev, int command)
 {
-       int result = (-EFAULT);
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       int ret;
        int nrec;
        int i;
 
        for (i = 0; i < RETRIES; i++) {
-               result = usb_bulk_msg(this_usbduxsub->usbdev,
-                                     usb_rcvbulkpipe(this_usbduxsub->usbdev,
-                                                     COMMAND_IN_EP),
-                                     this_usbduxsub->insn_buffer, SIZEINSNBUF,
+               ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, COMMAND_IN_EP),
+                                     devpriv->insn_buffer, SIZEINSNBUF,
                                      &nrec, BULK_TIMEOUT);
-               if (result < 0) {
-                       dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-                               "insn: USB error %d while receiving DUX command"
-                               "\n", this_usbduxsub->comedidev->minor, result);
-                       return result;
-               }
-               if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command)
-                       return result;
+               if (ret < 0)
+                       return ret;
+               if (le16_to_cpu(devpriv->insn_buffer[0]) == command)
+                       return ret;
        }
-       /* this is only reached if the data has been requested a couple of
-        * times */
-       dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
-               "wrong data returned from firmware: want cmd %d, got cmd %d.\n",
-               this_usbduxsub->comedidev->minor, command,
-               le16_to_cpu(this_usbduxsub->insn_buffer[0]));
+       /* command not received */
        return -EFAULT;
 }
 
 static int usbdux_ai_inttrig(struct comedi_device *dev,
-                            struct comedi_subdevice *s, unsigned int trignum)
+                            struct comedi_subdevice *s,
+                            unsigned int trignum)
 {
-       int ret;
-       struct usbduxsub *this_usbduxsub = dev->private;
-       if (!this_usbduxsub)
-               return -EFAULT;
+       struct usbdux_private *devpriv = dev->private;
+       int ret = -EINVAL;
 
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi%d: usbdux_ai_inttrig\n", dev->minor);
+       down(&devpriv->sem);
 
-       if (trignum != 0) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
-                       dev->minor);
-               up(&this_usbduxsub->sem);
-               return -EINVAL;
-       }
-       if (!(this_usbduxsub->ai_cmd_running)) {
-               this_usbduxsub->ai_cmd_running = 1;
-               ret = usbduxsub_submit_inurbs(this_usbduxsub);
+       if (trignum != 0)
+               goto ai_trig_exit;
+
+       if (!devpriv->ai_cmd_running) {
+               devpriv->ai_cmd_running = 1;
+               ret = usbduxsub_submit_inurbs(dev);
                if (ret < 0) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: usbdux_ai_inttrig: "
-                               "urbSubmit: err=%d\n", dev->minor, ret);
-                       this_usbduxsub->ai_cmd_running = 0;
-                       up(&this_usbduxsub->sem);
-                       return ret;
+                       devpriv->ai_cmd_running = 0;
+                       goto ai_trig_exit;
                }
                s->async->inttrig = NULL;
        } else {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: ai_inttrig but acqu is already running\n",
-                       dev->minor);
+               ret = -EBUSY;
        }
-       up(&this_usbduxsub->sem);
-       return 1;
+
+ai_trig_exit:
+       up(&devpriv->sem);
+       return ret;
 }
 
 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct usbdux_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
-       unsigned int chan, range;
-       int i, ret;
-       struct usbduxsub *this_usbduxsub = dev->private;
-       int result;
-
-       if (!this_usbduxsub)
-               return -EFAULT;
-
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi%d: usbdux_ai_cmd\n", dev->minor);
+       int len = cmd->chanlist_len;
+       int ret = -EBUSY;
+       int i;
 
        /* block other CPUs from starting an ai_cmd */
-       down(&this_usbduxsub->sem);
+       down(&devpriv->sem);
+
+       if (devpriv->ai_cmd_running)
+               goto ai_cmd_exit;
 
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       if (this_usbduxsub->ai_cmd_running) {
-               dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
-                       "ai_cmd not possible. Another ai_cmd is running.\n",
-                       dev->minor);
-               up(&this_usbduxsub->sem);
-               return -EBUSY;
-       }
        /* set current channel of the running acquisition to zero */
        s->async->cur_chan = 0;
 
-       this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
-       for (i = 0; i < cmd->chanlist_len; ++i) {
-               chan = CR_CHAN(cmd->chanlist[i]);
-               range = CR_RANGE(cmd->chanlist[i]);
-               if (i >= NUMCHANNELS) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: channel list too long\n",
-                               dev->minor);
-                       break;
-               }
-               this_usbduxsub->dux_commands[i + 2] =
-                   create_adc_command(chan, range);
-       }
+       devpriv->dux_commands[1] = len;
+       for (i = 0; i < len; ++i) {
+               unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+               unsigned int range = CR_RANGE(cmd->chanlist[i]);
 
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi %d: sending commands to the usb device: size=%u\n",
-               dev->minor, NUMCHANNELS);
+               if (i >= NUMCHANNELS)
+                       break;
 
-       result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
-       if (result < 0) {
-               up(&this_usbduxsub->sem);
-               return result;
+               devpriv->dux_commands[i + 2] = create_adc_command(chan, range);
        }
 
-       if (this_usbduxsub->high_speed) {
+       ret = send_dux_commands(dev, SENDADCOMMANDS);
+       if (ret < 0)
+               goto ai_cmd_exit;
+
+       if (devpriv->high_speed) {
                /*
                 * every channel gets a time window of 125us. Thus, if we
                 * sample all 8 channels we need 1ms. If we sample only one
                 * channel we need only 125us
                 */
-               this_usbduxsub->ai_interval = 1;
+               devpriv->ai_interval = 1;
                /* find a power of 2 for the interval */
-               while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
-                       this_usbduxsub->ai_interval =
-                           (this_usbduxsub->ai_interval) * 2;
-               }
-               this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
-                                                         (this_usbduxsub->
-                                                          ai_interval));
+               while (devpriv->ai_interval < len)
+                       devpriv->ai_interval *= 2;
+
+               devpriv->ai_timer = cmd->scan_begin_arg /
+                                   (125000 * devpriv->ai_interval);
        } else {
                /* interval always 1ms */
-               this_usbduxsub->ai_interval = 1;
-               this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
+               devpriv->ai_interval = 1;
+               devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
        }
-       if (this_usbduxsub->ai_timer < 1) {
-               dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
-                       "timer=%d, scan_begin_arg=%d. "
-                       "Not properly tested by cmdtest?\n", dev->minor,
-                       this_usbduxsub->ai_timer, cmd->scan_begin_arg);
-               up(&this_usbduxsub->sem);
-               return -EINVAL;
+       if (devpriv->ai_timer < 1) {
+               ret = -EINVAL;
+               goto ai_cmd_exit;
        }
-       this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+
+       devpriv->ai_counter = devpriv->ai_timer;
 
        if (cmd->stop_src == TRIG_COUNT) {
                /* data arrives as one packet */
-               this_usbduxsub->ai_sample_count = cmd->stop_arg;
-               this_usbduxsub->ai_continous = 0;
+               devpriv->ai_sample_count = cmd->stop_arg;
+               devpriv->ai_continous = 0;
        } else {
                /* continous acquisition */
-               this_usbduxsub->ai_continous = 1;
-               this_usbduxsub->ai_sample_count = 0;
+               devpriv->ai_continous = 1;
+               devpriv->ai_sample_count = 0;
        }
 
        if (cmd->start_src == TRIG_NOW) {
                /* enable this acquisition operation */
-               this_usbduxsub->ai_cmd_running = 1;
-               ret = usbduxsub_submit_inurbs(this_usbduxsub);
+               devpriv->ai_cmd_running = 1;
+               ret = usbduxsub_submit_inurbs(dev);
                if (ret < 0) {
-                       this_usbduxsub->ai_cmd_running = 0;
+                       devpriv->ai_cmd_running = 0;
                        /* fixme: unlink here?? */
-                       up(&this_usbduxsub->sem);
-                       return ret;
+                       goto ai_cmd_exit;
                }
                s->async->inttrig = NULL;
        } else {
@@ -1179,202 +963,155 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                /* wait for an internal signal */
                s->async->inttrig = usbdux_ai_inttrig;
        }
-       up(&this_usbduxsub->sem);
-       return 0;
+
+ai_cmd_exit:
+       up(&devpriv->sem);
+
+       return ret;
 }
 
 /* Mode 0 is used to get a single conversion on demand */
 static int usbdux_ai_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
+                              struct comedi_insn *insn,
+                              unsigned int *data)
 {
+       struct usbdux_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
+       unsigned int val;
+       int ret = -EBUSY;
        int i;
-       unsigned int one = 0;
-       int chan, range;
-       int err;
-       struct usbduxsub *this_usbduxsub = dev->private;
-
-       if (!this_usbduxsub)
-               return 0;
 
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
-               dev->minor, insn->n, insn->subdev);
+       down(&devpriv->sem);
 
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       if (this_usbduxsub->ai_cmd_running) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: ai_insn_read not possible. "
-                       "Async Command is running.\n", dev->minor);
-               up(&this_usbduxsub->sem);
-               return 0;
-       }
+       if (devpriv->ai_cmd_running)
+               goto ai_read_exit;
 
-       /* sample one channel */
-       chan = CR_CHAN(insn->chanspec);
-       range = CR_RANGE(insn->chanspec);
        /* set command for the first channel */
-       this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
+       devpriv->dux_commands[1] = create_adc_command(chan, range);
 
        /* adc commands */
-       err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
-       if (err < 0) {
-               up(&this_usbduxsub->sem);
-               return err;
-       }
+       ret = send_dux_commands(dev, SENDSINGLEAD);
+       if (ret < 0)
+               goto ai_read_exit;
 
        for (i = 0; i < insn->n; i++) {
-               err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
-               if (err < 0) {
-                       up(&this_usbduxsub->sem);
-                       return 0;
-               }
-               one = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
-               if (CR_RANGE(insn->chanspec) <= 1)
-                       one = one ^ 0x800;
+               ret = receive_dux_commands(dev, SENDSINGLEAD);
+               if (ret < 0)
+                       goto ai_read_exit;
+
+               val = le16_to_cpu(devpriv->insn_buffer[1]);
+
+               /* bipolar data is two's-complement */
+               if (comedi_range_is_bipolar(s, range))
+                       val ^= ((s->maxdata + 1) >> 1);
 
-               data[i] = one;
+               data[i] = val;
        }
-       up(&this_usbduxsub->sem);
-       return i;
-}
 
-/************************************/
-/* analog out */
+ai_read_exit:
+       up(&devpriv->sem);
+
+       return ret ? ret : insn->n;
+}
 
 static int usbdux_ao_insn_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
-                              struct comedi_insn *insn, unsigned int *data)
+                              struct comedi_insn *insn,
+                              unsigned int *data)
 {
+       struct usbdux_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
        int i;
-       int chan = CR_CHAN(insn->chanspec);
-       struct usbduxsub *this_usbduxsub = dev->private;
 
-       if (!this_usbduxsub)
-               return -EFAULT;
-
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
+       down(&devpriv->sem);
        for (i = 0; i < insn->n; i++)
-               data[i] = this_usbduxsub->out_buffer[chan];
+               data[i] = devpriv->out_buffer[chan];
+       up(&devpriv->sem);
 
-       up(&this_usbduxsub->sem);
-       return i;
+       return insn->n;
 }
 
 static int usbdux_ao_insn_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
-                               struct comedi_insn *insn, unsigned int *data)
+                               struct comedi_insn *insn,
+                               unsigned int *data)
 {
-       int i, err;
-       int chan = CR_CHAN(insn->chanspec);
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int val = devpriv->out_buffer[chan];
+       int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+       int ret = -EBUSY;
+       int i;
 
-       if (!this_usbduxsub)
-               return -EFAULT;
+       down(&devpriv->sem);
 
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi%d: ao_insn_write\n", dev->minor);
+       if (devpriv->ao_cmd_running)
+               goto ao_write_exit;
 
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       if (this_usbduxsub->ao_cmd_running) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: ao_insn_write: "
-                       "ERROR: asynchronous ao_cmd is running\n", dev->minor);
-               up(&this_usbduxsub->sem);
-               return 0;
-       }
+       /* number of channels: 1 */
+       devpriv->dux_commands[1] = 1;
+       /* channel number */
+       devpriv->dux_commands[4] = chan << 6;
 
        for (i = 0; i < insn->n; i++) {
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
-                       dev->minor, chan, i, data[i]);
+               val = data[i];
 
-               /* number of channels: 1 */
-               this_usbduxsub->dux_commands[1] = 1;
                /* one 16 bit value */
-               *((int16_t *) (this_usbduxsub->dux_commands + 2)) =
-                   cpu_to_le16(data[i]);
-               this_usbduxsub->out_buffer[chan] = data[i];
-               /* channel number */
-               this_usbduxsub->dux_commands[4] = (chan << 6);
-               err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
-               if (err < 0) {
-                       up(&this_usbduxsub->sem);
-                       return err;
-               }
+               *p = cpu_to_le16(val);
+
+               ret = send_dux_commands(dev, SENDDACOMMANDS);
+               if (ret < 0)
+                       goto ao_write_exit;
        }
-       up(&this_usbduxsub->sem);
+       devpriv->out_buffer[chan] = val;
 
-       return i;
+ao_write_exit:
+       up(&devpriv->sem);
+
+       return ret ? ret : insn->n;
 }
 
 static int usbdux_ao_inttrig(struct comedi_device *dev,
-                            struct comedi_subdevice *s, unsigned int trignum)
+                            struct comedi_subdevice *s,
+                            unsigned int trignum)
 {
-       int ret;
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *devpriv = dev->private;
+       int ret = -EINVAL;
 
-       if (!this_usbduxsub)
-               return -EFAULT;
+       down(&devpriv->sem);
 
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       if (trignum != 0) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
-                       dev->minor);
-               up(&this_usbduxsub->sem);
-               return -EINVAL;
-       }
-       if (!(this_usbduxsub->ao_cmd_running)) {
-               this_usbduxsub->ao_cmd_running = 1;
-               ret = usbduxsub_submit_outurbs(this_usbduxsub);
+       if (trignum != 0)
+               goto ao_trig_exit;
+
+       if (!devpriv->ao_cmd_running) {
+               devpriv->ao_cmd_running = 1;
+               ret = usbduxsub_submit_outurbs(dev);
                if (ret < 0) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: usbdux_ao_inttrig: submitURB: "
-                               "err=%d\n", dev->minor, ret);
-                       this_usbduxsub->ao_cmd_running = 0;
-                       up(&this_usbduxsub->sem);
-                       return ret;
+                       devpriv->ao_cmd_running = 0;
+                       goto ao_trig_exit;
                }
                s->async->inttrig = NULL;
        } else {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: ao_inttrig but acqu is already running.\n",
-                       dev->minor);
+               ret = -EBUSY;
        }
-       up(&this_usbduxsub->sem);
-       return 1;
+
+ao_trig_exit:
+       up(&devpriv->sem);
+       return ret;
 }
 
 static int usbdux_ao_cmdtest(struct comedi_device *dev,
                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int err = 0;
        unsigned int flags;
 
        if (!this_usbduxsub)
                return -EFAULT;
 
-       if (!(this_usbduxsub->probed))
-               return -ENODEV;
-
        /* Step 1 : check if triggers are trivially valid */
 
        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
@@ -1451,99 +1188,74 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev,
 
 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
+       struct usbdux_private *devpriv = dev->private;
        struct comedi_cmd *cmd = &s->async->cmd;
-       unsigned int chan, gain;
-       int i, ret;
-       struct usbduxsub *this_usbduxsub = dev->private;
+       int ret = -EBUSY;
+       int i;
 
-       if (!this_usbduxsub)
-               return -EFAULT;
+       down(&devpriv->sem);
 
-       down(&this_usbduxsub->sem);
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi%d: %s\n", dev->minor, __func__);
+       if (devpriv->ao_cmd_running)
+               goto ao_cmd_exit;
 
        /* set current channel of the running acquisition to zero */
        s->async->cur_chan = 0;
+
        for (i = 0; i < cmd->chanlist_len; ++i) {
-               chan = CR_CHAN(cmd->chanlist[i]);
-               gain = CR_RANGE(cmd->chanlist[i]);
-               if (i >= NUMOUTCHANNELS) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: %s: channel list too long\n",
-                               dev->minor, __func__);
+               unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
+               if (i >= NUMOUTCHANNELS)
                        break;
-               }
-               this_usbduxsub->dac_commands[i] = (chan << 6);
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: dac command for ch %d is %x\n",
-                       dev->minor, i, this_usbduxsub->dac_commands[i]);
+
+               devpriv->dac_commands[i] = chan << 6;
        }
 
        /* we count in steps of 1ms (125us) */
        /* 125us mode not used yet */
-       if (0) {                /* (this_usbduxsub->high_speed) */
+       if (0) {                /* (devpriv->high_speed) */
                /* 125us */
                /* timing of the conversion itself: every 125 us */
-               this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
+               devpriv->ao_timer = cmd->convert_arg / 125000;
        } else {
                /* 1ms */
                /* timing of the scan: we get all channels at once */
-               this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
-                       "convert_src=%d, convert_arg=%d\n", dev->minor,
-                       cmd->scan_begin_src, cmd->scan_begin_arg,
-                       cmd->convert_src, cmd->convert_arg);
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: ao_timer=%d (ms)\n",
-                       dev->minor, this_usbduxsub->ao_timer);
-               if (this_usbduxsub->ao_timer < 1) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: usbdux: ao_timer=%d, "
-                               "scan_begin_arg=%d. "
-                               "Not properly tested by cmdtest?\n",
-                               dev->minor, this_usbduxsub->ao_timer,
-                               cmd->scan_begin_arg);
-                       up(&this_usbduxsub->sem);
-                       return -EINVAL;
+               devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
+               if (devpriv->ao_timer < 1) {
+                       ret = -EINVAL;
+                       goto ao_cmd_exit;
                }
        }
-       this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+
+       devpriv->ao_counter = devpriv->ao_timer;
 
        if (cmd->stop_src == TRIG_COUNT) {
                /* not continuous */
                /* counter */
                /* high speed also scans everything at once */
-               if (0) {        /* (this_usbduxsub->high_speed) */
-                       this_usbduxsub->ao_sample_count =
-                           (cmd->stop_arg) * (cmd->scan_end_arg);
+               if (0) {        /* (devpriv->high_speed) */
+                       devpriv->ao_sample_count = cmd->stop_arg *
+                                                  cmd->scan_end_arg;
                } else {
                        /* there's no scan as the scan has been */
                        /* perf inside the FX2 */
                        /* data arrives as one packet */
-                       this_usbduxsub->ao_sample_count = cmd->stop_arg;
+                       devpriv->ao_sample_count = cmd->stop_arg;
                }
-               this_usbduxsub->ao_continous = 0;
+               devpriv->ao_continous = 0;
        } else {
                /* continous acquisition */
-               this_usbduxsub->ao_continous = 1;
-               this_usbduxsub->ao_sample_count = 0;
+               devpriv->ao_continous = 1;
+               devpriv->ao_sample_count = 0;
        }
 
        if (cmd->start_src == TRIG_NOW) {
                /* enable this acquisition operation */
-               this_usbduxsub->ao_cmd_running = 1;
-               ret = usbduxsub_submit_outurbs(this_usbduxsub);
+               devpriv->ao_cmd_running = 1;
+               ret = usbduxsub_submit_outurbs(dev);
                if (ret < 0) {
-                       this_usbduxsub->ao_cmd_running = 0;
+                       devpriv->ao_cmd_running = 0;
                        /* fixme: unlink here?? */
-                       up(&this_usbduxsub->sem);
-                       return ret;
+                       goto ao_cmd_exit;
                }
                s->async->inttrig = NULL;
        } else {
@@ -1553,38 +1265,38 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
                s->async->inttrig = usbdux_ao_inttrig;
        }
 
-       up(&this_usbduxsub->sem);
-       return 0;
+ao_cmd_exit:
+       up(&devpriv->sem);
+
+       return ret;
 }
 
 static int usbdux_dio_insn_config(struct comedi_device *dev,
                                  struct comedi_subdevice *s,
-                                 struct comedi_insn *insn, unsigned int *data)
+                                 struct comedi_insn *insn,
+                                 unsigned int *data)
 {
-       int chan = CR_CHAN(insn->chanspec);
-
-       /* 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. */
+       unsigned int mask = 1 << CR_CHAN(insn->chanspec);
 
        switch (data[0]) {
        case INSN_CONFIG_DIO_OUTPUT:
-               s->io_bits |= 1 << chan;        /* 1 means Out */
+               s->io_bits |= mask;
                break;
        case INSN_CONFIG_DIO_INPUT:
-               s->io_bits &= ~(1 << chan);
+               s->io_bits &= ~mask;
                break;
        case INSN_CONFIG_DIO_QUERY:
-               data[1] =
-                   (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
                break;
        default:
                return -EINVAL;
                break;
        }
-       /* we don't tell the firmware here as it would take 8 frames */
-       /* to submit the information. We do it in the insn_bits. */
+
+       /*
+        * We don't tell the firmware here as it would take 8 frames
+        * to submit the information. We do it in the insn_bits.
+        */
        return insn->n;
 }
 
@@ -1593,7 +1305,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
                                struct comedi_insn *insn, unsigned int *data)
 {
 
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int err;
 
        if (!this_usbduxsub)
@@ -1601,11 +1313,6 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
 
        down(&this_usbduxsub->sem);
 
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-
        /* The insn data is a mask in data[0] and the new data
         * in data[1], each channel cooresponding to a bit. */
        s->state &= ~data[0];
@@ -1615,12 +1322,12 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
 
        /* This command also tells the firmware to return */
        /* the digital input lines */
-       err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
+       err = send_dux_commands(dev, SENDDIOBITSCOMMAND);
        if (err < 0) {
                up(&this_usbduxsub->sem);
                return err;
        }
-       err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
+       err = receive_dux_commands(dev, SENDDIOBITSCOMMAND);
        if (err < 0) {
                up(&this_usbduxsub->sem);
                return err;
@@ -1636,7 +1343,7 @@ static int usbdux_counter_read(struct comedi_device *dev,
                               struct comedi_subdevice *s,
                               struct comedi_insn *insn, unsigned int *data)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int chan = insn->chanspec;
        int err;
 
@@ -1644,19 +1351,13 @@ static int usbdux_counter_read(struct comedi_device *dev,
                return -EFAULT;
 
        down(&this_usbduxsub->sem);
-
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-
-       err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
+       err = send_dux_commands(dev, READCOUNTERCOMMAND);
        if (err < 0) {
                up(&this_usbduxsub->sem);
                return err;
        }
 
-       err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
+       err = receive_dux_commands(dev, READCOUNTERCOMMAND);
        if (err < 0) {
                up(&this_usbduxsub->sem);
                return err;
@@ -1671,23 +1372,17 @@ static int usbdux_counter_write(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_insn *insn, unsigned int *data)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int err;
 
        if (!this_usbduxsub)
                return -EFAULT;
 
        down(&this_usbduxsub->sem);
-
-       if (!(this_usbduxsub->probed)) {
-               up(&this_usbduxsub->sem);
-               return -ENODEV;
-       }
-
        this_usbduxsub->dux_commands[1] = insn->chanspec;
        *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
 
-       err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
+       err = send_dux_commands(dev, WRITECOUNTERCOMMAND);
        if (err < 0) {
                up(&this_usbduxsub->sem);
                return err;
@@ -1709,15 +1404,13 @@ static int usbdux_counter_config(struct comedi_device *dev,
 /***********************************/
 /* PWM */
 
-static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp)
+static int usbduxsub_unlink_pwm_urbs(struct usbdux_private *usbduxsub_tmp)
 {
        int err = 0;
 
        if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) {
                if (usbduxsub_tmp->urb_pwm)
                        usb_kill_urb(usbduxsub_tmp->urb_pwm);
-               dev_dbg(&usbduxsub_tmp->interface->dev,
-                       "comedi: unlinked PwmURB: res=%d\n", err);
        }
        return err;
 }
@@ -1725,14 +1418,13 @@ static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp)
 /* This cancels a running acquisition operation
  * in any context.
  */
-static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+static int usbdux_pwm_stop(struct usbdux_private *this_usbduxsub, int do_unlink)
 {
        int ret = 0;
 
        if (!this_usbduxsub)
                return -EFAULT;
 
-       dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
        if (do_unlink)
                ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub);
 
@@ -1745,34 +1437,20 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 static int usbdux_pwm_cancel(struct comedi_device *dev,
                             struct comedi_subdevice *s)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int res = 0;
 
        /* unlink only if it is really running */
        res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
 
-       dev_dbg(&this_usbduxsub->interface->dev,
-               "comedi %d: sending pwm off command to the usb device.\n",
-               dev->minor);
-
-       return send_dux_commands(this_usbduxsub, SENDPWMOFF);
+       return send_dux_commands(dev, SENDPWMOFF);
 }
 
 static void usbduxsub_pwm_irq(struct urb *urb)
 {
+       struct comedi_device *dev = urb->context;
+       struct usbdux_private *devpriv = dev->private;
        int ret;
-       struct usbduxsub *this_usbduxsub;
-       struct comedi_device *this_comedidev;
-       struct comedi_subdevice *s;
-
-       /* printk(KERN_DEBUG "PWM: IRQ\n"); */
-
-       /* the context variable points to the subdevice */
-       this_comedidev = urb->context;
-       /* the private structure of the subdevice is struct usbduxsub */
-       this_usbduxsub = this_comedidev->private;
-
-       s = &this_comedidev->subdevices[SUBDEV_DA];
 
        switch (urb->status) {
        case 0:
@@ -1787,97 +1465,77 @@ static void usbduxsub_pwm_irq(struct urb *urb)
                 * after an unlink command, unplug, ... etc
                 * no unlink needed here. Already shutting down.
                 */
-               if (this_usbduxsub->pwm_cmd_running)
-                       usbdux_pwm_stop(this_usbduxsub, 0);
+               if (devpriv->pwm_cmd_running)
+                       usbdux_pwm_stop(devpriv, 0);
 
                return;
 
        default:
                /* a real error */
-               if (this_usbduxsub->pwm_cmd_running) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi_: Non-zero urb status received in "
-                               "pwm intr context: %d\n", urb->status);
-                       usbdux_pwm_stop(this_usbduxsub, 0);
+               if (devpriv->pwm_cmd_running) {
+                       dev_err(dev->class_dev,
+                               "Non-zero urb status received in pwm intr context: %d\n",
+                               urb->status);
+                       usbdux_pwm_stop(devpriv, 0);
                }
                return;
        }
 
        /* are we actually running? */
-       if (!(this_usbduxsub->pwm_cmd_running))
+       if (!devpriv->pwm_cmd_running)
                return;
 
-       urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf;
-       urb->dev = this_usbduxsub->usbdev;
+       urb->transfer_buffer_length = devpriv->size_pwm_buf;
+       urb->dev = comedi_to_usb_dev(dev);
        urb->status = 0;
-       if (this_usbduxsub->pwm_cmd_running) {
+       if (devpriv->pwm_cmd_running) {
                ret = usb_submit_urb(urb, GFP_ATOMIC);
                if (ret < 0) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi_: pwm urb resubm failed in int-cont. "
-                               "ret=%d", ret);
+                       dev_err(dev->class_dev,
+                               "pwm urb resubm failed in int-cont. ret=%d",
+                               ret);
                        if (ret == EL2NSYNC)
-                               dev_err(&this_usbduxsub->interface->dev,
-                                       "buggy USB host controller or bug in "
-                                       "IRQ handling!\n");
+                               dev_err(dev->class_dev,
+                                       "buggy USB host controller or bug in IRQ handling!\n");
 
                        /* don't do an unlink here */
-                       usbdux_pwm_stop(this_usbduxsub, 0);
+                       usbdux_pwm_stop(devpriv, 0);
                }
        }
 }
 
-static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub)
+static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev)
 {
-       int err_flag;
-
-       if (!usbduxsub)
-               return -EFAULT;
-
-       dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       struct urb *urb = devpriv->urb_pwm;
 
        /* in case of a resubmission after an unlink... */
-       usb_fill_bulk_urb(usbduxsub->urb_pwm,
-                         usbduxsub->usbdev,
-                         usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
-                         usbduxsub->urb_pwm->transfer_buffer,
-                         usbduxsub->size_pwm_buf, usbduxsub_pwm_irq,
-                         usbduxsub->comedidev);
-
-       err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC);
-       if (err_flag) {
-               dev_err(&usbduxsub->interface->dev,
-                       "comedi_: usbdux: pwm: usb_submit_urb error %d\n",
-                       err_flag);
-               return err_flag;
-       }
-       return 0;
+       usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, PWM_EP),
+                         urb->transfer_buffer,
+                         devpriv->size_pwm_buf,
+                         usbduxsub_pwm_irq,
+                         dev);
+
+       return usb_submit_urb(urb, GFP_ATOMIC);
 }
 
 static int usbdux_pwm_period(struct comedi_device *dev,
                             struct comedi_subdevice *s, unsigned int period)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int fx2delay = 255;
 
        if (period < MIN_PWM_PERIOD) {
-               dev_err(&this_usbduxsub->interface->dev,
-                       "comedi%d: illegal period setting for pwm.\n",
-                       dev->minor);
                return -EAGAIN;
        } else {
                fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
-               if (fx2delay > 255) {
-                       dev_err(&this_usbduxsub->interface->dev,
-                               "comedi%d: period %d for pwm is too low.\n",
-                               dev->minor, period);
+               if (fx2delay > 255)
                        return -EAGAIN;
-               }
        }
        this_usbduxsub->pwn_delay = fx2delay;
        this_usbduxsub->pwm_period = period;
-       dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
-               __func__, period, fx2delay);
+
        return 0;
 }
 
@@ -1886,10 +1544,7 @@ static int usbdux_pwm_start(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
        int ret, i;
-       struct usbduxsub *this_usbduxsub = dev->private;
-
-       dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
-               dev->minor, __func__);
+       struct usbdux_private *this_usbduxsub = dev->private;
 
        if (this_usbduxsub->pwm_cmd_running) {
                /* already running */
@@ -1897,7 +1552,7 @@ static int usbdux_pwm_start(struct comedi_device *dev,
        }
 
        this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay);
-       ret = send_dux_commands(this_usbduxsub, SENDPWMON);
+       ret = send_dux_commands(dev, SENDPWMON);
        if (ret < 0)
                return ret;
 
@@ -1906,7 +1561,7 @@ static int usbdux_pwm_start(struct comedi_device *dev,
                ((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0;
 
        this_usbduxsub->pwm_cmd_running = 1;
-       ret = usbduxsub_submit_pwm_urbs(this_usbduxsub);
+       ret = usbduxsub_submit_pwm_urbs(dev);
        if (ret < 0) {
                this_usbduxsub->pwm_cmd_running = 0;
                return ret;
@@ -1919,7 +1574,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev,
                              struct comedi_subdevice *s, int channel,
                              unsigned int value, unsigned int sign)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        int i, szbuf;
        char *p_buf;
        char pwm_mask;
@@ -1961,7 +1616,7 @@ static int usbdux_pwm_write(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
 
        if (!this_usbduxsub)
                return -EFAULT;
@@ -1995,12 +1650,10 @@ static int usbdux_pwm_config(struct comedi_device *dev,
                             struct comedi_subdevice *s,
                             struct comedi_insn *insn, unsigned int *data)
 {
-       struct usbduxsub *this_usbduxsub = dev->private;
+       struct usbdux_private *this_usbduxsub = dev->private;
        switch (data[0]) {
        case INSN_CONFIG_ARM:
                /* switch it on */
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: %s: pwm on\n", dev->minor, __func__);
                /*
                 * if not zero the PWM is limited to a certain time which is
                 * not supported here
@@ -2009,8 +1662,6 @@ static int usbdux_pwm_config(struct comedi_device *dev,
                        return -EINVAL;
                return usbdux_pwm_start(dev, s);
        case INSN_CONFIG_DISARM:
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: %s: pwm off\n", dev->minor, __func__);
                return usbdux_pwm_cancel(dev, s);
        case INSN_CONFIG_GET_PWM_STATUS:
                /*
@@ -2020,8 +1671,6 @@ static int usbdux_pwm_config(struct comedi_device *dev,
                data[1] = this_usbduxsub->pwm_cmd_running;
                return 0;
        case INSN_CONFIG_PWM_SET_PERIOD:
-               dev_dbg(&this_usbduxsub->interface->dev,
-                       "comedi%d: %s: setting period\n", dev->minor, __func__);
                return usbdux_pwm_period(dev, s, data[1]);
        case INSN_CONFIG_PWM_GET_PERIOD:
                data[1] = this_usbduxsub->pwm_period;
@@ -2046,249 +1695,294 @@ static int usbdux_pwm_config(struct comedi_device *dev,
 /* end of PWM */
 /*****************************************************************/
 
-static void tidy_up(struct usbduxsub *usbduxsub_tmp)
+static int usbdux_alloc_usb_buffers(struct comedi_device *dev)
 {
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv = dev->private;
+       struct urb *urb;
        int i;
 
-       if (!usbduxsub_tmp)
-               return;
-       dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
+       /* create space for the commands of the DA converter */
+       devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
+       if (!devpriv->dac_commands)
+               return -ENOMEM;
 
-       /* shows the usb subsystem that the driver is down */
-       if (usbduxsub_tmp->interface)
-               usb_set_intfdata(usbduxsub_tmp->interface, NULL);
+       /* create space for the commands going to the usb device */
+       devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
+       if (!devpriv->dux_commands)
+               return -ENOMEM;
 
-       usbduxsub_tmp->probed = 0;
+       /* create space for the in buffer and set it to zero */
+       devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+       if (!devpriv->in_buffer)
+               return -ENOMEM;
 
-       if (usbduxsub_tmp->urb_in) {
-               if (usbduxsub_tmp->ai_cmd_running) {
-                       usbduxsub_tmp->ai_cmd_running = 0;
-                       usbduxsub_unlink_inurbs(usbduxsub_tmp);
-               }
-               for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
-                       kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer);
-                       usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL;
-                       usb_kill_urb(usbduxsub_tmp->urb_in[i]);
-                       usb_free_urb(usbduxsub_tmp->urb_in[i]);
-                       usbduxsub_tmp->urb_in[i] = NULL;
-               }
-               kfree(usbduxsub_tmp->urb_in);
-               usbduxsub_tmp->urb_in = NULL;
+       /* create space of the instruction buffer */
+       devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
+       if (!devpriv->insn_buffer)
+               return -ENOMEM;
+
+       /* create space for the outbuffer */
+       devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+       if (!devpriv->out_buffer)
+               return -ENOMEM;
+
+       /* in urbs */
+       devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb),
+                                 GFP_KERNEL);
+       if (!devpriv->urb_in)
+               return -ENOMEM;
+
+       for (i = 0; i < devpriv->num_in_buffers; i++) {
+               /* one frame: 1ms */
+               urb = usb_alloc_urb(1, GFP_KERNEL);
+               if (!urb)
+                       return -ENOMEM;
+               devpriv->urb_in[i] = urb;
+
+               urb->dev = usb;
+               /* will be filled later with a pointer to the comedi-device */
+               /* and ONLY then the urb should be submitted */
+               urb->context = NULL;
+               urb->pipe = usb_rcvisocpipe(usb, ISOINEP);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+               if (!urb->transfer_buffer)
+                       return -ENOMEM;
+
+               urb->complete = usbduxsub_ai_isoc_irq;
+               urb->number_of_packets = 1;
+               urb->transfer_buffer_length = SIZEINBUF;
+               urb->iso_frame_desc[0].offset = 0;
+               urb->iso_frame_desc[0].length = SIZEINBUF;
        }
-       if (usbduxsub_tmp->urb_out) {
-               if (usbduxsub_tmp->ao_cmd_running) {
-                       usbduxsub_tmp->ao_cmd_running = 0;
-                       usbduxsub_unlink_outurbs(usbduxsub_tmp);
-               }
-               for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
-                       kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer);
-                       usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL;
-                       if (usbduxsub_tmp->urb_out[i]) {
-                               usb_kill_urb(usbduxsub_tmp->urb_out[i]);
-                               usb_free_urb(usbduxsub_tmp->urb_out[i]);
-                               usbduxsub_tmp->urb_out[i] = NULL;
+
+       /* out urbs */
+       devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb),
+                                  GFP_KERNEL);
+       if (!devpriv->urb_out)
+               return -ENOMEM;
+
+       for (i = 0; i < devpriv->num_out_buffers; i++) {
+               /* one frame: 1ms */
+               urb = usb_alloc_urb(1, GFP_KERNEL);
+               if (!urb)
+                       return -ENOMEM;
+               devpriv->urb_out[i] = urb;
+
+               urb->dev = usb;
+               /* will be filled later with a pointer to the comedi-device */
+               /* and ONLY then the urb should be submitted */
+               urb->context = NULL;
+               urb->pipe = usb_sndisocpipe(usb, ISOOUTEP);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+               if (!urb->transfer_buffer)
+                       return -ENOMEM;
+
+               urb->complete = usbduxsub_ao_isoc_irq;
+               urb->number_of_packets = 1;
+               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 */
+       }
+
+       /* pwm */
+       if (devpriv->size_pwm_buf) {
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb)
+                       return -ENOMEM;
+               devpriv->urb_pwm = urb;
+
+               /* max bulk ep size in high speed */
+               urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf,
+                                              GFP_KERNEL);
+               if (!urb->transfer_buffer)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void usbdux_free_usb_buffers(struct usbdux_private *devpriv)
+{
+       struct urb *urb;
+       int i;
+
+       urb = devpriv->urb_pwm;
+       if (urb) {
+               kfree(urb->transfer_buffer);
+               usb_kill_urb(urb);
+               usb_free_urb(urb);
+       }
+       if (devpriv->urb_out) {
+               for (i = 0; i < devpriv->num_out_buffers; i++) {
+                       urb = devpriv->urb_out[i];
+                       if (urb) {
+                               kfree(urb->transfer_buffer);
+                               usb_kill_urb(urb);
+                               usb_free_urb(urb);
                        }
                }
-               kfree(usbduxsub_tmp->urb_out);
-               usbduxsub_tmp->urb_out = NULL;
-       }
-       if (usbduxsub_tmp->urb_pwm) {
-               if (usbduxsub_tmp->pwm_cmd_running) {
-                       usbduxsub_tmp->pwm_cmd_running = 0;
-                       usbduxsub_unlink_pwm_urbs(usbduxsub_tmp);
+               kfree(devpriv->urb_out);
+       }
+       if (devpriv->urb_in) {
+               for (i = 0; i < devpriv->num_in_buffers; i++) {
+                       urb = devpriv->urb_in[i];
+                       if (urb) {
+                               kfree(urb->transfer_buffer);
+                               usb_kill_urb(urb);
+                               usb_free_urb(urb);
+                       }
                }
-               kfree(usbduxsub_tmp->urb_pwm->transfer_buffer);
-               usbduxsub_tmp->urb_pwm->transfer_buffer = NULL;
-               usb_kill_urb(usbduxsub_tmp->urb_pwm);
-               usb_free_urb(usbduxsub_tmp->urb_pwm);
-               usbduxsub_tmp->urb_pwm = NULL;
+               kfree(devpriv->urb_in);
        }
-       kfree(usbduxsub_tmp->in_buffer);
-       usbduxsub_tmp->in_buffer = NULL;
-       kfree(usbduxsub_tmp->insn_buffer);
-       usbduxsub_tmp->insn_buffer = NULL;
-       kfree(usbduxsub_tmp->out_buffer);
-       usbduxsub_tmp->out_buffer = NULL;
-       kfree(usbduxsub_tmp->dac_commands);
-       usbduxsub_tmp->dac_commands = NULL;
-       kfree(usbduxsub_tmp->dux_commands);
-       usbduxsub_tmp->dux_commands = NULL;
-       usbduxsub_tmp->ai_cmd_running = 0;
-       usbduxsub_tmp->ao_cmd_running = 0;
-       usbduxsub_tmp->pwm_cmd_running = 0;
+       kfree(devpriv->out_buffer);
+       kfree(devpriv->insn_buffer);
+       kfree(devpriv->in_buffer);
+       kfree(devpriv->dux_commands);
+       kfree(devpriv->dac_commands);
 }
 
-static int usbdux_attach_common(struct comedi_device *dev,
-                               struct usbduxsub *udev)
+static int usbdux_auto_attach(struct comedi_device *dev,
+                             unsigned long context_unused)
 {
+       struct usb_interface *intf = comedi_to_usb_interface(dev);
+       struct usb_device *usb = comedi_to_usb_dev(dev);
+       struct usbdux_private *devpriv;
+       struct comedi_subdevice *s;
        int ret;
-       struct comedi_subdevice *s = NULL;
-       int n_subdevs;
 
-       down(&udev->sem);
-       /* pointer back to the corresponding comedi device */
-       udev->comedidev = dev;
+       devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+       if (!devpriv)
+               return -ENOMEM;
+
+       sema_init(&devpriv->sem, 1);
 
-       /* set number of subdevices */
-       if (udev->high_speed) {
-               /* with pwm */
-               n_subdevs = 5;
+       usb_set_intfdata(intf, devpriv);
+
+       devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
+       if (devpriv->high_speed) {
+               devpriv->num_in_buffers = NUMOFINBUFFERSHIGH;
+               devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH;
+               devpriv->size_pwm_buf = 512;
        } else {
-               /* without pwm */
-               n_subdevs = 4;
+               devpriv->num_in_buffers = NUMOFINBUFFERSFULL;
+               devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL;
        }
 
-       ret = comedi_alloc_subdevices(dev, n_subdevs);
-       if (ret) {
-               up(&udev->sem);
+       ret = usbdux_alloc_usb_buffers(dev);
+       if (ret)
+               return ret;
+
+       /* setting to alternate setting 3: enabling iso ep and bulk ep. */
+       ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
+                               3);
+       if (ret < 0) {
+               dev_err(dev->class_dev,
+                       "could not set alternate setting 3 in high speed\n");
                return ret;
        }
 
-       /* private structure is also simply the usb-structure */
-       dev->private = udev;
+       ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
+                                  usbdux_firmware_upload, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4);
+       if (ret)
+               return ret;
 
-       /* the first subdevice is the A/D converter */
-       s = &dev->subdevices[SUBDEV_AD];
-       /* the URBs get the comedi subdevice */
-       /* which is responsible for reading */
-       /* this is the subdevice which reads data */
+       /* Analog Input subdevice */
+       s = &dev->subdevices[0];
        dev->read_subdev = s;
-       /* the subdevice receives as private structure the */
-       /* usb-structure */
-       s->private = NULL;
-       /* analog input */
-       s->type = COMEDI_SUBD_AI;
-       /* readable and ref is to ground */
-       s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
-       /* 8 channels */
-       s->n_chan = 8;
-       /* length of the channellist */
-       s->len_chanlist = 8;
-       /* callback functions */
-       s->insn_read = usbdux_ai_insn_read;
-       s->do_cmdtest = usbdux_ai_cmdtest;
-       s->do_cmd = usbdux_ai_cmd;
-       s->cancel = usbdux_ai_cancel;
-       /* max value from the A/D converter (12bit) */
-       s->maxdata = 0xfff;
-       /* range table to convert to physical units */
-       s->range_table = (&range_usbdux_ai_range);
-
-       /* analog out */
-       s = &dev->subdevices[SUBDEV_DA];
-       /* analog out */
-       s->type = COMEDI_SUBD_AO;
-       /* backward pointer */
+       s->type         = COMEDI_SUBD_AI;
+       s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+       s->n_chan       = 8;
+       s->maxdata      = 0x0fff;
+       s->len_chanlist = 8;
+       s->range_table  = &range_usbdux_ai_range;
+       s->insn_read    = usbdux_ai_insn_read;
+       s->do_cmdtest   = usbdux_ai_cmdtest;
+       s->do_cmd       = usbdux_ai_cmd;
+       s->cancel       = usbdux_ai_cancel;
+
+       /* Analog Output subdevice */
+       s = &dev->subdevices[1];
        dev->write_subdev = s;
-       /* the subdevice receives as private structure the */
-       /* usb-structure */
-       s->private = NULL;
-       /* are writable */
-       s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
-       /* 4 channels */
-       s->n_chan = 4;
-       /* length of the channellist */
-       s->len_chanlist = 4;
-       /* 12 bit resolution */
-       s->maxdata = 0x0fff;
-       /* bipolar range */
-       s->range_table = (&range_usbdux_ao_range);
-       /* callback */
-       s->do_cmdtest = usbdux_ao_cmdtest;
-       s->do_cmd = usbdux_ao_cmd;
-       s->cancel = usbdux_ao_cancel;
-       s->insn_read = usbdux_ao_insn_read;
-       s->insn_write = usbdux_ao_insn_write;
-
-       /* digital I/O */
-       s = &dev->subdevices[SUBDEV_DIO];
-       s->type = COMEDI_SUBD_DIO;
-       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-       s->n_chan = 8;
-       s->maxdata = 1;
-       s->range_table = (&range_digital);
-       s->insn_bits = usbdux_dio_insn_bits;
-       s->insn_config = usbdux_dio_insn_config;
-       /* we don't use it */
-       s->private = NULL;
-
-       /* counter */
-       s = &dev->subdevices[SUBDEV_COUNTER];
-       s->type = COMEDI_SUBD_COUNTER;
-       s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
-       s->n_chan = 4;
-       s->maxdata = 0xFFFF;
-       s->insn_read = usbdux_counter_read;
-       s->insn_write = usbdux_counter_write;
-       s->insn_config = usbdux_counter_config;
-
-       if (udev->high_speed) {
-               /* timer / pwm */
-               s = &dev->subdevices[SUBDEV_PWM];
-               s->type = COMEDI_SUBD_PWM;
-               s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
-               s->n_chan = 8;
-               /* this defines the max duty cycle resolution */
-               s->maxdata = udev->size_pwm_buf;
-               s->insn_write = usbdux_pwm_write;
-               s->insn_read = usbdux_pwm_read;
-               s->insn_config = usbdux_pwm_config;
+       s->type         = COMEDI_SUBD_AO;
+       s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
+       s->n_chan       = 4;
+       s->maxdata      = 0x0fff;
+       s->len_chanlist = 4;
+       s->range_table  = &range_usbdux_ao_range;
+       s->do_cmdtest   = usbdux_ao_cmdtest;
+       s->do_cmd       = usbdux_ao_cmd;
+       s->cancel       = usbdux_ao_cancel;
+       s->insn_read    = usbdux_ao_insn_read;
+       s->insn_write   = usbdux_ao_insn_write;
+
+       /* Digital I/O subdevice */
+       s = &dev->subdevices[2];
+       s->type         = COMEDI_SUBD_DIO;
+       s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+       s->n_chan       = 8;
+       s->maxdata      = 1;
+       s->range_table  = &range_digital;
+       s->insn_bits    = usbdux_dio_insn_bits;
+       s->insn_config  = usbdux_dio_insn_config;
+
+       /* Counter subdevice */
+       s = &dev->subdevices[3];
+       s->type         = COMEDI_SUBD_COUNTER;
+       s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+       s->n_chan       = 4;
+       s->maxdata      = 0xffff;
+       s->insn_read    = usbdux_counter_read;
+       s->insn_write   = usbdux_counter_write;
+       s->insn_config  = usbdux_counter_config;
+
+       if (devpriv->high_speed) {
+               /* PWM subdevice */
+               s = &dev->subdevices[4];
+               s->type         = COMEDI_SUBD_PWM;
+               s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
+               s->n_chan       = 8;
+               s->maxdata      = devpriv->size_pwm_buf;
+               s->insn_write   = usbdux_pwm_write;
+               s->insn_read    = usbdux_pwm_read;
+               s->insn_config  = usbdux_pwm_config;
+
                usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
        }
-       /* finally decide that it's attached */
-       udev->attached = 1;
-
-       up(&udev->sem);
-
-       dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
-                dev->minor);
 
        return 0;
 }
 
-static int usbdux_auto_attach(struct comedi_device *dev,
-                             unsigned long context_unused)
+static void usbdux_detach(struct comedi_device *dev)
 {
-       struct usb_interface *uinterf = comedi_to_usb_interface(dev);
-       struct usbduxsub *this_usbduxsub = usb_get_intfdata(uinterf);
-       struct usb_device *usb = usbduxsub->usbdev;
-       int ret;
+       struct usb_interface *intf = comedi_to_usb_interface(dev);
+       struct usbdux_private *devpriv = dev->private;
 
-       dev->private = this_usbduxsub;  /* This is temporary... */
-       ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
-                                  usbdux_firmware_upload, 0);
-       if (ret < 0) {
-               dev->private = NULL;
-               return ret;
-       }
+       if (devpriv) {
+               down(&devpriv->sem);
 
-       dev->private = NULL;
+               usb_set_intfdata(intf, NULL);
 
-       down(&start_stop_sem);
-       if (!this_usbduxsub || !this_usbduxsub->probed) {
-               dev_err(dev->class_dev,
-                       "usbdux: error: auto_attach failed, not connected\n");
-               ret = -ENODEV;
-       } else if (this_usbduxsub->attached) {
-               dev_err(dev->class_dev,
-                       "error: auto_attach failed, already attached\n");
-               ret = -ENODEV;
-       } else
-               ret = usbdux_attach_common(dev, this_usbduxsub);
-       up(&start_stop_sem);
-       return ret;
-}
+               if (devpriv->pwm_cmd_running)
+                       usbduxsub_unlink_pwm_urbs(devpriv);
+               if (devpriv->ao_cmd_running)
+                       usbduxsub_unlink_outurbs(devpriv);
+               if (devpriv->ai_cmd_running)
+                       usbduxsub_unlink_inurbs(devpriv);
 
-static void usbdux_detach(struct comedi_device *dev)
-{
-       struct usbduxsub *usb = dev->private;
-
-       if (usb) {
-               down(&usb->sem);
-               dev->private = NULL;
-               usb->attached = 0;
-               usb->comedidev = NULL;
-               up(&usb->sem);
+               usbdux_free_usb_buffers(devpriv);
+
+               up(&devpriv->sem);
        }
 }
 
@@ -2299,253 +1993,10 @@ static struct comedi_driver usbdux_driver = {
        .detach         = usbdux_detach,
 };
 
-static int usbdux_usb_probe(struct usb_interface *uinterf,
+static int usbdux_usb_probe(struct usb_interface *intf,
                            const struct usb_device_id *id)
 {
-       struct usb_device *udev = interface_to_usbdev(uinterf);
-       struct device *dev = &uinterf->dev;
-       int i;
-       int index;
-
-       dev_dbg(dev, "comedi_: usbdux_: "
-               "finding a free structure for the usb-device\n");
-
-       down(&start_stop_sem);
-       /* look for a free place in the usbdux array */
-       index = -1;
-       for (i = 0; i < NUMUSBDUX; i++) {
-               if (!(usbduxsub[i].probed)) {
-                       index = i;
-                       break;
-               }
-       }
-
-       /* no more space */
-       if (index == -1) {
-               dev_err(dev, "Too many usbdux-devices connected.\n");
-               up(&start_stop_sem);
-               return -EMFILE;
-       }
-       dev_dbg(dev, "comedi_: usbdux: "
-               "usbduxsub[%d] is ready to connect to comedi.\n", index);
-
-       sema_init(&(usbduxsub[index].sem), 1);
-       /* save a pointer to the usb device */
-       usbduxsub[index].usbdev = udev;
-
-       /* 2.6: save the interface itself */
-       usbduxsub[index].interface = uinterf;
-       /* get the interface number from the interface */
-       usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
-       /* hand the private data over to the usb subsystem */
-       /* will be needed for disconnect */
-       usb_set_intfdata(uinterf, &(usbduxsub[index]));
-
-       dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
-
-       /* test if it is high speed (USB 2.0) */
-       usbduxsub[index].high_speed =
-           (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
-
-       /* create space for the commands of the DA converter */
-       usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
-       if (!usbduxsub[index].dac_commands) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       /* create space for the commands going to the usb device */
-       usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
-       if (!usbduxsub[index].dux_commands) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       /* create space for the in buffer and set it to zero */
-       usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
-       if (!(usbduxsub[index].in_buffer)) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       /* create space of the instruction buffer */
-       usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
-       if (!(usbduxsub[index].insn_buffer)) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       /* create space for the outbuffer */
-       usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
-       if (!(usbduxsub[index].out_buffer)) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       /* setting to alternate setting 3: enabling iso ep and bulk ep. */
-       i = usb_set_interface(usbduxsub[index].usbdev,
-                             usbduxsub[index].ifnum, 3);
-       if (i < 0) {
-               dev_err(dev, "comedi_: usbdux%d: "
-                       "could not set alternate setting 3 in high speed.\n",
-                       index);
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENODEV;
-       }
-       if (usbduxsub[index].high_speed)
-               usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH;
-       else
-               usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL;
-
-       usbduxsub[index].urb_in =
-               kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *),
-                       GFP_KERNEL);
-       if (!(usbduxsub[index].urb_in)) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       for (i = 0; i < usbduxsub[index].num_in_buffers; i++) {
-               /* one frame: 1ms */
-               usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL);
-               if (usbduxsub[index].urb_in[i] == NULL) {
-                       dev_err(dev, "comedi_: usbdux%d: "
-                               "Could not alloc. urb(%d)\n", index, i);
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-               usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev;
-               /* will be filled later with a pointer to the comedi-device */
-               /* and ONLY then the urb should be submitted */
-               usbduxsub[index].urb_in[i]->context = NULL;
-               usbduxsub[index].urb_in[i]->pipe =
-                   usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
-               usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP;
-               usbduxsub[index].urb_in[i]->transfer_buffer =
-                   kzalloc(SIZEINBUF, GFP_KERNEL);
-               if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) {
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-               usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq;
-               usbduxsub[index].urb_in[i]->number_of_packets = 1;
-               usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF;
-               usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0;
-               usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF;
-       }
-
-       /* out */
-       if (usbduxsub[index].high_speed)
-               usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH;
-       else
-               usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL;
-
-       usbduxsub[index].urb_out =
-               kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *),
-                       GFP_KERNEL);
-       if (!(usbduxsub[index].urb_out)) {
-               tidy_up(&(usbduxsub[index]));
-               up(&start_stop_sem);
-               return -ENOMEM;
-       }
-       for (i = 0; i < usbduxsub[index].num_out_buffers; i++) {
-               /* one frame: 1ms */
-               usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL);
-               if (usbduxsub[index].urb_out[i] == NULL) {
-                       dev_err(dev, "comedi_: usbdux%d: "
-                               "Could not alloc. urb(%d)\n", index, i);
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-               usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev;
-               /* will be filled later with a pointer to the comedi-device */
-               /* and ONLY then the urb should be submitted */
-               usbduxsub[index].urb_out[i]->context = NULL;
-               usbduxsub[index].urb_out[i]->pipe =
-                   usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
-               usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP;
-               usbduxsub[index].urb_out[i]->transfer_buffer =
-                   kzalloc(SIZEOUTBUF, GFP_KERNEL);
-               if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) {
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-               usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq;
-               usbduxsub[index].urb_out[i]->number_of_packets = 1;
-               usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF;
-               usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0;
-               usbduxsub[index].urb_out[i]->iso_frame_desc[0].length =
-                   SIZEOUTBUF;
-               if (usbduxsub[index].high_speed) {
-                       /* uframes */
-                       usbduxsub[index].urb_out[i]->interval = 8;
-               } else {
-                       /* frames */
-                       usbduxsub[index].urb_out[i]->interval = 1;
-               }
-       }
-
-       /* pwm */
-       if (usbduxsub[index].high_speed) {
-               /* max bulk ep size in high speed */
-               usbduxsub[index].size_pwm_buf = 512;
-               usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL);
-               if (usbduxsub[index].urb_pwm == NULL) {
-                       dev_err(dev, "comedi_: usbdux%d: "
-                               "Could not alloc. pwm urb\n", index);
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-               usbduxsub[index].urb_pwm->transfer_buffer =
-                   kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL);
-               if (!(usbduxsub[index].urb_pwm->transfer_buffer)) {
-                       tidy_up(&(usbduxsub[index]));
-                       up(&start_stop_sem);
-                       return -ENOMEM;
-               }
-       } else {
-               usbduxsub[index].urb_pwm = NULL;
-               usbduxsub[index].size_pwm_buf = 0;
-       }
-
-       usbduxsub[index].ai_cmd_running = 0;
-       usbduxsub[index].ao_cmd_running = 0;
-       usbduxsub[index].pwm_cmd_running = 0;
-
-       /* we've reached the bottom of the function */
-       usbduxsub[index].probed = 1;
-       up(&start_stop_sem);
-
-       return comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
-}
-
-static void usbdux_usb_disconnect(struct usb_interface *intf)
-{
-       struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
-       struct usb_device *udev = interface_to_usbdev(intf);
-
-       if (!usbduxsub_tmp) {
-               dev_err(&intf->dev,
-                       "comedi_: disconnect called with null pointer.\n");
-               return;
-       }
-       if (usbduxsub_tmp->usbdev != udev) {
-               dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n");
-               return;
-       }
-       comedi_usb_auto_unconfig(intf);
-       down(&start_stop_sem);
-       down(&usbduxsub_tmp->sem);
-       tidy_up(usbduxsub_tmp);
-       up(&usbduxsub_tmp->sem);
-       up(&start_stop_sem);
-       dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
+       return comedi_usb_auto_config(intf, &usbdux_driver, 0);
 }
 
 static const struct usb_device_id usbdux_usb_table[] = {
@@ -2553,13 +2004,12 @@ static const struct usb_device_id usbdux_usb_table[] = {
        { USB_DEVICE(0x13d8, 0x0002) },
        { }
 };
-
 MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
 
 static struct usb_driver usbdux_usb_driver = {
        .name           = "usbdux",
        .probe          = usbdux_usb_probe,
-       .disconnect     = usbdux_usb_disconnect,
+       .disconnect     = comedi_usb_auto_unconfig,
        .id_table       = usbdux_usb_table,
 };
 module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);