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