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