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