linux/drivers/staging/comedi/drivers/usbdux.c
<<
>>
Prefs
   1/*
   2   comedi/drivers/usbdux.c
   3   Copyright (C) 2003-2007 Bernd Porr, Bernd.Porr@f2s.com
   4
   5   This program is free software; you can redistribute it and/or modify
   6   it under the terms of the GNU General Public License as published by
   7   the Free Software Foundation; either version 2 of the License, or
   8   (at your option) any later version.
   9
  10   This program is distributed in the hope that it will be useful,
  11   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13   GNU General Public License for more details.
  14
  15   You should have received a copy of the GNU General Public License
  16   along with this program; if not, write to the Free Software
  17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18
  19 */
  20/*
  21Driver: usbdux
  22Description: University of Stirling USB DAQ & INCITE Technology Limited
  23Devices: [ITL] USB-DUX (usbdux.o)
  24Author: Bernd Porr <BerndPorr@f2s.com>
  25Updated: 8 Dec 2008
  26Status: Stable
  27Configuration options:
  28  You have to upload firmware with the -i option. The
  29  firmware is usually installed under /usr/share/usb or
  30  /usr/local/share/usb or /lib/firmware.
  31
  32Connection scheme for the counter at the digital port:
  33  0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
  34  The sampling rate of the counter is approximately 500Hz.
  35
  36Please note that under USB2.0 the length of the channel list determines
  37the max sampling rate. If you sample only one channel you get 8kHz
  38sampling rate. If you sample two channels you get 4kHz and so on.
  39*/
  40/*
  41 * I must give credit here to Chris Baugher who
  42 * wrote the driver for AT-MIO-16d. I used some parts of this
  43 * driver. I also must give credits to David Brownell
  44 * who supported me with the USB development.
  45 *
  46 * Bernd Porr
  47 *
  48 *
  49 * Revision history:
  50 * 0.94: D/A output should work now with any channel list combinations
  51 * 0.95: .owner commented out for kernel vers below 2.4.19
  52 *       sanity checks in ai/ao_cmd
  53 * 0.96: trying to get it working with 2.6, moved all memory alloc to comedi's
  54 *       attach final USB IDs
  55 *       moved memory allocation completely to the corresponding comedi
  56 *       functions firmware upload is by fxload and no longer by comedi (due to
  57 *       enumeration)
  58 * 0.97: USB IDs received, adjusted table
  59 * 0.98: SMP, locking, memory alloc: moved all usb memory alloc
  60 *       to the usb subsystem and moved all comedi related memory
  61 *       alloc to comedi.
  62 *       | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
  63 * 0.99: USB 2.0: changed protocol to isochronous transfer
  64 *                IRQ transfer is too buggy and too risky in 2.0
  65 *                for the high speed ISO transfer is now a working version
  66 *                available
  67 * 0.99b: Increased the iso transfer buffer for high sp.to 10 buffers. Some VIA
  68 *        chipsets miss out IRQs. Deeper buffering is needed.
  69 * 1.00: full USB 2.0 support for the A/D converter. Now: max 8kHz sampling
  70 *       rate.
  71 *       Firmware vers 1.00 is needed for this.
  72 *       Two 16 bit up/down/reset counter with a sampling rate of 1kHz
  73 *       And loads of cleaning up, in particular streamlining the
  74 *       bulk transfers.
  75 * 1.1:  moved EP4 transfers to EP1 to make space for a PWM output on EP4
  76 * 1.2:  added PWM support via EP4
  77 * 2.0:  PWM seems to be stable and is not interfering with the other functions
  78 * 2.1:  changed PWM API
  79 * 2.2:  added firmware kernel request to fix an udev problem
  80 * 2.3:  corrected a bug in bulk timeouts which were far too short
  81 * 2.4:  fixed a bug which causes the driver to hang when it ran out of data.
  82 *       Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
  83 *
  84 */
  85
  86/* generates loads of debug info */
  87/* #define NOISY_DUX_DEBUGBUG */
  88
  89#include <linux/kernel.h>
  90#include <linux/module.h>
  91#include <linux/init.h>
  92#include <linux/slab.h>
  93#include <linux/input.h>
  94#include <linux/usb.h>
  95#include <linux/fcntl.h>
  96#include <linux/compiler.h>
  97#include <linux/firmware.h>
  98
  99#include "../comedidev.h"
 100
 101#include "comedi_fc.h"
 102
 103/* timeout for the USB-transfer in ms*/
 104#define BULK_TIMEOUT 1000
 105
 106/* constants for "firmware" upload and download */
 107#define FIRMWARE "usbdux_firmware.bin"
 108#define USBDUXSUB_FIRMWARE 0xA0
 109#define VENDOR_DIR_IN  0xC0
 110#define VENDOR_DIR_OUT 0x40
 111
 112/* internal addresses of the 8051 processor */
 113#define USBDUXSUB_CPUCS 0xE600
 114
 115/*
 116 * the minor device number, major is 180 only for debugging purposes and to
 117 * upload special firmware (programming the eeprom etc) which is not compatible
 118 * with the comedi framwork
 119 */
 120#define USBDUXSUB_MINOR 32
 121
 122/* max lenghth of the transfer-buffer for software upload */
 123#define TB_LEN 0x2000
 124
 125/* Input endpoint number: ISO/IRQ */
 126#define ISOINEP           6
 127
 128/* Output endpoint number: ISO/IRQ */
 129#define ISOOUTEP          2
 130
 131/* This EP sends DUX commands to USBDUX */
 132#define COMMAND_OUT_EP     1
 133
 134/* This EP receives the DUX commands from USBDUX */
 135#define COMMAND_IN_EP        8
 136
 137/* Output endpoint for PWM */
 138#define PWM_EP         4
 139
 140/* 300Hz max frequ under PWM */
 141#define MIN_PWM_PERIOD  ((long)(1E9/300))
 142
 143/* Default PWM frequency */
 144#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
 145
 146/* Number of channels */
 147#define NUMCHANNELS       8
 148
 149/* Size of one A/D value */
 150#define SIZEADIN          ((sizeof(int16_t)))
 151
 152/*
 153 * Size of the input-buffer IN BYTES
 154 * Always multiple of 8 for 8 microframes which is needed in the highspeed mode
 155 */
 156#define SIZEINBUF         ((8*SIZEADIN))
 157
 158/* 16 bytes. */
 159#define SIZEINSNBUF       16
 160
 161/* Number of DA channels */
 162#define NUMOUTCHANNELS    8
 163
 164/* size of one value for the D/A converter: channel and value */
 165#define SIZEDAOUT          ((sizeof(int8_t)+sizeof(int16_t)))
 166
 167/*
 168 * Size of the output-buffer in bytes
 169 * Actually only the first 4 triplets are used but for the
 170 * high speed mode we need to pad it to 8 (microframes).
 171 */
 172#define SIZEOUTBUF         ((8*SIZEDAOUT))
 173
 174/*
 175 * Size of the buffer for the dux commands: just now max size is determined
 176 * by the analogue out + command byte + panic bytes...
 177 */
 178#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
 179
 180/* Number of in-URBs which receive the data: min=2 */
 181#define NUMOFINBUFFERSFULL     5
 182
 183/* Number of out-URBs which send the data: min=2 */
 184#define NUMOFOUTBUFFERSFULL    5
 185
 186/* Number of in-URBs which receive the data: min=5 */
 187/* must have more buffers due to buggy USB ctr */
 188#define NUMOFINBUFFERSHIGH     10
 189
 190/* Number of out-URBs which send the data: min=5 */
 191/* must have more buffers due to buggy USB ctr */
 192#define NUMOFOUTBUFFERSHIGH    10
 193
 194/* Total number of usbdux devices */
 195#define NUMUSBDUX             16
 196
 197/* Analogue in subdevice */
 198#define SUBDEV_AD             0
 199
 200/* Analogue out subdevice */
 201#define SUBDEV_DA             1
 202
 203/* Digital I/O */
 204#define SUBDEV_DIO            2
 205
 206/* counter */
 207#define SUBDEV_COUNTER        3
 208
 209/* timer aka pwm output */
 210#define SUBDEV_PWM            4
 211
 212/* number of retries to get the right dux command */
 213#define RETRIES 10
 214
 215/**************************************************/
 216/* comedi constants */
 217static const struct comedi_lrange range_usbdux_ai_range = { 4, {
 218                                                                BIP_RANGE
 219                                                                (4.096),
 220                                                                BIP_RANGE(4.096
 221                                                                          / 2),
 222                                                                UNI_RANGE
 223                                                                (4.096),
 224                                                                UNI_RANGE(4.096
 225                                                                          / 2)
 226                                                                }
 227};
 228
 229static const struct comedi_lrange range_usbdux_ao_range = { 2, {
 230                                                                BIP_RANGE
 231                                                                (4.096),
 232                                                                UNI_RANGE
 233                                                                (4.096),
 234                                                                }
 235};
 236
 237/*
 238 * private structure of one subdevice
 239 */
 240
 241/*
 242 * This is the structure which holds all the data of
 243 * this driver one sub device just now: A/D
 244 */
 245struct usbduxsub {
 246        /* attached? */
 247        int attached;
 248        /* is it associated with a subdevice? */
 249        int probed;
 250        /* pointer to the usb-device */
 251        struct usb_device *usbdev;
 252        /* actual number of in-buffers */
 253        int num_in_buffers;
 254        /* actual number of out-buffers */
 255        int num_out_buffers;
 256        /* ISO-transfer handling: buffers */
 257        struct urb **urb_in;
 258        struct urb **urb_out;
 259        /* pwm-transfer handling */
 260        struct urb *urb_pwm;
 261        /* PWM period */
 262        unsigned int pwm_period;
 263        /* PWM internal delay for the GPIF in the FX2 */
 264        int8_t pwn_delay;
 265        /* size of the PWM buffer which holds the bit pattern */
 266        int size_pwm_buf;
 267        /* input buffer for the ISO-transfer */
 268        int16_t *in_buffer;
 269        /* input buffer for single insn */
 270        int16_t *insn_buffer;
 271        /* output buffer for single DA outputs */
 272        int16_t *out_buffer;
 273        /* interface number */
 274        int ifnum;
 275        /* interface structure in 2.6 */
 276        struct usb_interface *interface;
 277        /* comedi device for the interrupt context */
 278        struct comedi_device *comedidev;
 279        /* is it USB_SPEED_HIGH or not? */
 280        short int high_speed;
 281        /* asynchronous command is running */
 282        short int ai_cmd_running;
 283        short int ao_cmd_running;
 284        /* pwm is running */
 285        short int pwm_cmd_running;
 286        /* continous acquisition */
 287        short int ai_continous;
 288        short int ao_continous;
 289        /* number of samples to acquire */
 290        int ai_sample_count;
 291        int ao_sample_count;
 292        /* time between samples in units of the timer */
 293        unsigned int ai_timer;
 294        unsigned int ao_timer;
 295        /* counter between aquisitions */
 296        unsigned int ai_counter;
 297        unsigned int ao_counter;
 298        /* interval in frames/uframes */
 299        unsigned int ai_interval;
 300        /* D/A commands */
 301        int8_t *dac_commands;
 302        /* commands */
 303        int8_t *dux_commands;
 304        struct semaphore sem;
 305};
 306
 307/*
 308 * The pointer to the private usb-data of the driver is also the private data
 309 * for the comedi-device.  This has to be global as the usb subsystem needs
 310 * global variables. The other reason is that this structure must be there
 311 * _before_ any comedi command is issued. The usb subsystem must be initialised
 312 * before comedi can access it.
 313 */
 314static struct usbduxsub usbduxsub[NUMUSBDUX];
 315
 316static DEFINE_SEMAPHORE(start_stop_sem);
 317
 318/*
 319 * Stops the data acquision
 320 * It should be safe to call this function from any context
 321 */
 322static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp)
 323{
 324        int i = 0;
 325        int err = 0;
 326
 327        if (usbduxsub_tmp && usbduxsub_tmp->urb_in) {
 328                for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
 329                        if (usbduxsub_tmp->urb_in[i]) {
 330                                /* We wait here until all transfers have been
 331                                 * cancelled. */
 332                                usb_kill_urb(usbduxsub_tmp->urb_in[i]);
 333                        }
 334                        dev_dbg(&usbduxsub_tmp->interface->dev,
 335                                "comedi: usbdux: unlinked InURB %d, err=%d\n",
 336                                i, err);
 337                }
 338        }
 339        return err;
 340}
 341
 342/*
 343 * This will stop a running acquisition operation
 344 * Is called from within this driver from both the
 345 * interrupt context and from comedi
 346 */
 347static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 348{
 349        int ret = 0;
 350
 351        if (!this_usbduxsub) {
 352                pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
 353                return -EFAULT;
 354        }
 355        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
 356
 357        if (do_unlink) {
 358                /* stop aquistion */
 359                ret = usbduxsub_unlink_inurbs(this_usbduxsub);
 360        }
 361
 362        this_usbduxsub->ai_cmd_running = 0;
 363
 364        return ret;
 365}
 366
 367/*
 368 * This will cancel a running acquisition operation.
 369 * This is called by comedi but never from inside the driver.
 370 */
 371static int usbdux_ai_cancel(struct comedi_device *dev,
 372                            struct comedi_subdevice *s)
 373{
 374        struct usbduxsub *this_usbduxsub;
 375        int res = 0;
 376
 377        /* force unlink of all urbs */
 378        this_usbduxsub = dev->private;
 379        if (!this_usbduxsub)
 380                return -EFAULT;
 381
 382        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
 383
 384        /* prevent other CPUs from submitting new commands just now */
 385        down(&this_usbduxsub->sem);
 386        if (!(this_usbduxsub->probed)) {
 387                up(&this_usbduxsub->sem);
 388                return -ENODEV;
 389        }
 390        /* unlink only if the urb really has been submitted */
 391        res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
 392        up(&this_usbduxsub->sem);
 393        return res;
 394}
 395
 396/* analogue IN - interrupt service routine */
 397static void usbduxsub_ai_isoc_irq(struct urb *urb)
 398{
 399        int i, err, n;
 400        struct usbduxsub *this_usbduxsub;
 401        struct comedi_device *this_comedidev;
 402        struct comedi_subdevice *s;
 403
 404        /* the context variable points to the subdevice */
 405        this_comedidev = urb->context;
 406        /* the private structure of the subdevice is struct usbduxsub */
 407        this_usbduxsub = this_comedidev->private;
 408        /* subdevice which is the AD converter */
 409        s = &this_comedidev->subdevices[SUBDEV_AD];
 410
 411        /* first we test if something unusual has just happened */
 412        switch (urb->status) {
 413        case 0:
 414                /* copy the result in the transfer buffer */
 415                memcpy(this_usbduxsub->in_buffer,
 416                       urb->transfer_buffer, SIZEINBUF);
 417                break;
 418        case -EILSEQ:
 419                /* error in the ISOchronous data */
 420                /* we don't copy the data into the transfer buffer */
 421                /* and recycle the last data byte */
 422                dev_dbg(&urb->dev->dev,
 423                        "comedi%d: usbdux: CRC error in ISO IN stream.\n",
 424                        this_usbduxsub->comedidev->minor);
 425
 426                break;
 427
 428        case -ECONNRESET:
 429        case -ENOENT:
 430        case -ESHUTDOWN:
 431        case -ECONNABORTED:
 432                /* happens after an unlink command */
 433                if (this_usbduxsub->ai_cmd_running) {
 434                        /* we are still running a command */
 435                        /* tell this comedi */
 436                        s->async->events |= COMEDI_CB_EOA;
 437                        s->async->events |= COMEDI_CB_ERROR;
 438                        comedi_event(this_usbduxsub->comedidev, s);
 439                        /* stop the transfer w/o unlink */
 440                        usbdux_ai_stop(this_usbduxsub, 0);
 441                }
 442                return;
 443
 444        default:
 445                /* a real error on the bus */
 446                /* pass error to comedi if we are really running a command */
 447                if (this_usbduxsub->ai_cmd_running) {
 448                        dev_err(&urb->dev->dev,
 449                                "Non-zero urb status received in ai intr "
 450                                "context: %d\n", urb->status);
 451                        s->async->events |= COMEDI_CB_EOA;
 452                        s->async->events |= COMEDI_CB_ERROR;
 453                        comedi_event(this_usbduxsub->comedidev, s);
 454                        /* don't do an unlink here */
 455                        usbdux_ai_stop(this_usbduxsub, 0);
 456                }
 457                return;
 458        }
 459
 460        /*
 461         * at this point we are reasonably sure that nothing dodgy has happened
 462         * are we running a command?
 463         */
 464        if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
 465                /*
 466                 * not running a command, do not continue execution if no
 467                 * asynchronous command is running in particular not resubmit
 468                 */
 469                return;
 470        }
 471
 472        urb->dev = this_usbduxsub->usbdev;
 473
 474        /* resubmit the urb */
 475        err = usb_submit_urb(urb, GFP_ATOMIC);
 476        if (unlikely(err < 0)) {
 477                dev_err(&urb->dev->dev,
 478                        "comedi_: urb resubmit failed in int-context! err=%d\n",
 479                        err);
 480                if (err == -EL2NSYNC)
 481                        dev_err(&urb->dev->dev,
 482                                "buggy USB host controller or bug in IRQ "
 483                                "handler!\n");
 484                s->async->events |= COMEDI_CB_EOA;
 485                s->async->events |= COMEDI_CB_ERROR;
 486                comedi_event(this_usbduxsub->comedidev, s);
 487                /* don't do an unlink here */
 488                usbdux_ai_stop(this_usbduxsub, 0);
 489                return;
 490        }
 491
 492        this_usbduxsub->ai_counter--;
 493        if (likely(this_usbduxsub->ai_counter > 0))
 494                return;
 495
 496        /* timer zero, transfer measurements to comedi */
 497        this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
 498
 499        /* test, if we transmit only a fixed number of samples */
 500        if (!(this_usbduxsub->ai_continous)) {
 501                /* not continuous, fixed number of samples */
 502                this_usbduxsub->ai_sample_count--;
 503                /* all samples received? */
 504                if (this_usbduxsub->ai_sample_count < 0) {
 505                        /* prevent a resubmit next time */
 506                        usbdux_ai_stop(this_usbduxsub, 0);
 507                        /* say comedi that the acquistion is over */
 508                        s->async->events |= COMEDI_CB_EOA;
 509                        comedi_event(this_usbduxsub->comedidev, s);
 510                        return;
 511                }
 512        }
 513        /* get the data from the USB bus and hand it over to comedi */
 514        n = s->async->cmd.chanlist_len;
 515        for (i = 0; i < n; i++) {
 516                /* transfer data */
 517                if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
 518                        err = comedi_buf_put
 519                            (s->async,
 520                             le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800);
 521                } else {
 522                        err = comedi_buf_put
 523                            (s->async,
 524                             le16_to_cpu(this_usbduxsub->in_buffer[i]));
 525                }
 526                if (unlikely(err == 0)) {
 527                        /* buffer overflow */
 528                        usbdux_ai_stop(this_usbduxsub, 0);
 529                        return;
 530                }
 531        }
 532        /* tell comedi that data is there */
 533        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
 534        comedi_event(this_usbduxsub->comedidev, s);
 535}
 536
 537static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp)
 538{
 539        int i = 0;
 540        int err = 0;
 541
 542        if (usbduxsub_tmp && usbduxsub_tmp->urb_out) {
 543                for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
 544                        if (usbduxsub_tmp->urb_out[i])
 545                                usb_kill_urb(usbduxsub_tmp->urb_out[i]);
 546
 547                        dev_dbg(&usbduxsub_tmp->interface->dev,
 548                                "comedi: usbdux: unlinked OutURB %d: res=%d\n",
 549                                i, err);
 550                }
 551        }
 552        return err;
 553}
 554
 555/* This will cancel a running acquisition operation
 556 * in any context.
 557 */
 558static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 559{
 560        int ret = 0;
 561
 562        if (!this_usbduxsub)
 563                return -EFAULT;
 564        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
 565
 566        if (do_unlink)
 567                ret = usbduxsub_unlink_outurbs(this_usbduxsub);
 568
 569        this_usbduxsub->ao_cmd_running = 0;
 570
 571        return ret;
 572}
 573
 574/* force unlink, is called by comedi */
 575static int usbdux_ao_cancel(struct comedi_device *dev,
 576                            struct comedi_subdevice *s)
 577{
 578        struct usbduxsub *this_usbduxsub = dev->private;
 579        int res = 0;
 580
 581        if (!this_usbduxsub)
 582                return -EFAULT;
 583
 584        /* prevent other CPUs from submitting a command just now */
 585        down(&this_usbduxsub->sem);
 586        if (!(this_usbduxsub->probed)) {
 587                up(&this_usbduxsub->sem);
 588                return -ENODEV;
 589        }
 590        /* unlink only if it is really running */
 591        res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
 592        up(&this_usbduxsub->sem);
 593        return res;
 594}
 595
 596static void usbduxsub_ao_isoc_irq(struct urb *urb)
 597{
 598        int i, ret;
 599        int8_t *datap;
 600        struct usbduxsub *this_usbduxsub;
 601        struct comedi_device *this_comedidev;
 602        struct comedi_subdevice *s;
 603
 604        /* the context variable points to the subdevice */
 605        this_comedidev = urb->context;
 606        /* the private structure of the subdevice is struct usbduxsub */
 607        this_usbduxsub = this_comedidev->private;
 608
 609        s = &this_comedidev->subdevices[SUBDEV_DA];
 610
 611        switch (urb->status) {
 612        case 0:
 613                /* success */
 614                break;
 615
 616        case -ECONNRESET:
 617        case -ENOENT:
 618        case -ESHUTDOWN:
 619        case -ECONNABORTED:
 620                /* after an unlink command, unplug, ... etc */
 621                /* no unlink needed here. Already shutting down. */
 622                if (this_usbduxsub->ao_cmd_running) {
 623                        s->async->events |= COMEDI_CB_EOA;
 624                        comedi_event(this_usbduxsub->comedidev, s);
 625                        usbdux_ao_stop(this_usbduxsub, 0);
 626                }
 627                return;
 628
 629        default:
 630                /* a real error */
 631                if (this_usbduxsub->ao_cmd_running) {
 632                        dev_err(&urb->dev->dev,
 633                                "comedi_: Non-zero urb status received in ao "
 634                                "intr context: %d\n", urb->status);
 635                        s->async->events |= COMEDI_CB_ERROR;
 636                        s->async->events |= COMEDI_CB_EOA;
 637                        comedi_event(this_usbduxsub->comedidev, s);
 638                        /* we do an unlink if we are in the high speed mode */
 639                        usbdux_ao_stop(this_usbduxsub, 0);
 640                }
 641                return;
 642        }
 643
 644        /* are we actually running? */
 645        if (!(this_usbduxsub->ao_cmd_running))
 646                return;
 647
 648        /* normal operation: executing a command in this subdevice */
 649        this_usbduxsub->ao_counter--;
 650        if ((int)this_usbduxsub->ao_counter <= 0) {
 651                /* timer zero */
 652                this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
 653
 654                /* handle non continous acquisition */
 655                if (!(this_usbduxsub->ao_continous)) {
 656                        /* fixed number of samples */
 657                        this_usbduxsub->ao_sample_count--;
 658                        if (this_usbduxsub->ao_sample_count < 0) {
 659                                /* all samples transmitted */
 660                                usbdux_ao_stop(this_usbduxsub, 0);
 661                                s->async->events |= COMEDI_CB_EOA;
 662                                comedi_event(this_usbduxsub->comedidev, s);
 663                                /* no resubmit of the urb */
 664                                return;
 665                        }
 666                }
 667                /* transmit data to the USB bus */
 668                ((uint8_t *) (urb->transfer_buffer))[0] =
 669                    s->async->cmd.chanlist_len;
 670                for (i = 0; i < s->async->cmd.chanlist_len; i++) {
 671                        short temp;
 672                        if (i >= NUMOUTCHANNELS)
 673                                break;
 674
 675                        /* pointer to the DA */
 676                        datap =
 677                            (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1]));
 678                        /* get the data from comedi */
 679                        ret = comedi_buf_get(s->async, &temp);
 680                        datap[0] = temp;
 681                        datap[1] = temp >> 8;
 682                        datap[2] = this_usbduxsub->dac_commands[i];
 683                        /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
 684                        /* datap[0],datap[1],datap[2]); */
 685                        if (ret < 0) {
 686                                dev_err(&urb->dev->dev,
 687                                        "comedi: buffer underflow\n");
 688                                s->async->events |= COMEDI_CB_EOA;
 689                                s->async->events |= COMEDI_CB_OVERFLOW;
 690                        }
 691                        /* transmit data to comedi */
 692                        s->async->events |= COMEDI_CB_BLOCK;
 693                        comedi_event(this_usbduxsub->comedidev, s);
 694                }
 695        }
 696        urb->transfer_buffer_length = SIZEOUTBUF;
 697        urb->dev = this_usbduxsub->usbdev;
 698        urb->status = 0;
 699        if (this_usbduxsub->ao_cmd_running) {
 700                if (this_usbduxsub->high_speed) {
 701                        /* uframes */
 702                        urb->interval = 8;
 703                } else {
 704                        /* frames */
 705                        urb->interval = 1;
 706                }
 707                urb->number_of_packets = 1;
 708                urb->iso_frame_desc[0].offset = 0;
 709                urb->iso_frame_desc[0].length = SIZEOUTBUF;
 710                urb->iso_frame_desc[0].status = 0;
 711                ret = usb_submit_urb(urb, GFP_ATOMIC);
 712                if (ret < 0) {
 713                        dev_err(&urb->dev->dev,
 714                                "comedi_: ao urb resubm failed in int-cont. "
 715                                "ret=%d", ret);
 716                        if (ret == EL2NSYNC)
 717                                dev_err(&urb->dev->dev,
 718                                        "buggy USB host controller or bug in "
 719                                        "IRQ handling!\n");
 720
 721                        s->async->events |= COMEDI_CB_EOA;
 722                        s->async->events |= COMEDI_CB_ERROR;
 723                        comedi_event(this_usbduxsub->comedidev, s);
 724                        /* don't do an unlink here */
 725                        usbdux_ao_stop(this_usbduxsub, 0);
 726                }
 727        }
 728}
 729
 730static int usbduxsub_start(struct usbduxsub *usbduxsub)
 731{
 732        int errcode = 0;
 733        uint8_t *local_transfer_buffer;
 734
 735        local_transfer_buffer = kmalloc(1, GFP_KERNEL);
 736        if (!local_transfer_buffer)
 737                return -ENOMEM;
 738
 739        /* 7f92 to zero */
 740        *local_transfer_buffer = 0;
 741        errcode = usb_control_msg(usbduxsub->usbdev,
 742                                  /* create a pipe for a control transfer */
 743                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 744                                  /* bRequest, "Firmware" */
 745                                  USBDUXSUB_FIRMWARE,
 746                                  /* bmRequestType */
 747                                  VENDOR_DIR_OUT,
 748                                  /* Value */
 749                                  USBDUXSUB_CPUCS,
 750                                  /* Index */
 751                                  0x0000,
 752                                  /* address of the transfer buffer */
 753                                  local_transfer_buffer,
 754                                  /* Length */
 755                                  1,
 756                                  /* Timeout */
 757                                  BULK_TIMEOUT);
 758        if (errcode < 0)
 759                dev_err(&usbduxsub->interface->dev,
 760                        "comedi_: control msg failed (start)\n");
 761
 762        kfree(local_transfer_buffer);
 763        return errcode;
 764}
 765
 766static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 767{
 768        int errcode = 0;
 769        uint8_t *local_transfer_buffer;
 770
 771        local_transfer_buffer = kmalloc(1, GFP_KERNEL);
 772        if (!local_transfer_buffer)
 773                return -ENOMEM;
 774
 775        /* 7f92 to one */
 776        *local_transfer_buffer = 1;
 777        errcode = usb_control_msg(usbduxsub->usbdev,
 778                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 779                                  /* bRequest, "Firmware" */
 780                                  USBDUXSUB_FIRMWARE,
 781                                  /* bmRequestType */
 782                                  VENDOR_DIR_OUT,
 783                                  /* Value */
 784                                  USBDUXSUB_CPUCS,
 785                                  /* Index */
 786                                  0x0000, local_transfer_buffer,
 787                                  /* Length */
 788                                  1,
 789                                  /* Timeout */
 790                                  BULK_TIMEOUT);
 791        if (errcode < 0)
 792                dev_err(&usbduxsub->interface->dev,
 793                        "comedi_: control msg failed (stop)\n");
 794
 795        kfree(local_transfer_buffer);
 796        return errcode;
 797}
 798
 799static int usbduxsub_upload(struct usbduxsub *usbduxsub,
 800                            uint8_t *local_transfer_buffer,
 801                            unsigned int start_addr, unsigned int len)
 802{
 803        int errcode;
 804
 805        errcode = usb_control_msg(usbduxsub->usbdev,
 806                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 807                                  /* brequest, firmware */
 808                                  USBDUXSUB_FIRMWARE,
 809                                  /* bmRequestType */
 810                                  VENDOR_DIR_OUT,
 811                                  /* value */
 812                                  start_addr,
 813                                  /* index */
 814                                  0x0000,
 815                                  /* our local safe buffer */
 816                                  local_transfer_buffer,
 817                                  /* length */
 818                                  len,
 819                                  /* timeout */
 820                                  BULK_TIMEOUT);
 821        dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
 822        if (errcode < 0) {
 823                dev_err(&usbduxsub->interface->dev, "comedi_: upload failed\n");
 824                return errcode;
 825        }
 826        return 0;
 827}
 828
 829#define FIRMWARE_MAX_LEN 0x2000
 830
 831static int firmware_upload(struct usbduxsub *usbduxsub,
 832                          const u8 *firmware_binary, int size_firmware)
 833{
 834        int ret;
 835        uint8_t *fw_buf;
 836
 837        if (!firmware_binary)
 838                return 0;
 839
 840        if (size_firmware > FIRMWARE_MAX_LEN) {
 841                dev_err(&usbduxsub->interface->dev,
 842                        "usbdux firmware binary it too large for FX2.\n");
 843                return -ENOMEM;
 844        }
 845
 846        /* we generate a local buffer for the firmware */
 847        fw_buf = kmemdup(firmware_binary, size_firmware, GFP_KERNEL);
 848        if (!fw_buf) {
 849                dev_err(&usbduxsub->interface->dev,
 850                        "comedi_: mem alloc for firmware failed\n");
 851                return -ENOMEM;
 852        }
 853
 854        ret = usbduxsub_stop(usbduxsub);
 855        if (ret < 0) {
 856                dev_err(&usbduxsub->interface->dev,
 857                        "comedi_: can not stop firmware\n");
 858                kfree(fw_buf);
 859                return ret;
 860        }
 861
 862        ret = usbduxsub_upload(usbduxsub, fw_buf, 0, size_firmware);
 863        if (ret < 0) {
 864                dev_err(&usbduxsub->interface->dev,
 865                        "comedi_: firmware upload failed\n");
 866                kfree(fw_buf);
 867                return ret;
 868        }
 869        ret = usbduxsub_start(usbduxsub);
 870        if (ret < 0) {
 871                dev_err(&usbduxsub->interface->dev,
 872                        "comedi_: can not start firmware\n");
 873                kfree(fw_buf);
 874                return ret;
 875        }
 876        kfree(fw_buf);
 877        return 0;
 878}
 879
 880static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub)
 881{
 882        int i, err_flag;
 883
 884        if (!usbduxsub)
 885                return -EFAULT;
 886
 887        /* Submit all URBs and start the transfer on the bus */
 888        for (i = 0; i < usbduxsub->num_in_buffers; i++) {
 889                /* in case of a resubmission after an unlink... */
 890                usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval;
 891                usbduxsub->urb_in[i]->context = usbduxsub->comedidev;
 892                usbduxsub->urb_in[i]->dev = usbduxsub->usbdev;
 893                usbduxsub->urb_in[i]->status = 0;
 894                usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP;
 895                dev_dbg(&usbduxsub->interface->dev,
 896                        "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
 897                        usbduxsub->comedidev->minor, i,
 898                        (usbduxsub->urb_in[i]->context),
 899                        (usbduxsub->urb_in[i]->dev),
 900                        (usbduxsub->urb_in[i]->interval));
 901                err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC);
 902                if (err_flag) {
 903                        dev_err(&usbduxsub->interface->dev,
 904                                "comedi_: ai: usb_submit_urb(%d) error %d\n",
 905                                i, err_flag);
 906                        return err_flag;
 907                }
 908        }
 909        return 0;
 910}
 911
 912static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub)
 913{
 914        int i, err_flag;
 915
 916        if (!usbduxsub)
 917                return -EFAULT;
 918
 919        for (i = 0; i < usbduxsub->num_out_buffers; i++) {
 920                dev_dbg(&usbduxsub->interface->dev,
 921                        "comedi_: submitting out-urb[%d]\n", i);
 922                /* in case of a resubmission after an unlink... */
 923                usbduxsub->urb_out[i]->context = usbduxsub->comedidev;
 924                usbduxsub->urb_out[i]->dev = usbduxsub->usbdev;
 925                usbduxsub->urb_out[i]->status = 0;
 926                usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP;
 927                err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC);
 928                if (err_flag) {
 929                        dev_err(&usbduxsub->interface->dev,
 930                                "comedi_: ao: usb_submit_urb(%d) error %d\n",
 931                                i, err_flag);
 932                        return err_flag;
 933                }
 934        }
 935        return 0;
 936}
 937
 938static int usbdux_ai_cmdtest(struct comedi_device *dev,
 939                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 940{
 941        struct usbduxsub *this_usbduxsub = dev->private;
 942        int err = 0, i;
 943        unsigned int tmp_timer;
 944
 945        if (!(this_usbduxsub->probed))
 946                return -ENODEV;
 947
 948        /* Step 1 : check if triggers are trivially valid */
 949
 950        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 951        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
 952        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 953        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 954        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 955
 956        if (err)
 957                return 1;
 958
 959        /* Step 2a : make sure trigger sources are unique */
 960
 961        err |= cfc_check_trigger_is_unique(cmd->start_src);
 962        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 963
 964        /* Step 2b : and mutually compatible */
 965
 966        if (err)
 967                return 2;
 968
 969        /* Step 3: check if arguments are trivially valid */
 970
 971        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 972
 973        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 974                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 975
 976        if (cmd->scan_begin_src == TRIG_TIMER) {
 977                if (this_usbduxsub->high_speed) {
 978                        /*
 979                         * In high speed mode microframes are possible.
 980                         * However, during one microframe we can roughly
 981                         * sample one channel. Thus, the more channels
 982                         * are in the channel list the more time we need.
 983                         */
 984                        i = 1;
 985                        /* find a power of 2 for the number of channels */
 986                        while (i < (cmd->chanlist_len))
 987                                i = i * 2;
 988
 989                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 990                                                         1000000 / 8 * i);
 991                        /* now calc the real sampling rate with all the
 992                         * rounding errors */
 993                        tmp_timer =
 994                            ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 995                            125000;
 996                } else {
 997                        /* full speed */
 998                        /* 1kHz scans every USB frame */
 999                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1000                                                         1000000);
1001                        /*
1002                         * calc the real sampling rate with the rounding errors
1003                         */
1004                        tmp_timer = ((unsigned int)(cmd->scan_begin_arg /
1005                                                   1000000)) * 1000000;
1006                }
1007                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
1008                                                tmp_timer);
1009        }
1010
1011        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1012
1013        if (cmd->stop_src == TRIG_COUNT) {
1014                /* any count is allowed */
1015        } else {
1016                /* TRIG_NONE */
1017                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1018        }
1019
1020        if (err)
1021                return 3;
1022
1023        return 0;
1024}
1025
1026/*
1027 * creates the ADC command for the MAX1271
1028 * range is the range value from comedi
1029 */
1030static int8_t create_adc_command(unsigned int chan, int range)
1031{
1032        int8_t p = (range <= 1);
1033        int8_t r = ((range % 2) == 0);
1034        return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
1035}
1036
1037/* bulk transfers to usbdux */
1038
1039#define SENDADCOMMANDS            0
1040#define SENDDACOMMANDS            1
1041#define SENDDIOCONFIGCOMMAND      2
1042#define SENDDIOBITSCOMMAND        3
1043#define SENDSINGLEAD              4
1044#define READCOUNTERCOMMAND        5
1045#define WRITECOUNTERCOMMAND       6
1046#define SENDPWMON                 7
1047#define SENDPWMOFF                8
1048
1049static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
1050{
1051        int result, nsent;
1052
1053        this_usbduxsub->dux_commands[0] = cmd_type;
1054#ifdef NOISY_DUX_DEBUGBUG
1055        printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
1056               this_usbduxsub->comedidev->minor);
1057        for (result = 0; result < SIZEOFDUXBUFFER; result++)
1058                printk(" %02x", this_usbduxsub->dux_commands[result]);
1059        printk("\n");
1060#endif
1061        result = usb_bulk_msg(this_usbduxsub->usbdev,
1062                              usb_sndbulkpipe(this_usbduxsub->usbdev,
1063                                              COMMAND_OUT_EP),
1064                              this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
1065                              &nsent, BULK_TIMEOUT);
1066        if (result < 0)
1067                dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1068                        "could not transmit dux_command to the usb-device, "
1069                        "err=%d\n", this_usbduxsub->comedidev->minor, result);
1070
1071        return result;
1072}
1073
1074static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
1075{
1076        int result = (-EFAULT);
1077        int nrec;
1078        int i;
1079
1080        for (i = 0; i < RETRIES; i++) {
1081                result = usb_bulk_msg(this_usbduxsub->usbdev,
1082                                      usb_rcvbulkpipe(this_usbduxsub->usbdev,
1083                                                      COMMAND_IN_EP),
1084                                      this_usbduxsub->insn_buffer, SIZEINSNBUF,
1085                                      &nrec, BULK_TIMEOUT);
1086                if (result < 0) {
1087                        dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1088                                "insn: USB error %d while receiving DUX command"
1089                                "\n", this_usbduxsub->comedidev->minor, result);
1090                        return result;
1091                }
1092                if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command)
1093                        return result;
1094        }
1095        /* this is only reached if the data has been requested a couple of
1096         * times */
1097        dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
1098                "wrong data returned from firmware: want cmd %d, got cmd %d.\n",
1099                this_usbduxsub->comedidev->minor, command,
1100                le16_to_cpu(this_usbduxsub->insn_buffer[0]));
1101        return -EFAULT;
1102}
1103
1104static int usbdux_ai_inttrig(struct comedi_device *dev,
1105                             struct comedi_subdevice *s, unsigned int trignum)
1106{
1107        int ret;
1108        struct usbduxsub *this_usbduxsub = dev->private;
1109        if (!this_usbduxsub)
1110                return -EFAULT;
1111
1112        down(&this_usbduxsub->sem);
1113        if (!(this_usbduxsub->probed)) {
1114                up(&this_usbduxsub->sem);
1115                return -ENODEV;
1116        }
1117        dev_dbg(&this_usbduxsub->interface->dev,
1118                "comedi%d: usbdux_ai_inttrig\n", dev->minor);
1119
1120        if (trignum != 0) {
1121                dev_err(&this_usbduxsub->interface->dev,
1122                        "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
1123                        dev->minor);
1124                up(&this_usbduxsub->sem);
1125                return -EINVAL;
1126        }
1127        if (!(this_usbduxsub->ai_cmd_running)) {
1128                this_usbduxsub->ai_cmd_running = 1;
1129                ret = usbduxsub_submit_inurbs(this_usbduxsub);
1130                if (ret < 0) {
1131                        dev_err(&this_usbduxsub->interface->dev,
1132                                "comedi%d: usbdux_ai_inttrig: "
1133                                "urbSubmit: err=%d\n", dev->minor, ret);
1134                        this_usbduxsub->ai_cmd_running = 0;
1135                        up(&this_usbduxsub->sem);
1136                        return ret;
1137                }
1138                s->async->inttrig = NULL;
1139        } else {
1140                dev_err(&this_usbduxsub->interface->dev,
1141                        "comedi%d: ai_inttrig but acqu is already running\n",
1142                        dev->minor);
1143        }
1144        up(&this_usbduxsub->sem);
1145        return 1;
1146}
1147
1148static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1149{
1150        struct comedi_cmd *cmd = &s->async->cmd;
1151        unsigned int chan, range;
1152        int i, ret;
1153        struct usbduxsub *this_usbduxsub = dev->private;
1154        int result;
1155
1156        if (!this_usbduxsub)
1157                return -EFAULT;
1158
1159        dev_dbg(&this_usbduxsub->interface->dev,
1160                "comedi%d: usbdux_ai_cmd\n", dev->minor);
1161
1162        /* block other CPUs from starting an ai_cmd */
1163        down(&this_usbduxsub->sem);
1164
1165        if (!(this_usbduxsub->probed)) {
1166                up(&this_usbduxsub->sem);
1167                return -ENODEV;
1168        }
1169        if (this_usbduxsub->ai_cmd_running) {
1170                dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1171                        "ai_cmd not possible. Another ai_cmd is running.\n",
1172                        dev->minor);
1173                up(&this_usbduxsub->sem);
1174                return -EBUSY;
1175        }
1176        /* set current channel of the running acquisition to zero */
1177        s->async->cur_chan = 0;
1178
1179        this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
1180        for (i = 0; i < cmd->chanlist_len; ++i) {
1181                chan = CR_CHAN(cmd->chanlist[i]);
1182                range = CR_RANGE(cmd->chanlist[i]);
1183                if (i >= NUMCHANNELS) {
1184                        dev_err(&this_usbduxsub->interface->dev,
1185                                "comedi%d: channel list too long\n",
1186                                dev->minor);
1187                        break;
1188                }
1189                this_usbduxsub->dux_commands[i + 2] =
1190                    create_adc_command(chan, range);
1191        }
1192
1193        dev_dbg(&this_usbduxsub->interface->dev,
1194                "comedi %d: sending commands to the usb device: size=%u\n",
1195                dev->minor, NUMCHANNELS);
1196
1197        result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
1198        if (result < 0) {
1199                up(&this_usbduxsub->sem);
1200                return result;
1201        }
1202
1203        if (this_usbduxsub->high_speed) {
1204                /*
1205                 * every channel gets a time window of 125us. Thus, if we
1206                 * sample all 8 channels we need 1ms. If we sample only one
1207                 * channel we need only 125us
1208                 */
1209                this_usbduxsub->ai_interval = 1;
1210                /* find a power of 2 for the interval */
1211                while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
1212                        this_usbduxsub->ai_interval =
1213                            (this_usbduxsub->ai_interval) * 2;
1214                }
1215                this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
1216                                                          (this_usbduxsub->
1217                                                           ai_interval));
1218        } else {
1219                /* interval always 1ms */
1220                this_usbduxsub->ai_interval = 1;
1221                this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
1222        }
1223        if (this_usbduxsub->ai_timer < 1) {
1224                dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
1225                        "timer=%d, scan_begin_arg=%d. "
1226                        "Not properly tested by cmdtest?\n", dev->minor,
1227                        this_usbduxsub->ai_timer, cmd->scan_begin_arg);
1228                up(&this_usbduxsub->sem);
1229                return -EINVAL;
1230        }
1231        this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
1232
1233        if (cmd->stop_src == TRIG_COUNT) {
1234                /* data arrives as one packet */
1235                this_usbduxsub->ai_sample_count = cmd->stop_arg;
1236                this_usbduxsub->ai_continous = 0;
1237        } else {
1238                /* continous acquisition */
1239                this_usbduxsub->ai_continous = 1;
1240                this_usbduxsub->ai_sample_count = 0;
1241        }
1242
1243        if (cmd->start_src == TRIG_NOW) {
1244                /* enable this acquisition operation */
1245                this_usbduxsub->ai_cmd_running = 1;
1246                ret = usbduxsub_submit_inurbs(this_usbduxsub);
1247                if (ret < 0) {
1248                        this_usbduxsub->ai_cmd_running = 0;
1249                        /* fixme: unlink here?? */
1250                        up(&this_usbduxsub->sem);
1251                        return ret;
1252                }
1253                s->async->inttrig = NULL;
1254        } else {
1255                /* TRIG_INT */
1256                /* don't enable the acquision operation */
1257                /* wait for an internal signal */
1258                s->async->inttrig = usbdux_ai_inttrig;
1259        }
1260        up(&this_usbduxsub->sem);
1261        return 0;
1262}
1263
1264/* Mode 0 is used to get a single conversion on demand */
1265static int usbdux_ai_insn_read(struct comedi_device *dev,
1266                               struct comedi_subdevice *s,
1267                               struct comedi_insn *insn, unsigned int *data)
1268{
1269        int i;
1270        unsigned int one = 0;
1271        int chan, range;
1272        int err;
1273        struct usbduxsub *this_usbduxsub = dev->private;
1274
1275        if (!this_usbduxsub)
1276                return 0;
1277
1278        dev_dbg(&this_usbduxsub->interface->dev,
1279                "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1280                dev->minor, insn->n, insn->subdev);
1281
1282        down(&this_usbduxsub->sem);
1283        if (!(this_usbduxsub->probed)) {
1284                up(&this_usbduxsub->sem);
1285                return -ENODEV;
1286        }
1287        if (this_usbduxsub->ai_cmd_running) {
1288                dev_err(&this_usbduxsub->interface->dev,
1289                        "comedi%d: ai_insn_read not possible. "
1290                        "Async Command is running.\n", dev->minor);
1291                up(&this_usbduxsub->sem);
1292                return 0;
1293        }
1294
1295        /* sample one channel */
1296        chan = CR_CHAN(insn->chanspec);
1297        range = CR_RANGE(insn->chanspec);
1298        /* set command for the first channel */
1299        this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
1300
1301        /* adc commands */
1302        err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1303        if (err < 0) {
1304                up(&this_usbduxsub->sem);
1305                return err;
1306        }
1307
1308        for (i = 0; i < insn->n; i++) {
1309                err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1310                if (err < 0) {
1311                        up(&this_usbduxsub->sem);
1312                        return 0;
1313                }
1314                one = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
1315                if (CR_RANGE(insn->chanspec) <= 1)
1316                        one = one ^ 0x800;
1317
1318                data[i] = one;
1319        }
1320        up(&this_usbduxsub->sem);
1321        return i;
1322}
1323
1324/************************************/
1325/* analog out */
1326
1327static int usbdux_ao_insn_read(struct comedi_device *dev,
1328                               struct comedi_subdevice *s,
1329                               struct comedi_insn *insn, unsigned int *data)
1330{
1331        int i;
1332        int chan = CR_CHAN(insn->chanspec);
1333        struct usbduxsub *this_usbduxsub = dev->private;
1334
1335        if (!this_usbduxsub)
1336                return -EFAULT;
1337
1338        down(&this_usbduxsub->sem);
1339        if (!(this_usbduxsub->probed)) {
1340                up(&this_usbduxsub->sem);
1341                return -ENODEV;
1342        }
1343        for (i = 0; i < insn->n; i++)
1344                data[i] = this_usbduxsub->out_buffer[chan];
1345
1346        up(&this_usbduxsub->sem);
1347        return i;
1348}
1349
1350static int usbdux_ao_insn_write(struct comedi_device *dev,
1351                                struct comedi_subdevice *s,
1352                                struct comedi_insn *insn, unsigned int *data)
1353{
1354        int i, err;
1355        int chan = CR_CHAN(insn->chanspec);
1356        struct usbduxsub *this_usbduxsub = dev->private;
1357
1358        if (!this_usbduxsub)
1359                return -EFAULT;
1360
1361        dev_dbg(&this_usbduxsub->interface->dev,
1362                "comedi%d: ao_insn_write\n", dev->minor);
1363
1364        down(&this_usbduxsub->sem);
1365        if (!(this_usbduxsub->probed)) {
1366                up(&this_usbduxsub->sem);
1367                return -ENODEV;
1368        }
1369        if (this_usbduxsub->ao_cmd_running) {
1370                dev_err(&this_usbduxsub->interface->dev,
1371                        "comedi%d: ao_insn_write: "
1372                        "ERROR: asynchronous ao_cmd is running\n", dev->minor);
1373                up(&this_usbduxsub->sem);
1374                return 0;
1375        }
1376
1377        for (i = 0; i < insn->n; i++) {
1378                dev_dbg(&this_usbduxsub->interface->dev,
1379                        "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1380                        dev->minor, chan, i, data[i]);
1381
1382                /* number of channels: 1 */
1383                this_usbduxsub->dux_commands[1] = 1;
1384                /* one 16 bit value */
1385                *((int16_t *) (this_usbduxsub->dux_commands + 2)) =
1386                    cpu_to_le16(data[i]);
1387                this_usbduxsub->out_buffer[chan] = data[i];
1388                /* channel number */
1389                this_usbduxsub->dux_commands[4] = (chan << 6);
1390                err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
1391                if (err < 0) {
1392                        up(&this_usbduxsub->sem);
1393                        return err;
1394                }
1395        }
1396        up(&this_usbduxsub->sem);
1397
1398        return i;
1399}
1400
1401static int usbdux_ao_inttrig(struct comedi_device *dev,
1402                             struct comedi_subdevice *s, unsigned int trignum)
1403{
1404        int ret;
1405        struct usbduxsub *this_usbduxsub = dev->private;
1406
1407        if (!this_usbduxsub)
1408                return -EFAULT;
1409
1410        down(&this_usbduxsub->sem);
1411        if (!(this_usbduxsub->probed)) {
1412                up(&this_usbduxsub->sem);
1413                return -ENODEV;
1414        }
1415        if (trignum != 0) {
1416                dev_err(&this_usbduxsub->interface->dev,
1417                        "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1418                        dev->minor);
1419                up(&this_usbduxsub->sem);
1420                return -EINVAL;
1421        }
1422        if (!(this_usbduxsub->ao_cmd_running)) {
1423                this_usbduxsub->ao_cmd_running = 1;
1424                ret = usbduxsub_submit_outurbs(this_usbduxsub);
1425                if (ret < 0) {
1426                        dev_err(&this_usbduxsub->interface->dev,
1427                                "comedi%d: usbdux_ao_inttrig: submitURB: "
1428                                "err=%d\n", dev->minor, ret);
1429                        this_usbduxsub->ao_cmd_running = 0;
1430                        up(&this_usbduxsub->sem);
1431                        return ret;
1432                }
1433                s->async->inttrig = NULL;
1434        } else {
1435                dev_err(&this_usbduxsub->interface->dev,
1436                        "comedi%d: ao_inttrig but acqu is already running.\n",
1437                        dev->minor);
1438        }
1439        up(&this_usbduxsub->sem);
1440        return 1;
1441}
1442
1443static int usbdux_ao_cmdtest(struct comedi_device *dev,
1444                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
1445{
1446        struct usbduxsub *this_usbduxsub = dev->private;
1447        int err = 0;
1448        unsigned int flags;
1449
1450        if (!this_usbduxsub)
1451                return -EFAULT;
1452
1453        if (!(this_usbduxsub->probed))
1454                return -ENODEV;
1455
1456        /* Step 1 : check if triggers are trivially valid */
1457
1458        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1459
1460        if (0) {                /* (this_usbduxsub->high_speed) */
1461                /* the sampling rate is set by the coversion rate */
1462                flags = TRIG_FOLLOW;
1463        } else {
1464                /* start a new scan (output at once) with a timer */
1465                flags = TRIG_TIMER;
1466        }
1467        err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1468
1469        if (0) {                /* (this_usbduxsub->high_speed) */
1470                /*
1471                 * in usb-2.0 only one conversion it transmitted
1472                 * but with 8kHz/n
1473                 */
1474                flags = TRIG_TIMER;
1475        } else {
1476                /*
1477                 * all conversion events happen simultaneously with
1478                 * a rate of 1kHz/n
1479                 */
1480                flags = TRIG_NOW;
1481        }
1482        err |= cfc_check_trigger_src(&cmd->convert_src, flags);
1483
1484        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1485        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1486
1487        if (err)
1488                return 1;
1489
1490        /* Step 2a : make sure trigger sources are unique */
1491
1492        err |= cfc_check_trigger_is_unique(cmd->start_src);
1493        err |= cfc_check_trigger_is_unique(cmd->stop_src);
1494
1495        /* Step 2b : and mutually compatible */
1496
1497        if (err)
1498                return 2;
1499
1500        /* Step 3: check if arguments are trivially valid */
1501
1502        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1503
1504        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
1505                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1506
1507        if (cmd->scan_begin_src == TRIG_TIMER)
1508                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1509                                                 1000000);
1510
1511        /* not used now, is for later use */
1512        if (cmd->convert_src == TRIG_TIMER)
1513                err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
1514
1515        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1516
1517        if (cmd->stop_src == TRIG_COUNT) {
1518                /* any count is allowed */
1519        } else {
1520                /* TRIG_NONE */
1521                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1522        }
1523
1524        if (err)
1525                return 3;
1526
1527        return 0;
1528}
1529
1530static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1531{
1532        struct comedi_cmd *cmd = &s->async->cmd;
1533        unsigned int chan, gain;
1534        int i, ret;
1535        struct usbduxsub *this_usbduxsub = dev->private;
1536
1537        if (!this_usbduxsub)
1538                return -EFAULT;
1539
1540        down(&this_usbduxsub->sem);
1541        if (!(this_usbduxsub->probed)) {
1542                up(&this_usbduxsub->sem);
1543                return -ENODEV;
1544        }
1545        dev_dbg(&this_usbduxsub->interface->dev,
1546                "comedi%d: %s\n", dev->minor, __func__);
1547
1548        /* set current channel of the running acquisition to zero */
1549        s->async->cur_chan = 0;
1550        for (i = 0; i < cmd->chanlist_len; ++i) {
1551                chan = CR_CHAN(cmd->chanlist[i]);
1552                gain = CR_RANGE(cmd->chanlist[i]);
1553                if (i >= NUMOUTCHANNELS) {
1554                        dev_err(&this_usbduxsub->interface->dev,
1555                                "comedi%d: %s: channel list too long\n",
1556                                dev->minor, __func__);
1557                        break;
1558                }
1559                this_usbduxsub->dac_commands[i] = (chan << 6);
1560                dev_dbg(&this_usbduxsub->interface->dev,
1561                        "comedi%d: dac command for ch %d is %x\n",
1562                        dev->minor, i, this_usbduxsub->dac_commands[i]);
1563        }
1564
1565        /* we count in steps of 1ms (125us) */
1566        /* 125us mode not used yet */
1567        if (0) {                /* (this_usbduxsub->high_speed) */
1568                /* 125us */
1569                /* timing of the conversion itself: every 125 us */
1570                this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1571        } else {
1572                /* 1ms */
1573                /* timing of the scan: we get all channels at once */
1574                this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1575                dev_dbg(&this_usbduxsub->interface->dev,
1576                        "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
1577                        "convert_src=%d, convert_arg=%d\n", dev->minor,
1578                        cmd->scan_begin_src, cmd->scan_begin_arg,
1579                        cmd->convert_src, cmd->convert_arg);
1580                dev_dbg(&this_usbduxsub->interface->dev,
1581                        "comedi%d: ao_timer=%d (ms)\n",
1582                        dev->minor, this_usbduxsub->ao_timer);
1583                if (this_usbduxsub->ao_timer < 1) {
1584                        dev_err(&this_usbduxsub->interface->dev,
1585                                "comedi%d: usbdux: ao_timer=%d, "
1586                                "scan_begin_arg=%d. "
1587                                "Not properly tested by cmdtest?\n",
1588                                dev->minor, this_usbduxsub->ao_timer,
1589                                cmd->scan_begin_arg);
1590                        up(&this_usbduxsub->sem);
1591                        return -EINVAL;
1592                }
1593        }
1594        this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1595
1596        if (cmd->stop_src == TRIG_COUNT) {
1597                /* not continuous */
1598                /* counter */
1599                /* high speed also scans everything at once */
1600                if (0) {        /* (this_usbduxsub->high_speed) */
1601                        this_usbduxsub->ao_sample_count =
1602                            (cmd->stop_arg) * (cmd->scan_end_arg);
1603                } else {
1604                        /* there's no scan as the scan has been */
1605                        /* perf inside the FX2 */
1606                        /* data arrives as one packet */
1607                        this_usbduxsub->ao_sample_count = cmd->stop_arg;
1608                }
1609                this_usbduxsub->ao_continous = 0;
1610        } else {
1611                /* continous acquisition */
1612                this_usbduxsub->ao_continous = 1;
1613                this_usbduxsub->ao_sample_count = 0;
1614        }
1615
1616        if (cmd->start_src == TRIG_NOW) {
1617                /* enable this acquisition operation */
1618                this_usbduxsub->ao_cmd_running = 1;
1619                ret = usbduxsub_submit_outurbs(this_usbduxsub);
1620                if (ret < 0) {
1621                        this_usbduxsub->ao_cmd_running = 0;
1622                        /* fixme: unlink here?? */
1623                        up(&this_usbduxsub->sem);
1624                        return ret;
1625                }
1626                s->async->inttrig = NULL;
1627        } else {
1628                /* TRIG_INT */
1629                /* submit the urbs later */
1630                /* wait for an internal signal */
1631                s->async->inttrig = usbdux_ao_inttrig;
1632        }
1633
1634        up(&this_usbduxsub->sem);
1635        return 0;
1636}
1637
1638static int usbdux_dio_insn_config(struct comedi_device *dev,
1639                                  struct comedi_subdevice *s,
1640                                  struct comedi_insn *insn, unsigned int *data)
1641{
1642        int chan = CR_CHAN(insn->chanspec);
1643
1644        /* The input or output configuration of each digital line is
1645         * configured by a special insn_config instruction.  chanspec
1646         * contains the channel to be changed, and data[0] contains the
1647         * value COMEDI_INPUT or COMEDI_OUTPUT. */
1648
1649        switch (data[0]) {
1650        case INSN_CONFIG_DIO_OUTPUT:
1651                s->io_bits |= 1 << chan;        /* 1 means Out */
1652                break;
1653        case INSN_CONFIG_DIO_INPUT:
1654                s->io_bits &= ~(1 << chan);
1655                break;
1656        case INSN_CONFIG_DIO_QUERY:
1657                data[1] =
1658                    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1659                break;
1660        default:
1661                return -EINVAL;
1662                break;
1663        }
1664        /* we don't tell the firmware here as it would take 8 frames */
1665        /* to submit the information. We do it in the insn_bits. */
1666        return insn->n;
1667}
1668
1669static int usbdux_dio_insn_bits(struct comedi_device *dev,
1670                                struct comedi_subdevice *s,
1671                                struct comedi_insn *insn, unsigned int *data)
1672{
1673
1674        struct usbduxsub *this_usbduxsub = dev->private;
1675        int err;
1676
1677        if (!this_usbduxsub)
1678                return -EFAULT;
1679
1680        down(&this_usbduxsub->sem);
1681
1682        if (!(this_usbduxsub->probed)) {
1683                up(&this_usbduxsub->sem);
1684                return -ENODEV;
1685        }
1686
1687        /* The insn data is a mask in data[0] and the new data
1688         * in data[1], each channel cooresponding to a bit. */
1689        s->state &= ~data[0];
1690        s->state |= data[0] & data[1];
1691        this_usbduxsub->dux_commands[1] = s->io_bits;
1692        this_usbduxsub->dux_commands[2] = s->state;
1693
1694        /* This command also tells the firmware to return */
1695        /* the digital input lines */
1696        err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1697        if (err < 0) {
1698                up(&this_usbduxsub->sem);
1699                return err;
1700        }
1701        err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1702        if (err < 0) {
1703                up(&this_usbduxsub->sem);
1704                return err;
1705        }
1706
1707        data[1] = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
1708        up(&this_usbduxsub->sem);
1709        return insn->n;
1710}
1711
1712/* reads the 4 counters, only two are used just now */
1713static int usbdux_counter_read(struct comedi_device *dev,
1714                               struct comedi_subdevice *s,
1715                               struct comedi_insn *insn, unsigned int *data)
1716{
1717        struct usbduxsub *this_usbduxsub = dev->private;
1718        int chan = insn->chanspec;
1719        int err;
1720
1721        if (!this_usbduxsub)
1722                return -EFAULT;
1723
1724        down(&this_usbduxsub->sem);
1725
1726        if (!(this_usbduxsub->probed)) {
1727                up(&this_usbduxsub->sem);
1728                return -ENODEV;
1729        }
1730
1731        err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1732        if (err < 0) {
1733                up(&this_usbduxsub->sem);
1734                return err;
1735        }
1736
1737        err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1738        if (err < 0) {
1739                up(&this_usbduxsub->sem);
1740                return err;
1741        }
1742
1743        data[0] = le16_to_cpu(this_usbduxsub->insn_buffer[chan + 1]);
1744        up(&this_usbduxsub->sem);
1745        return 1;
1746}
1747
1748static int usbdux_counter_write(struct comedi_device *dev,
1749                                struct comedi_subdevice *s,
1750                                struct comedi_insn *insn, unsigned int *data)
1751{
1752        struct usbduxsub *this_usbduxsub = dev->private;
1753        int err;
1754
1755        if (!this_usbduxsub)
1756                return -EFAULT;
1757
1758        down(&this_usbduxsub->sem);
1759
1760        if (!(this_usbduxsub->probed)) {
1761                up(&this_usbduxsub->sem);
1762                return -ENODEV;
1763        }
1764
1765        this_usbduxsub->dux_commands[1] = insn->chanspec;
1766        *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
1767
1768        err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
1769        if (err < 0) {
1770                up(&this_usbduxsub->sem);
1771                return err;
1772        }
1773
1774        up(&this_usbduxsub->sem);
1775
1776        return 1;
1777}
1778
1779static int usbdux_counter_config(struct comedi_device *dev,
1780                                 struct comedi_subdevice *s,
1781                                 struct comedi_insn *insn, unsigned int *data)
1782{
1783        /* nothing to do so far */
1784        return 2;
1785}
1786
1787/***********************************/
1788/* PWM */
1789
1790static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp)
1791{
1792        int err = 0;
1793
1794        if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) {
1795                if (usbduxsub_tmp->urb_pwm)
1796                        usb_kill_urb(usbduxsub_tmp->urb_pwm);
1797                dev_dbg(&usbduxsub_tmp->interface->dev,
1798                        "comedi: unlinked PwmURB: res=%d\n", err);
1799        }
1800        return err;
1801}
1802
1803/* This cancels a running acquisition operation
1804 * in any context.
1805 */
1806static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
1807{
1808        int ret = 0;
1809
1810        if (!this_usbduxsub)
1811                return -EFAULT;
1812
1813        dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
1814        if (do_unlink)
1815                ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub);
1816
1817        this_usbduxsub->pwm_cmd_running = 0;
1818
1819        return ret;
1820}
1821
1822/* force unlink - is called by comedi */
1823static int usbdux_pwm_cancel(struct comedi_device *dev,
1824                             struct comedi_subdevice *s)
1825{
1826        struct usbduxsub *this_usbduxsub = dev->private;
1827        int res = 0;
1828
1829        /* unlink only if it is really running */
1830        res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
1831
1832        dev_dbg(&this_usbduxsub->interface->dev,
1833                "comedi %d: sending pwm off command to the usb device.\n",
1834                dev->minor);
1835
1836        return send_dux_commands(this_usbduxsub, SENDPWMOFF);
1837}
1838
1839static void usbduxsub_pwm_irq(struct urb *urb)
1840{
1841        int ret;
1842        struct usbduxsub *this_usbduxsub;
1843        struct comedi_device *this_comedidev;
1844        struct comedi_subdevice *s;
1845
1846        /* printk(KERN_DEBUG "PWM: IRQ\n"); */
1847
1848        /* the context variable points to the subdevice */
1849        this_comedidev = urb->context;
1850        /* the private structure of the subdevice is struct usbduxsub */
1851        this_usbduxsub = this_comedidev->private;
1852
1853        s = &this_comedidev->subdevices[SUBDEV_DA];
1854
1855        switch (urb->status) {
1856        case 0:
1857                /* success */
1858                break;
1859
1860        case -ECONNRESET:
1861        case -ENOENT:
1862        case -ESHUTDOWN:
1863        case -ECONNABORTED:
1864                /*
1865                 * after an unlink command, unplug, ... etc
1866                 * no unlink needed here. Already shutting down.
1867                 */
1868                if (this_usbduxsub->pwm_cmd_running)
1869                        usbdux_pwm_stop(this_usbduxsub, 0);
1870
1871                return;
1872
1873        default:
1874                /* a real error */
1875                if (this_usbduxsub->pwm_cmd_running) {
1876                        dev_err(&this_usbduxsub->interface->dev,
1877                                "comedi_: Non-zero urb status received in "
1878                                "pwm intr context: %d\n", urb->status);
1879                        usbdux_pwm_stop(this_usbduxsub, 0);
1880                }
1881                return;
1882        }
1883
1884        /* are we actually running? */
1885        if (!(this_usbduxsub->pwm_cmd_running))
1886                return;
1887
1888        urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf;
1889        urb->dev = this_usbduxsub->usbdev;
1890        urb->status = 0;
1891        if (this_usbduxsub->pwm_cmd_running) {
1892                ret = usb_submit_urb(urb, GFP_ATOMIC);
1893                if (ret < 0) {
1894                        dev_err(&this_usbduxsub->interface->dev,
1895                                "comedi_: pwm urb resubm failed in int-cont. "
1896                                "ret=%d", ret);
1897                        if (ret == EL2NSYNC)
1898                                dev_err(&this_usbduxsub->interface->dev,
1899                                        "buggy USB host controller or bug in "
1900                                        "IRQ handling!\n");
1901
1902                        /* don't do an unlink here */
1903                        usbdux_pwm_stop(this_usbduxsub, 0);
1904                }
1905        }
1906}
1907
1908static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub)
1909{
1910        int err_flag;
1911
1912        if (!usbduxsub)
1913                return -EFAULT;
1914
1915        dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
1916
1917        /* in case of a resubmission after an unlink... */
1918        usb_fill_bulk_urb(usbduxsub->urb_pwm,
1919                          usbduxsub->usbdev,
1920                          usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
1921                          usbduxsub->urb_pwm->transfer_buffer,
1922                          usbduxsub->size_pwm_buf, usbduxsub_pwm_irq,
1923                          usbduxsub->comedidev);
1924
1925        err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC);
1926        if (err_flag) {
1927                dev_err(&usbduxsub->interface->dev,
1928                        "comedi_: usbdux: pwm: usb_submit_urb error %d\n",
1929                        err_flag);
1930                return err_flag;
1931        }
1932        return 0;
1933}
1934
1935static int usbdux_pwm_period(struct comedi_device *dev,
1936                             struct comedi_subdevice *s, unsigned int period)
1937{
1938        struct usbduxsub *this_usbduxsub = dev->private;
1939        int fx2delay = 255;
1940
1941        if (period < MIN_PWM_PERIOD) {
1942                dev_err(&this_usbduxsub->interface->dev,
1943                        "comedi%d: illegal period setting for pwm.\n",
1944                        dev->minor);
1945                return -EAGAIN;
1946        } else {
1947                fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
1948                if (fx2delay > 255) {
1949                        dev_err(&this_usbduxsub->interface->dev,
1950                                "comedi%d: period %d for pwm is too low.\n",
1951                                dev->minor, period);
1952                        return -EAGAIN;
1953                }
1954        }
1955        this_usbduxsub->pwn_delay = fx2delay;
1956        this_usbduxsub->pwm_period = period;
1957        dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
1958                __func__, period, fx2delay);
1959        return 0;
1960}
1961
1962/* is called from insn so there's no need to do all the sanity checks */
1963static int usbdux_pwm_start(struct comedi_device *dev,
1964                            struct comedi_subdevice *s)
1965{
1966        int ret, i;
1967        struct usbduxsub *this_usbduxsub = dev->private;
1968
1969        dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
1970                dev->minor, __func__);
1971
1972        if (this_usbduxsub->pwm_cmd_running) {
1973                /* already running */
1974                return 0;
1975        }
1976
1977        this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay);
1978        ret = send_dux_commands(this_usbduxsub, SENDPWMON);
1979        if (ret < 0)
1980                return ret;
1981
1982        /* initialise the buffer */
1983        for (i = 0; i < this_usbduxsub->size_pwm_buf; i++)
1984                ((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0;
1985
1986        this_usbduxsub->pwm_cmd_running = 1;
1987        ret = usbduxsub_submit_pwm_urbs(this_usbduxsub);
1988        if (ret < 0) {
1989                this_usbduxsub->pwm_cmd_running = 0;
1990                return ret;
1991        }
1992        return 0;
1993}
1994
1995/* generates the bit pattern for PWM with the optional sign bit */
1996static int usbdux_pwm_pattern(struct comedi_device *dev,
1997                              struct comedi_subdevice *s, int channel,
1998                              unsigned int value, unsigned int sign)
1999{
2000        struct usbduxsub *this_usbduxsub = dev->private;
2001        int i, szbuf;
2002        char *p_buf;
2003        char pwm_mask;
2004        char sgn_mask;
2005        char c;
2006
2007        if (!this_usbduxsub)
2008                return -EFAULT;
2009
2010        /* this is the DIO bit which carries the PWM data */
2011        pwm_mask = (1 << channel);
2012        /* this is the DIO bit which carries the optional direction bit */
2013        sgn_mask = (16 << channel);
2014        /* this is the buffer which will be filled with the with bit */
2015        /* pattern for one period */
2016        szbuf = this_usbduxsub->size_pwm_buf;
2017        p_buf = (char *)(this_usbduxsub->urb_pwm->transfer_buffer);
2018        for (i = 0; i < szbuf; i++) {
2019                c = *p_buf;
2020                /* reset bits */
2021                c = c & (~pwm_mask);
2022                /* set the bit as long as the index is lower than the value */
2023                if (i < value)
2024                        c = c | pwm_mask;
2025                /* set the optional sign bit for a relay */
2026                if (!sign) {
2027                        /* positive value */
2028                        c = c & (~sgn_mask);
2029                } else {
2030                        /* negative value */
2031                        c = c | sgn_mask;
2032                }
2033                *(p_buf++) = c;
2034        }
2035        return 1;
2036}
2037
2038static int usbdux_pwm_write(struct comedi_device *dev,
2039                            struct comedi_subdevice *s,
2040                            struct comedi_insn *insn, unsigned int *data)
2041{
2042        struct usbduxsub *this_usbduxsub = dev->private;
2043
2044        if (!this_usbduxsub)
2045                return -EFAULT;
2046
2047        if ((insn->n) != 1) {
2048                /*
2049                 * doesn't make sense to have more than one value here because
2050                 * it would just overwrite the PWM buffer a couple of times
2051                 */
2052                return -EINVAL;
2053        }
2054
2055        /*
2056         * the sign is set via a special INSN only, this gives us 8 bits for
2057         * normal operation
2058         * relay sign 0 by default
2059         */
2060        return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
2061}
2062
2063static int usbdux_pwm_read(struct comedi_device *x1,
2064                           struct comedi_subdevice *x2, struct comedi_insn *x3,
2065                           unsigned int *x4)
2066{
2067        /* not needed */
2068        return -EINVAL;
2069};
2070
2071/* switches on/off PWM */
2072static int usbdux_pwm_config(struct comedi_device *dev,
2073                             struct comedi_subdevice *s,
2074                             struct comedi_insn *insn, unsigned int *data)
2075{
2076        struct usbduxsub *this_usbduxsub = dev->private;
2077        switch (data[0]) {
2078        case INSN_CONFIG_ARM:
2079                /* switch it on */
2080                dev_dbg(&this_usbduxsub->interface->dev,
2081                        "comedi%d: %s: pwm on\n", dev->minor, __func__);
2082                /*
2083                 * if not zero the PWM is limited to a certain time which is
2084                 * not supported here
2085                 */
2086                if (data[1] != 0)
2087                        return -EINVAL;
2088                return usbdux_pwm_start(dev, s);
2089        case INSN_CONFIG_DISARM:
2090                dev_dbg(&this_usbduxsub->interface->dev,
2091                        "comedi%d: %s: pwm off\n", dev->minor, __func__);
2092                return usbdux_pwm_cancel(dev, s);
2093        case INSN_CONFIG_GET_PWM_STATUS:
2094                /*
2095                 * to check if the USB transmission has failed or in case PWM
2096                 * was limited to n cycles to check if it has terminated
2097                 */
2098                data[1] = this_usbduxsub->pwm_cmd_running;
2099                return 0;
2100        case INSN_CONFIG_PWM_SET_PERIOD:
2101                dev_dbg(&this_usbduxsub->interface->dev,
2102                        "comedi%d: %s: setting period\n", dev->minor, __func__);
2103                return usbdux_pwm_period(dev, s, data[1]);
2104        case INSN_CONFIG_PWM_GET_PERIOD:
2105                data[1] = this_usbduxsub->pwm_period;
2106                return 0;
2107        case INSN_CONFIG_PWM_SET_H_BRIDGE:
2108                /* value in the first byte and the sign in the second for a
2109                   relay */
2110                return usbdux_pwm_pattern(dev, s,
2111                                          /* the channel number */
2112                                          CR_CHAN(insn->chanspec),
2113                                          /* actual PWM data */
2114                                          data[1],
2115                                          /* just a sign */
2116                                          (data[2] != 0));
2117        case INSN_CONFIG_PWM_GET_H_BRIDGE:
2118                /* values are not kept in this driver, nothing to return here */
2119                return -EINVAL;
2120        }
2121        return -EINVAL;
2122}
2123
2124/* end of PWM */
2125/*****************************************************************/
2126
2127static void tidy_up(struct usbduxsub *usbduxsub_tmp)
2128{
2129        int i;
2130
2131        if (!usbduxsub_tmp)
2132                return;
2133        dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
2134
2135        /* shows the usb subsystem that the driver is down */
2136        if (usbduxsub_tmp->interface)
2137                usb_set_intfdata(usbduxsub_tmp->interface, NULL);
2138
2139        usbduxsub_tmp->probed = 0;
2140
2141        if (usbduxsub_tmp->urb_in) {
2142                if (usbduxsub_tmp->ai_cmd_running) {
2143                        usbduxsub_tmp->ai_cmd_running = 0;
2144                        usbduxsub_unlink_inurbs(usbduxsub_tmp);
2145                }
2146                for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) {
2147                        kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer);
2148                        usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL;
2149                        usb_kill_urb(usbduxsub_tmp->urb_in[i]);
2150                        usb_free_urb(usbduxsub_tmp->urb_in[i]);
2151                        usbduxsub_tmp->urb_in[i] = NULL;
2152                }
2153                kfree(usbduxsub_tmp->urb_in);
2154                usbduxsub_tmp->urb_in = NULL;
2155        }
2156        if (usbduxsub_tmp->urb_out) {
2157                if (usbduxsub_tmp->ao_cmd_running) {
2158                        usbduxsub_tmp->ao_cmd_running = 0;
2159                        usbduxsub_unlink_outurbs(usbduxsub_tmp);
2160                }
2161                for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) {
2162                        kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer);
2163                        usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL;
2164                        if (usbduxsub_tmp->urb_out[i]) {
2165                                usb_kill_urb(usbduxsub_tmp->urb_out[i]);
2166                                usb_free_urb(usbduxsub_tmp->urb_out[i]);
2167                                usbduxsub_tmp->urb_out[i] = NULL;
2168                        }
2169                }
2170                kfree(usbduxsub_tmp->urb_out);
2171                usbduxsub_tmp->urb_out = NULL;
2172        }
2173        if (usbduxsub_tmp->urb_pwm) {
2174                if (usbduxsub_tmp->pwm_cmd_running) {
2175                        usbduxsub_tmp->pwm_cmd_running = 0;
2176                        usbduxsub_unlink_pwm_urbs(usbduxsub_tmp);
2177                }
2178                kfree(usbduxsub_tmp->urb_pwm->transfer_buffer);
2179                usbduxsub_tmp->urb_pwm->transfer_buffer = NULL;
2180                usb_kill_urb(usbduxsub_tmp->urb_pwm);
2181                usb_free_urb(usbduxsub_tmp->urb_pwm);
2182                usbduxsub_tmp->urb_pwm = NULL;
2183        }
2184        kfree(usbduxsub_tmp->in_buffer);
2185        usbduxsub_tmp->in_buffer = NULL;
2186        kfree(usbduxsub_tmp->insn_buffer);
2187        usbduxsub_tmp->insn_buffer = NULL;
2188        kfree(usbduxsub_tmp->out_buffer);
2189        usbduxsub_tmp->out_buffer = NULL;
2190        kfree(usbduxsub_tmp->dac_commands);
2191        usbduxsub_tmp->dac_commands = NULL;
2192        kfree(usbduxsub_tmp->dux_commands);
2193        usbduxsub_tmp->dux_commands = NULL;
2194        usbduxsub_tmp->ai_cmd_running = 0;
2195        usbduxsub_tmp->ao_cmd_running = 0;
2196        usbduxsub_tmp->pwm_cmd_running = 0;
2197}
2198
2199static int usbdux_attach_common(struct comedi_device *dev,
2200                                struct usbduxsub *udev)
2201{
2202        int ret;
2203        struct comedi_subdevice *s = NULL;
2204        int n_subdevs;
2205
2206        down(&udev->sem);
2207        /* pointer back to the corresponding comedi device */
2208        udev->comedidev = dev;
2209
2210        /* set number of subdevices */
2211        if (udev->high_speed) {
2212                /* with pwm */
2213                n_subdevs = 5;
2214        } else {
2215                /* without pwm */
2216                n_subdevs = 4;
2217        }
2218
2219        ret = comedi_alloc_subdevices(dev, n_subdevs);
2220        if (ret) {
2221                up(&udev->sem);
2222                return ret;
2223        }
2224
2225        /* private structure is also simply the usb-structure */
2226        dev->private = udev;
2227
2228        /* the first subdevice is the A/D converter */
2229        s = &dev->subdevices[SUBDEV_AD];
2230        /* the URBs get the comedi subdevice */
2231        /* which is responsible for reading */
2232        /* this is the subdevice which reads data */
2233        dev->read_subdev = s;
2234        /* the subdevice receives as private structure the */
2235        /* usb-structure */
2236        s->private = NULL;
2237        /* analog input */
2238        s->type = COMEDI_SUBD_AI;
2239        /* readable and ref is to ground */
2240        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
2241        /* 8 channels */
2242        s->n_chan = 8;
2243        /* length of the channellist */
2244        s->len_chanlist = 8;
2245        /* callback functions */
2246        s->insn_read = usbdux_ai_insn_read;
2247        s->do_cmdtest = usbdux_ai_cmdtest;
2248        s->do_cmd = usbdux_ai_cmd;
2249        s->cancel = usbdux_ai_cancel;
2250        /* max value from the A/D converter (12bit) */
2251        s->maxdata = 0xfff;
2252        /* range table to convert to physical units */
2253        s->range_table = (&range_usbdux_ai_range);
2254
2255        /* analog out */
2256        s = &dev->subdevices[SUBDEV_DA];
2257        /* analog out */
2258        s->type = COMEDI_SUBD_AO;
2259        /* backward pointer */
2260        dev->write_subdev = s;
2261        /* the subdevice receives as private structure the */
2262        /* usb-structure */
2263        s->private = NULL;
2264        /* are writable */
2265        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
2266        /* 4 channels */
2267        s->n_chan = 4;
2268        /* length of the channellist */
2269        s->len_chanlist = 4;
2270        /* 12 bit resolution */
2271        s->maxdata = 0x0fff;
2272        /* bipolar range */
2273        s->range_table = (&range_usbdux_ao_range);
2274        /* callback */
2275        s->do_cmdtest = usbdux_ao_cmdtest;
2276        s->do_cmd = usbdux_ao_cmd;
2277        s->cancel = usbdux_ao_cancel;
2278        s->insn_read = usbdux_ao_insn_read;
2279        s->insn_write = usbdux_ao_insn_write;
2280
2281        /* digital I/O */
2282        s = &dev->subdevices[SUBDEV_DIO];
2283        s->type = COMEDI_SUBD_DIO;
2284        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2285        s->n_chan = 8;
2286        s->maxdata = 1;
2287        s->range_table = (&range_digital);
2288        s->insn_bits = usbdux_dio_insn_bits;
2289        s->insn_config = usbdux_dio_insn_config;
2290        /* we don't use it */
2291        s->private = NULL;
2292
2293        /* counter */
2294        s = &dev->subdevices[SUBDEV_COUNTER];
2295        s->type = COMEDI_SUBD_COUNTER;
2296        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2297        s->n_chan = 4;
2298        s->maxdata = 0xFFFF;
2299        s->insn_read = usbdux_counter_read;
2300        s->insn_write = usbdux_counter_write;
2301        s->insn_config = usbdux_counter_config;
2302
2303        if (udev->high_speed) {
2304                /* timer / pwm */
2305                s = &dev->subdevices[SUBDEV_PWM];
2306                s->type = COMEDI_SUBD_PWM;
2307                s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
2308                s->n_chan = 8;
2309                /* this defines the max duty cycle resolution */
2310                s->maxdata = udev->size_pwm_buf;
2311                s->insn_write = usbdux_pwm_write;
2312                s->insn_read = usbdux_pwm_read;
2313                s->insn_config = usbdux_pwm_config;
2314                usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
2315        }
2316        /* finally decide that it's attached */
2317        udev->attached = 1;
2318
2319        up(&udev->sem);
2320
2321        dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
2322                 dev->minor);
2323
2324        return 0;
2325}
2326
2327static int usbdux_auto_attach(struct comedi_device *dev,
2328                              unsigned long context_unused)
2329{
2330        struct usb_interface *uinterf = comedi_to_usb_interface(dev);
2331        int ret;
2332        struct usbduxsub *this_usbduxsub;
2333
2334        dev->private = NULL;
2335
2336        down(&start_stop_sem);
2337        this_usbduxsub = usb_get_intfdata(uinterf);
2338        if (!this_usbduxsub || !this_usbduxsub->probed) {
2339                dev_err(dev->class_dev,
2340                        "usbdux: error: auto_attach failed, not connected\n");
2341                ret = -ENODEV;
2342        } else if (this_usbduxsub->attached) {
2343                dev_err(dev->class_dev,
2344                        "error: auto_attach failed, already attached\n");
2345                ret = -ENODEV;
2346        } else
2347                ret = usbdux_attach_common(dev, this_usbduxsub);
2348        up(&start_stop_sem);
2349        return ret;
2350}
2351
2352static void usbdux_detach(struct comedi_device *dev)
2353{
2354        struct usbduxsub *usb = dev->private;
2355
2356        if (usb) {
2357                down(&usb->sem);
2358                dev->private = NULL;
2359                usb->attached = 0;
2360                usb->comedidev = NULL;
2361                up(&usb->sem);
2362        }
2363}
2364
2365static struct comedi_driver usbdux_driver = {
2366        .driver_name    = "usbdux",
2367        .module         = THIS_MODULE,
2368        .auto_attach    = usbdux_auto_attach,
2369        .detach         = usbdux_detach,
2370};
2371
2372static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
2373                                                     void *context)
2374{
2375        struct usbduxsub *usbduxsub_tmp = context;
2376        struct usb_interface *uinterf = usbduxsub_tmp->interface;
2377        int ret;
2378
2379        if (fw == NULL) {
2380                dev_err(&uinterf->dev,
2381                        "Firmware complete handler without firmware!\n");
2382                return;
2383        }
2384
2385        /*
2386         * we need to upload the firmware here because fw will be
2387         * freed once we've left this function
2388         */
2389        ret = firmware_upload(usbduxsub_tmp, fw->data, fw->size);
2390
2391        if (ret) {
2392                dev_err(&uinterf->dev,
2393                        "Could not upload firmware (err=%d)\n", ret);
2394                goto out;
2395        }
2396        comedi_usb_auto_config(uinterf, &usbdux_driver, 0);
2397 out:
2398        release_firmware(fw);
2399}
2400
2401static int usbdux_usb_probe(struct usb_interface *uinterf,
2402                            const struct usb_device_id *id)
2403{
2404        struct usb_device *udev = interface_to_usbdev(uinterf);
2405        struct device *dev = &uinterf->dev;
2406        int i;
2407        int index;
2408        int ret;
2409
2410        dev_dbg(dev, "comedi_: usbdux_: "
2411                "finding a free structure for the usb-device\n");
2412
2413        down(&start_stop_sem);
2414        /* look for a free place in the usbdux array */
2415        index = -1;
2416        for (i = 0; i < NUMUSBDUX; i++) {
2417                if (!(usbduxsub[i].probed)) {
2418                        index = i;
2419                        break;
2420                }
2421        }
2422
2423        /* no more space */
2424        if (index == -1) {
2425                dev_err(dev, "Too many usbdux-devices connected.\n");
2426                up(&start_stop_sem);
2427                return -EMFILE;
2428        }
2429        dev_dbg(dev, "comedi_: usbdux: "
2430                "usbduxsub[%d] is ready to connect to comedi.\n", index);
2431
2432        sema_init(&(usbduxsub[index].sem), 1);
2433        /* save a pointer to the usb device */
2434        usbduxsub[index].usbdev = udev;
2435
2436        /* 2.6: save the interface itself */
2437        usbduxsub[index].interface = uinterf;
2438        /* get the interface number from the interface */
2439        usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
2440        /* hand the private data over to the usb subsystem */
2441        /* will be needed for disconnect */
2442        usb_set_intfdata(uinterf, &(usbduxsub[index]));
2443
2444        dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
2445
2446        /* test if it is high speed (USB 2.0) */
2447        usbduxsub[index].high_speed =
2448            (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
2449
2450        /* create space for the commands of the DA converter */
2451        usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
2452        if (!usbduxsub[index].dac_commands) {
2453                tidy_up(&(usbduxsub[index]));
2454                up(&start_stop_sem);
2455                return -ENOMEM;
2456        }
2457        /* create space for the commands going to the usb device */
2458        usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
2459        if (!usbduxsub[index].dux_commands) {
2460                tidy_up(&(usbduxsub[index]));
2461                up(&start_stop_sem);
2462                return -ENOMEM;
2463        }
2464        /* create space for the in buffer and set it to zero */
2465        usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
2466        if (!(usbduxsub[index].in_buffer)) {
2467                tidy_up(&(usbduxsub[index]));
2468                up(&start_stop_sem);
2469                return -ENOMEM;
2470        }
2471        /* create space of the instruction buffer */
2472        usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
2473        if (!(usbduxsub[index].insn_buffer)) {
2474                tidy_up(&(usbduxsub[index]));
2475                up(&start_stop_sem);
2476                return -ENOMEM;
2477        }
2478        /* create space for the outbuffer */
2479        usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
2480        if (!(usbduxsub[index].out_buffer)) {
2481                tidy_up(&(usbduxsub[index]));
2482                up(&start_stop_sem);
2483                return -ENOMEM;
2484        }
2485        /* setting to alternate setting 3: enabling iso ep and bulk ep. */
2486        i = usb_set_interface(usbduxsub[index].usbdev,
2487                              usbduxsub[index].ifnum, 3);
2488        if (i < 0) {
2489                dev_err(dev, "comedi_: usbdux%d: "
2490                        "could not set alternate setting 3 in high speed.\n",
2491                        index);
2492                tidy_up(&(usbduxsub[index]));
2493                up(&start_stop_sem);
2494                return -ENODEV;
2495        }
2496        if (usbduxsub[index].high_speed)
2497                usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH;
2498        else
2499                usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL;
2500
2501        usbduxsub[index].urb_in =
2502                kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *),
2503                        GFP_KERNEL);
2504        if (!(usbduxsub[index].urb_in)) {
2505                tidy_up(&(usbduxsub[index]));
2506                up(&start_stop_sem);
2507                return -ENOMEM;
2508        }
2509        for (i = 0; i < usbduxsub[index].num_in_buffers; i++) {
2510                /* one frame: 1ms */
2511                usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL);
2512                if (usbduxsub[index].urb_in[i] == NULL) {
2513                        dev_err(dev, "comedi_: usbdux%d: "
2514                                "Could not alloc. urb(%d)\n", index, i);
2515                        tidy_up(&(usbduxsub[index]));
2516                        up(&start_stop_sem);
2517                        return -ENOMEM;
2518                }
2519                usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev;
2520                /* will be filled later with a pointer to the comedi-device */
2521                /* and ONLY then the urb should be submitted */
2522                usbduxsub[index].urb_in[i]->context = NULL;
2523                usbduxsub[index].urb_in[i]->pipe =
2524                    usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
2525                usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP;
2526                usbduxsub[index].urb_in[i]->transfer_buffer =
2527                    kzalloc(SIZEINBUF, GFP_KERNEL);
2528                if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) {
2529                        tidy_up(&(usbduxsub[index]));
2530                        up(&start_stop_sem);
2531                        return -ENOMEM;
2532                }
2533                usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq;
2534                usbduxsub[index].urb_in[i]->number_of_packets = 1;
2535                usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF;
2536                usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0;
2537                usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF;
2538        }
2539
2540        /* out */
2541        if (usbduxsub[index].high_speed)
2542                usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH;
2543        else
2544                usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL;
2545
2546        usbduxsub[index].urb_out =
2547                kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *),
2548                        GFP_KERNEL);
2549        if (!(usbduxsub[index].urb_out)) {
2550                tidy_up(&(usbduxsub[index]));
2551                up(&start_stop_sem);
2552                return -ENOMEM;
2553        }
2554        for (i = 0; i < usbduxsub[index].num_out_buffers; i++) {
2555                /* one frame: 1ms */
2556                usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL);
2557                if (usbduxsub[index].urb_out[i] == NULL) {
2558                        dev_err(dev, "comedi_: usbdux%d: "
2559                                "Could not alloc. urb(%d)\n", index, i);
2560                        tidy_up(&(usbduxsub[index]));
2561                        up(&start_stop_sem);
2562                        return -ENOMEM;
2563                }
2564                usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev;
2565                /* will be filled later with a pointer to the comedi-device */
2566                /* and ONLY then the urb should be submitted */
2567                usbduxsub[index].urb_out[i]->context = NULL;
2568                usbduxsub[index].urb_out[i]->pipe =
2569                    usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
2570                usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP;
2571                usbduxsub[index].urb_out[i]->transfer_buffer =
2572                    kzalloc(SIZEOUTBUF, GFP_KERNEL);
2573                if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) {
2574                        tidy_up(&(usbduxsub[index]));
2575                        up(&start_stop_sem);
2576                        return -ENOMEM;
2577                }
2578                usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq;
2579                usbduxsub[index].urb_out[i]->number_of_packets = 1;
2580                usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF;
2581                usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0;
2582                usbduxsub[index].urb_out[i]->iso_frame_desc[0].length =
2583                    SIZEOUTBUF;
2584                if (usbduxsub[index].high_speed) {
2585                        /* uframes */
2586                        usbduxsub[index].urb_out[i]->interval = 8;
2587                } else {
2588                        /* frames */
2589                        usbduxsub[index].urb_out[i]->interval = 1;
2590                }
2591        }
2592
2593        /* pwm */
2594        if (usbduxsub[index].high_speed) {
2595                /* max bulk ep size in high speed */
2596                usbduxsub[index].size_pwm_buf = 512;
2597                usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL);
2598                if (usbduxsub[index].urb_pwm == NULL) {
2599                        dev_err(dev, "comedi_: usbdux%d: "
2600                                "Could not alloc. pwm urb\n", index);
2601                        tidy_up(&(usbduxsub[index]));
2602                        up(&start_stop_sem);
2603                        return -ENOMEM;
2604                }
2605                usbduxsub[index].urb_pwm->transfer_buffer =
2606                    kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL);
2607                if (!(usbduxsub[index].urb_pwm->transfer_buffer)) {
2608                        tidy_up(&(usbduxsub[index]));
2609                        up(&start_stop_sem);
2610                        return -ENOMEM;
2611                }
2612        } else {
2613                usbduxsub[index].urb_pwm = NULL;
2614                usbduxsub[index].size_pwm_buf = 0;
2615        }
2616
2617        usbduxsub[index].ai_cmd_running = 0;
2618        usbduxsub[index].ao_cmd_running = 0;
2619        usbduxsub[index].pwm_cmd_running = 0;
2620
2621        /* we've reached the bottom of the function */
2622        usbduxsub[index].probed = 1;
2623        up(&start_stop_sem);
2624
2625        ret = request_firmware_nowait(THIS_MODULE,
2626                                      FW_ACTION_HOTPLUG,
2627                                      FIRMWARE,
2628                                      &udev->dev,
2629                                      GFP_KERNEL,
2630                                      usbduxsub + index,
2631                                      usbdux_firmware_request_complete_handler);
2632
2633        if (ret) {
2634                dev_err(dev, "Could not load firmware (err=%d)\n", ret);
2635                return ret;
2636        }
2637
2638        dev_info(dev, "comedi_: usbdux%d "
2639                 "has been successfully initialised.\n", index);
2640        /* success */
2641        return 0;
2642}
2643
2644static void usbdux_usb_disconnect(struct usb_interface *intf)
2645{
2646        struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
2647        struct usb_device *udev = interface_to_usbdev(intf);
2648
2649        if (!usbduxsub_tmp) {
2650                dev_err(&intf->dev,
2651                        "comedi_: disconnect called with null pointer.\n");
2652                return;
2653        }
2654        if (usbduxsub_tmp->usbdev != udev) {
2655                dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n");
2656                return;
2657        }
2658        comedi_usb_auto_unconfig(intf);
2659        down(&start_stop_sem);
2660        down(&usbduxsub_tmp->sem);
2661        tidy_up(usbduxsub_tmp);
2662        up(&usbduxsub_tmp->sem);
2663        up(&start_stop_sem);
2664        dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
2665}
2666
2667static const struct usb_device_id usbdux_usb_table[] = {
2668        { USB_DEVICE(0x13d8, 0x0001) },
2669        { USB_DEVICE(0x13d8, 0x0002) },
2670        { }
2671};
2672
2673MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
2674
2675static struct usb_driver usbdux_usb_driver = {
2676        .name           = "usbdux",
2677        .probe          = usbdux_usb_probe,
2678        .disconnect     = usbdux_usb_disconnect,
2679        .id_table       = usbdux_usb_table,
2680};
2681module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
2682
2683MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
2684MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");
2685MODULE_LICENSE("GPL");
2686MODULE_FIRMWARE(FIRMWARE);
2687