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