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#include <linux/kernel.h>
  82#include <linux/module.h>
  83#include <linux/slab.h>
  84#include <linux/input.h>
  85#include <linux/usb.h>
  86#include <linux/fcntl.h>
  87#include <linux/compiler.h>
  88
  89#include "../comedidev.h"
  90
  91#include "comedi_fc.h"
  92
  93/* constants for firmware upload and download */
  94#define USBDUX_FIRMWARE         "usbdux_firmware.bin"
  95#define USBDUX_FIRMWARE_MAX_LEN 0x2000
  96#define USBDUX_FIRMWARE_CMD     0xa0
  97#define VENDOR_DIR_IN           0xc0
  98#define VENDOR_DIR_OUT          0x40
  99#define USBDUX_CPU_CS           0xe600
 100
 101/* usbdux bulk transfer commands */
 102#define USBDUX_CMD_MULT_AI      0
 103#define USBDUX_CMD_AO           1
 104#define USBDUX_CMD_DIO_CFG      2
 105#define USBDUX_CMD_DIO_BITS     3
 106#define USBDUX_CMD_SINGLE_AI    4
 107#define USBDUX_CMD_TIMER_RD     5
 108#define USBDUX_CMD_TIMER_WR     6
 109#define USBDUX_CMD_PWM_ON       7
 110#define USBDUX_CMD_PWM_OFF      8
 111
 112#define USBDUX_NUM_AO_CHAN      4
 113
 114/* timeout for the USB-transfer in ms */
 115#define BULK_TIMEOUT            1000
 116
 117/* 300Hz max frequ under PWM */
 118#define MIN_PWM_PERIOD  ((long)(1E9/300))
 119
 120/* Default PWM frequency */
 121#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
 122
 123/* Size of one A/D value */
 124#define SIZEADIN          ((sizeof(uint16_t)))
 125
 126/*
 127 * Size of the input-buffer IN BYTES
 128 * Always multiple of 8 for 8 microframes which is needed in the highspeed mode
 129 */
 130#define SIZEINBUF         ((8*SIZEADIN))
 131
 132/* 16 bytes. */
 133#define SIZEINSNBUF       16
 134
 135/* size of one value for the D/A converter: channel and value */
 136#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(uint16_t)))
 137
 138/*
 139 * Size of the output-buffer in bytes
 140 * Actually only the first 4 triplets are used but for the
 141 * high speed mode we need to pad it to 8 (microframes).
 142 */
 143#define SIZEOUTBUF         ((8*SIZEDAOUT))
 144
 145/*
 146 * Size of the buffer for the dux commands: just now max size is determined
 147 * by the analogue out + command byte + panic bytes...
 148 */
 149#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
 150
 151/* Number of in-URBs which receive the data: min=2 */
 152#define NUMOFINBUFFERSFULL     5
 153
 154/* Number of out-URBs which send the data: min=2 */
 155#define NUMOFOUTBUFFERSFULL    5
 156
 157/* Number of in-URBs which receive the data: min=5 */
 158/* must have more buffers due to buggy USB ctr */
 159#define NUMOFINBUFFERSHIGH     10
 160
 161/* Number of out-URBs which send the data: min=5 */
 162/* must have more buffers due to buggy USB ctr */
 163#define NUMOFOUTBUFFERSHIGH    10
 164
 165/* number of retries to get the right dux command */
 166#define RETRIES 10
 167
 168static const struct comedi_lrange range_usbdux_ai_range = {
 169        4, {
 170                BIP_RANGE(4.096),
 171                BIP_RANGE(4.096 / 2),
 172                UNI_RANGE(4.096),
 173                UNI_RANGE(4.096 / 2)
 174        }
 175};
 176
 177static const struct comedi_lrange range_usbdux_ao_range = {
 178        2, {
 179                BIP_RANGE(4.096),
 180                UNI_RANGE(4.096)
 181        }
 182};
 183
 184struct usbdux_private {
 185        /* actual number of in-buffers */
 186        int n_ai_urbs;
 187        /* actual number of out-buffers */
 188        int n_ao_urbs;
 189        /* ISO-transfer handling: buffers */
 190        struct urb **ai_urbs;
 191        struct urb **ao_urbs;
 192        /* pwm-transfer handling */
 193        struct urb *pwm_urb;
 194        /* PWM period */
 195        unsigned int pwm_period;
 196        /* PWM internal delay for the GPIF in the FX2 */
 197        uint8_t pwm_delay;
 198        /* size of the PWM buffer which holds the bit pattern */
 199        int pwm_buf_sz;
 200        /* input buffer for the ISO-transfer */
 201        uint16_t *in_buf;
 202        /* input buffer for single insn */
 203        uint16_t *insn_buf;
 204
 205        uint8_t ao_chanlist[USBDUX_NUM_AO_CHAN];
 206        unsigned int ao_readback[USBDUX_NUM_AO_CHAN];
 207
 208        unsigned int high_speed:1;
 209        unsigned int ai_cmd_running:1;
 210        unsigned int ai_continous:1;
 211        unsigned int ao_cmd_running:1;
 212        unsigned int ao_continous:1;
 213        unsigned int pwm_cmd_running:1;
 214
 215        /* number of samples to acquire */
 216        int ai_sample_count;
 217        int ao_sample_count;
 218        /* time between samples in units of the timer */
 219        unsigned int ai_timer;
 220        unsigned int ao_timer;
 221        /* counter between aquisitions */
 222        unsigned int ai_counter;
 223        unsigned int ao_counter;
 224        /* interval in frames/uframes */
 225        unsigned int ai_interval;
 226        /* commands */
 227        uint8_t *dux_commands;
 228        struct semaphore sem;
 229};
 230
 231static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs)
 232{
 233        int i;
 234
 235        for (i = 0; i < num_urbs; i++)
 236                usb_kill_urb(urbs[i]);
 237}
 238
 239static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink)
 240{
 241        struct usbdux_private *devpriv = dev->private;
 242
 243        if (do_unlink && devpriv->ai_urbs)
 244                usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
 245
 246        devpriv->ai_cmd_running = 0;
 247}
 248
 249static int usbdux_ai_cancel(struct comedi_device *dev,
 250                            struct comedi_subdevice *s)
 251{
 252        struct usbdux_private *devpriv = dev->private;
 253
 254        /* prevent other CPUs from submitting new commands just now */
 255        down(&devpriv->sem);
 256        /* unlink only if the urb really has been submitted */
 257        usbdux_ai_stop(dev, devpriv->ai_cmd_running);
 258        up(&devpriv->sem);
 259
 260        return 0;
 261}
 262
 263/* analogue IN - interrupt service routine */
 264static void usbduxsub_ai_isoc_irq(struct urb *urb)
 265{
 266        struct comedi_device *dev = urb->context;
 267        struct comedi_subdevice *s = dev->read_subdev;
 268        struct usbdux_private *devpriv = dev->private;
 269        int i, err, n;
 270
 271        /* first we test if something unusual has just happened */
 272        switch (urb->status) {
 273        case 0:
 274                /* copy the result in the transfer buffer */
 275                memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
 276                break;
 277        case -EILSEQ:
 278                /* error in the ISOchronous data */
 279                /* we don't copy the data into the transfer buffer */
 280                /* and recycle the last data byte */
 281                dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
 282                break;
 283
 284        case -ECONNRESET:
 285        case -ENOENT:
 286        case -ESHUTDOWN:
 287        case -ECONNABORTED:
 288                /* happens after an unlink command */
 289                if (devpriv->ai_cmd_running) {
 290                        s->async->events |= COMEDI_CB_EOA;
 291                        s->async->events |= COMEDI_CB_ERROR;
 292                        comedi_event(dev, s);
 293                        /* stop the transfer w/o unlink */
 294                        usbdux_ai_stop(dev, 0);
 295                }
 296                return;
 297
 298        default:
 299                /* a real error on the bus */
 300                /* pass error to comedi if we are really running a command */
 301                if (devpriv->ai_cmd_running) {
 302                        dev_err(dev->class_dev,
 303                                "Non-zero urb status received in ai intr context: %d\n",
 304                                urb->status);
 305                        s->async->events |= COMEDI_CB_EOA;
 306                        s->async->events |= COMEDI_CB_ERROR;
 307                        comedi_event(dev, s);
 308                        /* don't do an unlink here */
 309                        usbdux_ai_stop(dev, 0);
 310                }
 311                return;
 312        }
 313
 314        /*
 315         * at this point we are reasonably sure that nothing dodgy has happened
 316         * are we running a command?
 317         */
 318        if (unlikely(!devpriv->ai_cmd_running)) {
 319                /*
 320                 * not running a command, do not continue execution if no
 321                 * asynchronous command is running in particular not resubmit
 322                 */
 323                return;
 324        }
 325
 326        urb->dev = comedi_to_usb_dev(dev);
 327
 328        /* resubmit the urb */
 329        err = usb_submit_urb(urb, GFP_ATOMIC);
 330        if (unlikely(err < 0)) {
 331                dev_err(dev->class_dev,
 332                        "urb resubmit failed in int-context! err=%d\n", err);
 333                if (err == -EL2NSYNC)
 334                        dev_err(dev->class_dev,
 335                                "buggy USB host controller or bug in IRQ handler!\n");
 336                s->async->events |= COMEDI_CB_EOA;
 337                s->async->events |= COMEDI_CB_ERROR;
 338                comedi_event(dev, s);
 339                /* don't do an unlink here */
 340                usbdux_ai_stop(dev, 0);
 341                return;
 342        }
 343
 344        devpriv->ai_counter--;
 345        if (likely(devpriv->ai_counter > 0))
 346                return;
 347
 348        /* timer zero, transfer measurements to comedi */
 349        devpriv->ai_counter = devpriv->ai_timer;
 350
 351        /* test, if we transmit only a fixed number of samples */
 352        if (!devpriv->ai_continous) {
 353                /* not continuous, fixed number of samples */
 354                devpriv->ai_sample_count--;
 355                /* all samples received? */
 356                if (devpriv->ai_sample_count < 0) {
 357                        /* prevent a resubmit next time */
 358                        usbdux_ai_stop(dev, 0);
 359                        /* say comedi that the acquistion is over */
 360                        s->async->events |= COMEDI_CB_EOA;
 361                        comedi_event(dev, s);
 362                        return;
 363                }
 364        }
 365        /* get the data from the USB bus and hand it over to comedi */
 366        n = s->async->cmd.chanlist_len;
 367        for (i = 0; i < n; i++) {
 368                unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]);
 369                uint16_t val = le16_to_cpu(devpriv->in_buf[i]);
 370
 371                /* bipolar data is two's-complement */
 372                if (comedi_range_is_bipolar(s, range))
 373                        val ^= ((s->maxdata + 1) >> 1);
 374
 375                /* transfer data */
 376                err = comedi_buf_put(s->async, val);
 377                if (unlikely(err == 0)) {
 378                        /* buffer overflow */
 379                        usbdux_ai_stop(dev, 0);
 380                        return;
 381                }
 382        }
 383        /* tell comedi that data is there */
 384        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
 385        comedi_event(dev, s);
 386}
 387
 388static void usbdux_ao_stop(struct comedi_device *dev, int do_unlink)
 389{
 390        struct usbdux_private *devpriv = dev->private;
 391
 392        if (do_unlink && devpriv->ao_urbs)
 393                usbdux_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
 394
 395        devpriv->ao_cmd_running = 0;
 396}
 397
 398static int usbdux_ao_cancel(struct comedi_device *dev,
 399                            struct comedi_subdevice *s)
 400{
 401        struct usbdux_private *devpriv = dev->private;
 402
 403        /* prevent other CPUs from submitting a command just now */
 404        down(&devpriv->sem);
 405        /* unlink only if it is really running */
 406        usbdux_ao_stop(dev, devpriv->ao_cmd_running);
 407        up(&devpriv->sem);
 408
 409        return 0;
 410}
 411
 412static void usbduxsub_ao_isoc_irq(struct urb *urb)
 413{
 414        struct comedi_device *dev = urb->context;
 415        struct comedi_subdevice *s = dev->write_subdev;
 416        struct usbdux_private *devpriv = dev->private;
 417        uint8_t *datap;
 418        int len;
 419        int ret;
 420        int i;
 421
 422        switch (urb->status) {
 423        case 0:
 424                /* success */
 425                break;
 426
 427        case -ECONNRESET:
 428        case -ENOENT:
 429        case -ESHUTDOWN:
 430        case -ECONNABORTED:
 431                /* after an unlink command, unplug, ... etc */
 432                /* no unlink needed here. Already shutting down. */
 433                if (devpriv->ao_cmd_running) {
 434                        s->async->events |= COMEDI_CB_EOA;
 435                        comedi_event(dev, s);
 436                        usbdux_ao_stop(dev, 0);
 437                }
 438                return;
 439
 440        default:
 441                /* a real error */
 442                if (devpriv->ao_cmd_running) {
 443                        dev_err(dev->class_dev,
 444                                "Non-zero urb status received in ao intr context: %d\n",
 445                                urb->status);
 446                        s->async->events |= COMEDI_CB_ERROR;
 447                        s->async->events |= COMEDI_CB_EOA;
 448                        comedi_event(dev, s);
 449                        /* we do an unlink if we are in the high speed mode */
 450                        usbdux_ao_stop(dev, 0);
 451                }
 452                return;
 453        }
 454
 455        /* are we actually running? */
 456        if (!devpriv->ao_cmd_running)
 457                return;
 458
 459        /* normal operation: executing a command in this subdevice */
 460        devpriv->ao_counter--;
 461        if ((int)devpriv->ao_counter <= 0) {
 462                /* timer zero */
 463                devpriv->ao_counter = devpriv->ao_timer;
 464
 465                /* handle non continous acquisition */
 466                if (!devpriv->ao_continous) {
 467                        /* fixed number of samples */
 468                        devpriv->ao_sample_count--;
 469                        if (devpriv->ao_sample_count < 0) {
 470                                /* all samples transmitted */
 471                                usbdux_ao_stop(dev, 0);
 472                                s->async->events |= COMEDI_CB_EOA;
 473                                comedi_event(dev, s);
 474                                /* no resubmit of the urb */
 475                                return;
 476                        }
 477                }
 478
 479                /* transmit data to the USB bus */
 480                datap = urb->transfer_buffer;
 481                len = s->async->cmd.chanlist_len;
 482                *datap++ = len;
 483                for (i = 0; i < s->async->cmd.chanlist_len; i++) {
 484                        unsigned int chan = devpriv->ao_chanlist[i];
 485                        unsigned short val;
 486
 487                        ret = comedi_buf_get(s->async, &val);
 488                        if (ret < 0) {
 489                                dev_err(dev->class_dev, "buffer underflow\n");
 490                                s->async->events |= (COMEDI_CB_EOA |
 491                                                     COMEDI_CB_OVERFLOW);
 492                        }
 493                        /* pointer to the DA */
 494                        *datap++ = val & 0xff;
 495                        *datap++ = (val >> 8) & 0xff;
 496                        *datap++ = chan << 6;
 497                        devpriv->ao_readback[chan] = val;
 498
 499                        s->async->events |= COMEDI_CB_BLOCK;
 500                        comedi_event(dev, s);
 501                }
 502        }
 503        urb->transfer_buffer_length = SIZEOUTBUF;
 504        urb->dev = comedi_to_usb_dev(dev);
 505        urb->status = 0;
 506        if (devpriv->ao_cmd_running) {
 507                if (devpriv->high_speed)
 508                        urb->interval = 8;      /* uframes */
 509                else
 510                        urb->interval = 1;      /* frames */
 511                urb->number_of_packets = 1;
 512                urb->iso_frame_desc[0].offset = 0;
 513                urb->iso_frame_desc[0].length = SIZEOUTBUF;
 514                urb->iso_frame_desc[0].status = 0;
 515                ret = usb_submit_urb(urb, GFP_ATOMIC);
 516                if (ret < 0) {
 517                        dev_err(dev->class_dev,
 518                                "ao urb resubm failed in int-cont. ret=%d",
 519                                ret);
 520                        if (ret == EL2NSYNC)
 521                                dev_err(dev->class_dev,
 522                                        "buggy USB host controller or bug in IRQ handling!\n");
 523
 524                        s->async->events |= COMEDI_CB_EOA;
 525                        s->async->events |= COMEDI_CB_ERROR;
 526                        comedi_event(dev, s);
 527                        /* don't do an unlink here */
 528                        usbdux_ao_stop(dev, 0);
 529                }
 530        }
 531}
 532
 533static int usbdux_submit_urbs(struct comedi_device *dev,
 534                              struct urb **urbs, int num_urbs,
 535                              int input_urb)
 536{
 537        struct usb_device *usb = comedi_to_usb_dev(dev);
 538        struct usbdux_private *devpriv = dev->private;
 539        struct urb *urb;
 540        int ret;
 541        int i;
 542
 543        /* Submit all URBs and start the transfer on the bus */
 544        for (i = 0; i < num_urbs; i++) {
 545                urb = urbs[i];
 546
 547                /* in case of a resubmission after an unlink... */
 548                if (input_urb)
 549                        urb->interval = devpriv->ai_interval;
 550                urb->context = dev;
 551                urb->dev = usb;
 552                urb->status = 0;
 553                urb->transfer_flags = URB_ISO_ASAP;
 554
 555                ret = usb_submit_urb(urb, GFP_ATOMIC);
 556                if (ret)
 557                        return ret;
 558        }
 559        return 0;
 560}
 561
 562static int usbdux_ai_cmdtest(struct comedi_device *dev,
 563                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 564{
 565        struct usbdux_private *this_usbduxsub = dev->private;
 566        int err = 0, i;
 567        unsigned int tmp_timer;
 568
 569        /* Step 1 : check if triggers are trivially valid */
 570
 571        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 572        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
 573        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 574        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 575        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 576
 577        if (err)
 578                return 1;
 579
 580        /* Step 2a : make sure trigger sources are unique */
 581
 582        err |= cfc_check_trigger_is_unique(cmd->start_src);
 583        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 584
 585        /* Step 2b : and mutually compatible */
 586
 587        if (err)
 588                return 2;
 589
 590        /* Step 3: check if arguments are trivially valid */
 591
 592        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 593
 594        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 595                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 596
 597        if (cmd->scan_begin_src == TRIG_TIMER) {
 598                if (this_usbduxsub->high_speed) {
 599                        /*
 600                         * In high speed mode microframes are possible.
 601                         * However, during one microframe we can roughly
 602                         * sample one channel. Thus, the more channels
 603                         * are in the channel list the more time we need.
 604                         */
 605                        i = 1;
 606                        /* find a power of 2 for the number of channels */
 607                        while (i < (cmd->chanlist_len))
 608                                i = i * 2;
 609
 610                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 611                                                         1000000 / 8 * i);
 612                        /* now calc the real sampling rate with all the
 613                         * rounding errors */
 614                        tmp_timer =
 615                            ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 616                            125000;
 617                } else {
 618                        /* full speed */
 619                        /* 1kHz scans every USB frame */
 620                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 621                                                         1000000);
 622                        /*
 623                         * calc the real sampling rate with the rounding errors
 624                         */
 625                        tmp_timer = ((unsigned int)(cmd->scan_begin_arg /
 626                                                   1000000)) * 1000000;
 627                }
 628                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
 629                                                tmp_timer);
 630        }
 631
 632        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 633
 634        if (cmd->stop_src == TRIG_COUNT) {
 635                /* any count is allowed */
 636        } else {
 637                /* TRIG_NONE */
 638                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 639        }
 640
 641        if (err)
 642                return 3;
 643
 644        return 0;
 645}
 646
 647/*
 648 * creates the ADC command for the MAX1271
 649 * range is the range value from comedi
 650 */
 651static uint8_t create_adc_command(unsigned int chan, unsigned int range)
 652{
 653        uint8_t p = (range <= 1);
 654        uint8_t r = ((range % 2) == 0);
 655
 656        return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
 657}
 658
 659static int send_dux_commands(struct comedi_device *dev, unsigned int cmd_type)
 660{
 661        struct usb_device *usb = comedi_to_usb_dev(dev);
 662        struct usbdux_private *devpriv = dev->private;
 663        int nsent;
 664
 665        devpriv->dux_commands[0] = cmd_type;
 666
 667        return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
 668                            devpriv->dux_commands, SIZEOFDUXBUFFER,
 669                            &nsent, BULK_TIMEOUT);
 670}
 671
 672static int receive_dux_commands(struct comedi_device *dev, unsigned int command)
 673{
 674        struct usb_device *usb = comedi_to_usb_dev(dev);
 675        struct usbdux_private *devpriv = dev->private;
 676        int ret;
 677        int nrec;
 678        int i;
 679
 680        for (i = 0; i < RETRIES; i++) {
 681                ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
 682                                      devpriv->insn_buf, SIZEINSNBUF,
 683                                      &nrec, BULK_TIMEOUT);
 684                if (ret < 0)
 685                        return ret;
 686                if (le16_to_cpu(devpriv->insn_buf[0]) == command)
 687                        return ret;
 688        }
 689        /* command not received */
 690        return -EFAULT;
 691}
 692
 693static int usbdux_ai_inttrig(struct comedi_device *dev,
 694                             struct comedi_subdevice *s,
 695                             unsigned int trignum)
 696{
 697        struct usbdux_private *devpriv = dev->private;
 698        int ret = -EINVAL;
 699
 700        down(&devpriv->sem);
 701
 702        if (trignum != 0)
 703                goto ai_trig_exit;
 704
 705        if (!devpriv->ai_cmd_running) {
 706                devpriv->ai_cmd_running = 1;
 707                ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
 708                                         devpriv->n_ai_urbs, 1);
 709                if (ret < 0) {
 710                        devpriv->ai_cmd_running = 0;
 711                        goto ai_trig_exit;
 712                }
 713                s->async->inttrig = NULL;
 714        } else {
 715                ret = -EBUSY;
 716        }
 717
 718ai_trig_exit:
 719        up(&devpriv->sem);
 720        return ret;
 721}
 722
 723static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 724{
 725        struct usbdux_private *devpriv = dev->private;
 726        struct comedi_cmd *cmd = &s->async->cmd;
 727        int len = cmd->chanlist_len;
 728        int ret = -EBUSY;
 729        int i;
 730
 731        /* block other CPUs from starting an ai_cmd */
 732        down(&devpriv->sem);
 733
 734        if (devpriv->ai_cmd_running)
 735                goto ai_cmd_exit;
 736
 737        /* set current channel of the running acquisition to zero */
 738        s->async->cur_chan = 0;
 739
 740        devpriv->dux_commands[1] = len;
 741        for (i = 0; i < len; ++i) {
 742                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 743                unsigned int range = CR_RANGE(cmd->chanlist[i]);
 744
 745                devpriv->dux_commands[i + 2] = create_adc_command(chan, range);
 746        }
 747
 748        ret = send_dux_commands(dev, USBDUX_CMD_MULT_AI);
 749        if (ret < 0)
 750                goto ai_cmd_exit;
 751
 752        if (devpriv->high_speed) {
 753                /*
 754                 * every channel gets a time window of 125us. Thus, if we
 755                 * sample all 8 channels we need 1ms. If we sample only one
 756                 * channel we need only 125us
 757                 */
 758                devpriv->ai_interval = 1;
 759                /* find a power of 2 for the interval */
 760                while (devpriv->ai_interval < len)
 761                        devpriv->ai_interval *= 2;
 762
 763                devpriv->ai_timer = cmd->scan_begin_arg /
 764                                    (125000 * devpriv->ai_interval);
 765        } else {
 766                /* interval always 1ms */
 767                devpriv->ai_interval = 1;
 768                devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
 769        }
 770        if (devpriv->ai_timer < 1) {
 771                ret = -EINVAL;
 772                goto ai_cmd_exit;
 773        }
 774
 775        devpriv->ai_counter = devpriv->ai_timer;
 776
 777        if (cmd->stop_src == TRIG_COUNT) {
 778                /* data arrives as one packet */
 779                devpriv->ai_sample_count = cmd->stop_arg;
 780                devpriv->ai_continous = 0;
 781        } else {
 782                /* continous acquisition */
 783                devpriv->ai_continous = 1;
 784                devpriv->ai_sample_count = 0;
 785        }
 786
 787        if (cmd->start_src == TRIG_NOW) {
 788                /* enable this acquisition operation */
 789                devpriv->ai_cmd_running = 1;
 790                ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
 791                                         devpriv->n_ai_urbs, 1);
 792                if (ret < 0) {
 793                        devpriv->ai_cmd_running = 0;
 794                        /* fixme: unlink here?? */
 795                        goto ai_cmd_exit;
 796                }
 797                s->async->inttrig = NULL;
 798        } else {
 799                /* TRIG_INT */
 800                /* don't enable the acquision operation */
 801                /* wait for an internal signal */
 802                s->async->inttrig = usbdux_ai_inttrig;
 803        }
 804
 805ai_cmd_exit:
 806        up(&devpriv->sem);
 807
 808        return ret;
 809}
 810
 811/* Mode 0 is used to get a single conversion on demand */
 812static int usbdux_ai_insn_read(struct comedi_device *dev,
 813                               struct comedi_subdevice *s,
 814                               struct comedi_insn *insn,
 815                               unsigned int *data)
 816{
 817        struct usbdux_private *devpriv = dev->private;
 818        unsigned int chan = CR_CHAN(insn->chanspec);
 819        unsigned int range = CR_RANGE(insn->chanspec);
 820        unsigned int val;
 821        int ret = -EBUSY;
 822        int i;
 823
 824        down(&devpriv->sem);
 825
 826        if (devpriv->ai_cmd_running)
 827                goto ai_read_exit;
 828
 829        /* set command for the first channel */
 830        devpriv->dux_commands[1] = create_adc_command(chan, range);
 831
 832        /* adc commands */
 833        ret = send_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
 834        if (ret < 0)
 835                goto ai_read_exit;
 836
 837        for (i = 0; i < insn->n; i++) {
 838                ret = receive_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
 839                if (ret < 0)
 840                        goto ai_read_exit;
 841
 842                val = le16_to_cpu(devpriv->insn_buf[1]);
 843
 844                /* bipolar data is two's-complement */
 845                if (comedi_range_is_bipolar(s, range))
 846                        val ^= ((s->maxdata + 1) >> 1);
 847
 848                data[i] = val;
 849        }
 850
 851ai_read_exit:
 852        up(&devpriv->sem);
 853
 854        return ret ? ret : insn->n;
 855}
 856
 857static int usbdux_ao_insn_read(struct comedi_device *dev,
 858                               struct comedi_subdevice *s,
 859                               struct comedi_insn *insn,
 860                               unsigned int *data)
 861{
 862        struct usbdux_private *devpriv = dev->private;
 863        unsigned int chan = CR_CHAN(insn->chanspec);
 864        int i;
 865
 866        down(&devpriv->sem);
 867        for (i = 0; i < insn->n; i++)
 868                data[i] = devpriv->ao_readback[chan];
 869        up(&devpriv->sem);
 870
 871        return insn->n;
 872}
 873
 874static int usbdux_ao_insn_write(struct comedi_device *dev,
 875                                struct comedi_subdevice *s,
 876                                struct comedi_insn *insn,
 877                                unsigned int *data)
 878{
 879        struct usbdux_private *devpriv = dev->private;
 880        unsigned int chan = CR_CHAN(insn->chanspec);
 881        unsigned int val = devpriv->ao_readback[chan];
 882        uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
 883        int ret = -EBUSY;
 884        int i;
 885
 886        down(&devpriv->sem);
 887
 888        if (devpriv->ao_cmd_running)
 889                goto ao_write_exit;
 890
 891        /* number of channels: 1 */
 892        devpriv->dux_commands[1] = 1;
 893        /* channel number */
 894        devpriv->dux_commands[4] = chan << 6;
 895
 896        for (i = 0; i < insn->n; i++) {
 897                val = data[i];
 898
 899                /* one 16 bit value */
 900                *p = cpu_to_le16(val);
 901
 902                ret = send_dux_commands(dev, USBDUX_CMD_AO);
 903                if (ret < 0)
 904                        goto ao_write_exit;
 905        }
 906        devpriv->ao_readback[chan] = val;
 907
 908ao_write_exit:
 909        up(&devpriv->sem);
 910
 911        return ret ? ret : insn->n;
 912}
 913
 914static int usbdux_ao_inttrig(struct comedi_device *dev,
 915                             struct comedi_subdevice *s,
 916                             unsigned int trignum)
 917{
 918        struct usbdux_private *devpriv = dev->private;
 919        int ret = -EINVAL;
 920
 921        down(&devpriv->sem);
 922
 923        if (trignum != 0)
 924                goto ao_trig_exit;
 925
 926        if (!devpriv->ao_cmd_running) {
 927                devpriv->ao_cmd_running = 1;
 928                ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
 929                                         devpriv->n_ao_urbs, 0);
 930                if (ret < 0) {
 931                        devpriv->ao_cmd_running = 0;
 932                        goto ao_trig_exit;
 933                }
 934                s->async->inttrig = NULL;
 935        } else {
 936                ret = -EBUSY;
 937        }
 938
 939ao_trig_exit:
 940        up(&devpriv->sem);
 941        return ret;
 942}
 943
 944static int usbdux_ao_cmdtest(struct comedi_device *dev,
 945                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 946{
 947        struct usbdux_private *this_usbduxsub = dev->private;
 948        int err = 0;
 949        unsigned int flags;
 950
 951        if (!this_usbduxsub)
 952                return -EFAULT;
 953
 954        /* Step 1 : check if triggers are trivially valid */
 955
 956        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 957
 958        if (0) {                /* (this_usbduxsub->high_speed) */
 959                /* the sampling rate is set by the coversion rate */
 960                flags = TRIG_FOLLOW;
 961        } else {
 962                /* start a new scan (output at once) with a timer */
 963                flags = TRIG_TIMER;
 964        }
 965        err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
 966
 967        if (0) {                /* (this_usbduxsub->high_speed) */
 968                /*
 969                 * in usb-2.0 only one conversion it transmitted
 970                 * but with 8kHz/n
 971                 */
 972                flags = TRIG_TIMER;
 973        } else {
 974                /*
 975                 * all conversion events happen simultaneously with
 976                 * a rate of 1kHz/n
 977                 */
 978                flags = TRIG_NOW;
 979        }
 980        err |= cfc_check_trigger_src(&cmd->convert_src, flags);
 981
 982        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 983        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 984
 985        if (err)
 986                return 1;
 987
 988        /* Step 2a : make sure trigger sources are unique */
 989
 990        err |= cfc_check_trigger_is_unique(cmd->start_src);
 991        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 992
 993        /* Step 2b : and mutually compatible */
 994
 995        if (err)
 996                return 2;
 997
 998        /* Step 3: check if arguments are trivially valid */
 999
1000        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1001
1002        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
1003                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1004
1005        if (cmd->scan_begin_src == TRIG_TIMER)
1006                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1007                                                 1000000);
1008
1009        /* not used now, is for later use */
1010        if (cmd->convert_src == TRIG_TIMER)
1011                err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
1012
1013        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1014
1015        if (cmd->stop_src == TRIG_COUNT) {
1016                /* any count is allowed */
1017        } else {
1018                /* TRIG_NONE */
1019                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1020        }
1021
1022        if (err)
1023                return 3;
1024
1025        return 0;
1026}
1027
1028static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1029{
1030        struct usbdux_private *devpriv = dev->private;
1031        struct comedi_cmd *cmd = &s->async->cmd;
1032        int ret = -EBUSY;
1033        int i;
1034
1035        down(&devpriv->sem);
1036
1037        if (devpriv->ao_cmd_running)
1038                goto ao_cmd_exit;
1039
1040        /* set current channel of the running acquisition to zero */
1041        s->async->cur_chan = 0;
1042
1043        for (i = 0; i < cmd->chanlist_len; ++i)
1044                devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]);
1045
1046        /* we count in steps of 1ms (125us) */
1047        /* 125us mode not used yet */
1048        if (0) {                /* (devpriv->high_speed) */
1049                /* 125us */
1050                /* timing of the conversion itself: every 125 us */
1051                devpriv->ao_timer = cmd->convert_arg / 125000;
1052        } else {
1053                /* 1ms */
1054                /* timing of the scan: we get all channels at once */
1055                devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
1056                if (devpriv->ao_timer < 1) {
1057                        ret = -EINVAL;
1058                        goto ao_cmd_exit;
1059                }
1060        }
1061
1062        devpriv->ao_counter = devpriv->ao_timer;
1063
1064        if (cmd->stop_src == TRIG_COUNT) {
1065                /* not continuous */
1066                /* counter */
1067                /* high speed also scans everything at once */
1068                if (0) {        /* (devpriv->high_speed) */
1069                        devpriv->ao_sample_count = cmd->stop_arg *
1070                                                   cmd->scan_end_arg;
1071                } else {
1072                        /* there's no scan as the scan has been */
1073                        /* perf inside the FX2 */
1074                        /* data arrives as one packet */
1075                        devpriv->ao_sample_count = cmd->stop_arg;
1076                }
1077                devpriv->ao_continous = 0;
1078        } else {
1079                /* continous acquisition */
1080                devpriv->ao_continous = 1;
1081                devpriv->ao_sample_count = 0;
1082        }
1083
1084        if (cmd->start_src == TRIG_NOW) {
1085                /* enable this acquisition operation */
1086                devpriv->ao_cmd_running = 1;
1087                ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
1088                                         devpriv->n_ao_urbs, 0);
1089                if (ret < 0) {
1090                        devpriv->ao_cmd_running = 0;
1091                        /* fixme: unlink here?? */
1092                        goto ao_cmd_exit;
1093                }
1094                s->async->inttrig = NULL;
1095        } else {
1096                /* TRIG_INT */
1097                /* submit the urbs later */
1098                /* wait for an internal signal */
1099                s->async->inttrig = usbdux_ao_inttrig;
1100        }
1101
1102ao_cmd_exit:
1103        up(&devpriv->sem);
1104
1105        return ret;
1106}
1107
1108static int usbdux_dio_insn_config(struct comedi_device *dev,
1109                                  struct comedi_subdevice *s,
1110                                  struct comedi_insn *insn,
1111                                  unsigned int *data)
1112{
1113        int ret;
1114
1115        ret = comedi_dio_insn_config(dev, s, insn, data, 0);
1116        if (ret)
1117                return ret;
1118
1119        /*
1120         * We don't tell the firmware here as it would take 8 frames
1121         * to submit the information. We do it in the insn_bits.
1122         */
1123        return insn->n;
1124}
1125
1126static int usbdux_dio_insn_bits(struct comedi_device *dev,
1127                                struct comedi_subdevice *s,
1128                                struct comedi_insn *insn,
1129                                unsigned int *data)
1130{
1131
1132        struct usbdux_private *devpriv = dev->private;
1133        int ret;
1134
1135        down(&devpriv->sem);
1136
1137        comedi_dio_update_state(s, data);
1138
1139        /* Always update the hardware. See the (*insn_config). */
1140        devpriv->dux_commands[1] = s->io_bits;
1141        devpriv->dux_commands[2] = s->state;
1142
1143        /*
1144         * This command also tells the firmware to return
1145         * the digital input lines.
1146         */
1147        ret = send_dux_commands(dev, USBDUX_CMD_DIO_BITS);
1148        if (ret < 0)
1149                goto dio_exit;
1150        ret = receive_dux_commands(dev, USBDUX_CMD_DIO_BITS);
1151        if (ret < 0)
1152                goto dio_exit;
1153
1154        data[1] = le16_to_cpu(devpriv->insn_buf[1]);
1155
1156dio_exit:
1157        up(&devpriv->sem);
1158
1159        return ret ? ret : insn->n;
1160}
1161
1162static int usbdux_counter_read(struct comedi_device *dev,
1163                               struct comedi_subdevice *s,
1164                               struct comedi_insn *insn,
1165                               unsigned int *data)
1166{
1167        struct usbdux_private *devpriv = dev->private;
1168        unsigned int chan = CR_CHAN(insn->chanspec);
1169        int ret = 0;
1170        int i;
1171
1172        down(&devpriv->sem);
1173
1174        for (i = 0; i < insn->n; i++) {
1175                ret = send_dux_commands(dev, USBDUX_CMD_TIMER_RD);
1176                if (ret < 0)
1177                        goto counter_read_exit;
1178                ret = receive_dux_commands(dev, USBDUX_CMD_TIMER_RD);
1179                if (ret < 0)
1180                        goto counter_read_exit;
1181
1182                data[i] = le16_to_cpu(devpriv->insn_buf[chan + 1]);
1183        }
1184
1185counter_read_exit:
1186        up(&devpriv->sem);
1187
1188        return ret ? ret : insn->n;
1189}
1190
1191static int usbdux_counter_write(struct comedi_device *dev,
1192                                struct comedi_subdevice *s,
1193                                struct comedi_insn *insn,
1194                                unsigned int *data)
1195{
1196        struct usbdux_private *devpriv = dev->private;
1197        unsigned int chan = CR_CHAN(insn->chanspec);
1198        uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
1199        int ret = 0;
1200        int i;
1201
1202        down(&devpriv->sem);
1203
1204        devpriv->dux_commands[1] = chan;
1205
1206        for (i = 0; i < insn->n; i++) {
1207                *p = cpu_to_le16(data[i]);
1208
1209                ret = send_dux_commands(dev, USBDUX_CMD_TIMER_WR);
1210                if (ret < 0)
1211                        break;
1212        }
1213
1214        up(&devpriv->sem);
1215
1216        return ret ? ret : insn->n;
1217}
1218
1219static int usbdux_counter_config(struct comedi_device *dev,
1220                                 struct comedi_subdevice *s,
1221                                 struct comedi_insn *insn, unsigned int *data)
1222{
1223        /* nothing to do so far */
1224        return 2;
1225}
1226
1227static void usbduxsub_unlink_pwm_urbs(struct comedi_device *dev)
1228{
1229        struct usbdux_private *devpriv = dev->private;
1230
1231        usb_kill_urb(devpriv->pwm_urb);
1232}
1233
1234static void usbdux_pwm_stop(struct comedi_device *dev, int do_unlink)
1235{
1236        struct usbdux_private *devpriv = dev->private;
1237
1238        if (do_unlink)
1239                usbduxsub_unlink_pwm_urbs(dev);
1240
1241        devpriv->pwm_cmd_running = 0;
1242}
1243
1244static int usbdux_pwm_cancel(struct comedi_device *dev,
1245                             struct comedi_subdevice *s)
1246{
1247        struct usbdux_private *devpriv = dev->private;
1248        int ret;
1249
1250        down(&devpriv->sem);
1251        /* unlink only if it is really running */
1252        usbdux_pwm_stop(dev, devpriv->pwm_cmd_running);
1253        ret = send_dux_commands(dev, USBDUX_CMD_PWM_OFF);
1254        up(&devpriv->sem);
1255
1256        return ret;
1257}
1258
1259static void usbduxsub_pwm_irq(struct urb *urb)
1260{
1261        struct comedi_device *dev = urb->context;
1262        struct usbdux_private *devpriv = dev->private;
1263        int ret;
1264
1265        switch (urb->status) {
1266        case 0:
1267                /* success */
1268                break;
1269
1270        case -ECONNRESET:
1271        case -ENOENT:
1272        case -ESHUTDOWN:
1273        case -ECONNABORTED:
1274                /*
1275                 * after an unlink command, unplug, ... etc
1276                 * no unlink needed here. Already shutting down.
1277                 */
1278                if (devpriv->pwm_cmd_running)
1279                        usbdux_pwm_stop(dev, 0);
1280
1281                return;
1282
1283        default:
1284                /* a real error */
1285                if (devpriv->pwm_cmd_running) {
1286                        dev_err(dev->class_dev,
1287                                "Non-zero urb status received in pwm intr context: %d\n",
1288                                urb->status);
1289                        usbdux_pwm_stop(dev, 0);
1290                }
1291                return;
1292        }
1293
1294        /* are we actually running? */
1295        if (!devpriv->pwm_cmd_running)
1296                return;
1297
1298        urb->transfer_buffer_length = devpriv->pwm_buf_sz;
1299        urb->dev = comedi_to_usb_dev(dev);
1300        urb->status = 0;
1301        if (devpriv->pwm_cmd_running) {
1302                ret = usb_submit_urb(urb, GFP_ATOMIC);
1303                if (ret < 0) {
1304                        dev_err(dev->class_dev,
1305                                "pwm urb resubm failed in int-cont. ret=%d",
1306                                ret);
1307                        if (ret == EL2NSYNC)
1308                                dev_err(dev->class_dev,
1309                                        "buggy USB host controller or bug in IRQ handling!\n");
1310
1311                        /* don't do an unlink here */
1312                        usbdux_pwm_stop(dev, 0);
1313                }
1314        }
1315}
1316
1317static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev)
1318{
1319        struct usb_device *usb = comedi_to_usb_dev(dev);
1320        struct usbdux_private *devpriv = dev->private;
1321        struct urb *urb = devpriv->pwm_urb;
1322
1323        /* in case of a resubmission after an unlink... */
1324        usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
1325                          urb->transfer_buffer,
1326                          devpriv->pwm_buf_sz,
1327                          usbduxsub_pwm_irq,
1328                          dev);
1329
1330        return usb_submit_urb(urb, GFP_ATOMIC);
1331}
1332
1333static int usbdux_pwm_period(struct comedi_device *dev,
1334                             struct comedi_subdevice *s,
1335                             unsigned int period)
1336{
1337        struct usbdux_private *devpriv = dev->private;
1338        int fx2delay = 255;
1339
1340        if (period < MIN_PWM_PERIOD) {
1341                return -EAGAIN;
1342        } else {
1343                fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
1344                if (fx2delay > 255)
1345                        return -EAGAIN;
1346        }
1347        devpriv->pwm_delay = fx2delay;
1348        devpriv->pwm_period = period;
1349
1350        return 0;
1351}
1352
1353static int usbdux_pwm_start(struct comedi_device *dev,
1354                            struct comedi_subdevice *s)
1355{
1356        struct usbdux_private *devpriv = dev->private;
1357        int ret = 0;
1358
1359        down(&devpriv->sem);
1360
1361        if (devpriv->pwm_cmd_running)
1362                goto pwm_start_exit;
1363
1364        devpriv->dux_commands[1] = devpriv->pwm_delay;
1365        ret = send_dux_commands(dev, USBDUX_CMD_PWM_ON);
1366        if (ret < 0)
1367                goto pwm_start_exit;
1368
1369        /* initialise the buffer */
1370        memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
1371
1372        devpriv->pwm_cmd_running = 1;
1373        ret = usbduxsub_submit_pwm_urbs(dev);
1374        if (ret < 0)
1375                devpriv->pwm_cmd_running = 0;
1376
1377pwm_start_exit:
1378        up(&devpriv->sem);
1379
1380        return ret;
1381}
1382
1383static void usbdux_pwm_pattern(struct comedi_device *dev,
1384                               struct comedi_subdevice *s,
1385                               unsigned int chan,
1386                               unsigned int value,
1387                               unsigned int sign)
1388{
1389        struct usbdux_private *devpriv = dev->private;
1390        char pwm_mask = (1 << chan);    /* DIO bit for the PWM data */
1391        char sgn_mask = (16 << chan);   /* DIO bit for the sign */
1392        char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
1393        int szbuf = devpriv->pwm_buf_sz;
1394        int i;
1395
1396        for (i = 0; i < szbuf; i++) {
1397                char c = *buf;
1398
1399                c &= ~pwm_mask;
1400                if (i < value)
1401                        c |= pwm_mask;
1402                if (!sign)
1403                        c &= ~sgn_mask;
1404                else
1405                        c |= sgn_mask;
1406                *buf++ = c;
1407        }
1408}
1409
1410static int usbdux_pwm_write(struct comedi_device *dev,
1411                            struct comedi_subdevice *s,
1412                            struct comedi_insn *insn,
1413                            unsigned int *data)
1414{
1415        unsigned int chan = CR_CHAN(insn->chanspec);
1416
1417        /*
1418         * It doesn't make sense to support more than one value here
1419         * because it would just overwrite the PWM buffer.
1420         */
1421        if (insn->n != 1)
1422                return -EINVAL;
1423
1424        /*
1425         * The sign is set via a special INSN only, this gives us 8 bits
1426         * for normal operation, sign is 0 by default.
1427         */
1428        usbdux_pwm_pattern(dev, s, chan, data[0], 0);
1429
1430        return insn->n;
1431}
1432
1433static int usbdux_pwm_config(struct comedi_device *dev,
1434                             struct comedi_subdevice *s,
1435                             struct comedi_insn *insn,
1436                             unsigned int *data)
1437{
1438        struct usbdux_private *devpriv = dev->private;
1439        unsigned int chan = CR_CHAN(insn->chanspec);
1440
1441        switch (data[0]) {
1442        case INSN_CONFIG_ARM:
1443                /*
1444                 * if not zero the PWM is limited to a certain time which is
1445                 * not supported here
1446                 */
1447                if (data[1] != 0)
1448                        return -EINVAL;
1449                return usbdux_pwm_start(dev, s);
1450        case INSN_CONFIG_DISARM:
1451                return usbdux_pwm_cancel(dev, s);
1452        case INSN_CONFIG_GET_PWM_STATUS:
1453                data[1] = devpriv->pwm_cmd_running;
1454                return 0;
1455        case INSN_CONFIG_PWM_SET_PERIOD:
1456                return usbdux_pwm_period(dev, s, data[1]);
1457        case INSN_CONFIG_PWM_GET_PERIOD:
1458                data[1] = devpriv->pwm_period;
1459                return 0;
1460        case INSN_CONFIG_PWM_SET_H_BRIDGE:
1461                /*
1462                 * data[1] = value
1463                 * data[2] = sign (for a relay)
1464                 */
1465                usbdux_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
1466                return 0;
1467        case INSN_CONFIG_PWM_GET_H_BRIDGE:
1468                /* values are not kept in this driver, nothing to return here */
1469                return -EINVAL;
1470        }
1471        return -EINVAL;
1472}
1473
1474static int usbdux_firmware_upload(struct comedi_device *dev,
1475                                  const u8 *data, size_t size,
1476                                  unsigned long context)
1477{
1478        struct usb_device *usb = comedi_to_usb_dev(dev);
1479        uint8_t *buf;
1480        uint8_t *tmp;
1481        int ret;
1482
1483        if (!data)
1484                return 0;
1485
1486        if (size > USBDUX_FIRMWARE_MAX_LEN) {
1487                dev_err(dev->class_dev,
1488                        "usbdux firmware binary it too large for FX2.\n");
1489                return -ENOMEM;
1490        }
1491
1492        /* we generate a local buffer for the firmware */
1493        buf = kmemdup(data, size, GFP_KERNEL);
1494        if (!buf)
1495                return -ENOMEM;
1496
1497        /* we need a malloc'ed buffer for usb_control_msg() */
1498        tmp = kmalloc(1, GFP_KERNEL);
1499        if (!tmp) {
1500                kfree(buf);
1501                return -ENOMEM;
1502        }
1503
1504        /* stop the current firmware on the device */
1505        *tmp = 1;       /* 7f92 to one */
1506        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1507                              USBDUX_FIRMWARE_CMD,
1508                              VENDOR_DIR_OUT,
1509                              USBDUX_CPU_CS, 0x0000,
1510                              tmp, 1,
1511                              BULK_TIMEOUT);
1512        if (ret < 0) {
1513                dev_err(dev->class_dev, "can not stop firmware\n");
1514                goto done;
1515        }
1516
1517        /* upload the new firmware to the device */
1518        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1519                              USBDUX_FIRMWARE_CMD,
1520                              VENDOR_DIR_OUT,
1521                              0, 0x0000,
1522                              buf, size,
1523                              BULK_TIMEOUT);
1524        if (ret < 0) {
1525                dev_err(dev->class_dev, "firmware upload failed\n");
1526                goto done;
1527        }
1528
1529        /* start the new firmware on the device */
1530        *tmp = 0;       /* 7f92 to zero */
1531        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1532                              USBDUX_FIRMWARE_CMD,
1533                              VENDOR_DIR_OUT,
1534                              USBDUX_CPU_CS, 0x0000,
1535                              tmp, 1,
1536                              BULK_TIMEOUT);
1537        if (ret < 0)
1538                dev_err(dev->class_dev, "can not start firmware\n");
1539
1540done:
1541        kfree(tmp);
1542        kfree(buf);
1543        return ret;
1544}
1545
1546static int usbdux_alloc_usb_buffers(struct comedi_device *dev)
1547{
1548        struct usb_device *usb = comedi_to_usb_dev(dev);
1549        struct usbdux_private *devpriv = dev->private;
1550        struct urb *urb;
1551        int i;
1552
1553        devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
1554        devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
1555        devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1556        devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(void *),
1557                                   GFP_KERNEL);
1558        devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(void *),
1559                                   GFP_KERNEL);
1560        if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
1561            !devpriv->ai_urbs || !devpriv->ao_urbs)
1562                return -ENOMEM;
1563
1564        for (i = 0; i < devpriv->n_ai_urbs; i++) {
1565                /* one frame: 1ms */
1566                urb = usb_alloc_urb(1, GFP_KERNEL);
1567                if (!urb)
1568                        return -ENOMEM;
1569                devpriv->ai_urbs[i] = urb;
1570
1571                urb->dev = usb;
1572                urb->context = dev;
1573                urb->pipe = usb_rcvisocpipe(usb, 6);
1574                urb->transfer_flags = URB_ISO_ASAP;
1575                urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1576                if (!urb->transfer_buffer)
1577                        return -ENOMEM;
1578
1579                urb->complete = usbduxsub_ai_isoc_irq;
1580                urb->number_of_packets = 1;
1581                urb->transfer_buffer_length = SIZEINBUF;
1582                urb->iso_frame_desc[0].offset = 0;
1583                urb->iso_frame_desc[0].length = SIZEINBUF;
1584        }
1585
1586        for (i = 0; i < devpriv->n_ao_urbs; i++) {
1587                /* one frame: 1ms */
1588                urb = usb_alloc_urb(1, GFP_KERNEL);
1589                if (!urb)
1590                        return -ENOMEM;
1591                devpriv->ao_urbs[i] = urb;
1592
1593                urb->dev = usb;
1594                urb->context = dev;
1595                urb->pipe = usb_sndisocpipe(usb, 2);
1596                urb->transfer_flags = URB_ISO_ASAP;
1597                urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1598                if (!urb->transfer_buffer)
1599                        return -ENOMEM;
1600
1601                urb->complete = usbduxsub_ao_isoc_irq;
1602                urb->number_of_packets = 1;
1603                urb->transfer_buffer_length = SIZEOUTBUF;
1604                urb->iso_frame_desc[0].offset = 0;
1605                urb->iso_frame_desc[0].length = SIZEOUTBUF;
1606                if (devpriv->high_speed)
1607                        urb->interval = 8;      /* uframes */
1608                else
1609                        urb->interval = 1;      /* frames */
1610        }
1611
1612        /* pwm */
1613        if (devpriv->pwm_buf_sz) {
1614                urb = usb_alloc_urb(0, GFP_KERNEL);
1615                if (!urb)
1616                        return -ENOMEM;
1617                devpriv->pwm_urb = urb;
1618
1619                /* max bulk ep size in high speed */
1620                urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
1621                                               GFP_KERNEL);
1622                if (!urb->transfer_buffer)
1623                        return -ENOMEM;
1624        }
1625
1626        return 0;
1627}
1628
1629static void usbdux_free_usb_buffers(struct comedi_device *dev)
1630{
1631        struct usbdux_private *devpriv = dev->private;
1632        struct urb *urb;
1633        int i;
1634
1635        urb = devpriv->pwm_urb;
1636        if (urb) {
1637                kfree(urb->transfer_buffer);
1638                usb_free_urb(urb);
1639        }
1640        if (devpriv->ao_urbs) {
1641                for (i = 0; i < devpriv->n_ao_urbs; i++) {
1642                        urb = devpriv->ao_urbs[i];
1643                        if (urb) {
1644                                kfree(urb->transfer_buffer);
1645                                usb_free_urb(urb);
1646                        }
1647                }
1648                kfree(devpriv->ao_urbs);
1649        }
1650        if (devpriv->ai_urbs) {
1651                for (i = 0; i < devpriv->n_ai_urbs; i++) {
1652                        urb = devpriv->ai_urbs[i];
1653                        if (urb) {
1654                                kfree(urb->transfer_buffer);
1655                                usb_free_urb(urb);
1656                        }
1657                }
1658                kfree(devpriv->ai_urbs);
1659        }
1660        kfree(devpriv->insn_buf);
1661        kfree(devpriv->in_buf);
1662        kfree(devpriv->dux_commands);
1663}
1664
1665static int usbdux_auto_attach(struct comedi_device *dev,
1666                              unsigned long context_unused)
1667{
1668        struct usb_interface *intf = comedi_to_usb_interface(dev);
1669        struct usb_device *usb = comedi_to_usb_dev(dev);
1670        struct usbdux_private *devpriv;
1671        struct comedi_subdevice *s;
1672        int ret;
1673
1674        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1675        if (!devpriv)
1676                return -ENOMEM;
1677
1678        sema_init(&devpriv->sem, 1);
1679
1680        usb_set_intfdata(intf, devpriv);
1681
1682        devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
1683        if (devpriv->high_speed) {
1684                devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
1685                devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
1686                devpriv->pwm_buf_sz = 512;
1687        } else {
1688                devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
1689                devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
1690        }
1691
1692        ret = usbdux_alloc_usb_buffers(dev);
1693        if (ret)
1694                return ret;
1695
1696        /* setting to alternate setting 3: enabling iso ep and bulk ep. */
1697        ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
1698                                3);
1699        if (ret < 0) {
1700                dev_err(dev->class_dev,
1701                        "could not set alternate setting 3 in high speed\n");
1702                return ret;
1703        }
1704
1705        ret = comedi_load_firmware(dev, &usb->dev, USBDUX_FIRMWARE,
1706                                   usbdux_firmware_upload, 0);
1707        if (ret < 0)
1708                return ret;
1709
1710        ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4);
1711        if (ret)
1712                return ret;
1713
1714        /* Analog Input subdevice */
1715        s = &dev->subdevices[0];
1716        dev->read_subdev = s;
1717        s->type         = COMEDI_SUBD_AI;
1718        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
1719        s->n_chan       = 8;
1720        s->maxdata      = 0x0fff;
1721        s->len_chanlist = 8;
1722        s->range_table  = &range_usbdux_ai_range;
1723        s->insn_read    = usbdux_ai_insn_read;
1724        s->do_cmdtest   = usbdux_ai_cmdtest;
1725        s->do_cmd       = usbdux_ai_cmd;
1726        s->cancel       = usbdux_ai_cancel;
1727
1728        /* Analog Output subdevice */
1729        s = &dev->subdevices[1];
1730        dev->write_subdev = s;
1731        s->type         = COMEDI_SUBD_AO;
1732        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1733        s->n_chan       = USBDUX_NUM_AO_CHAN;
1734        s->maxdata      = 0x0fff;
1735        s->len_chanlist = s->n_chan;
1736        s->range_table  = &range_usbdux_ao_range;
1737        s->do_cmdtest   = usbdux_ao_cmdtest;
1738        s->do_cmd       = usbdux_ao_cmd;
1739        s->cancel       = usbdux_ao_cancel;
1740        s->insn_read    = usbdux_ao_insn_read;
1741        s->insn_write   = usbdux_ao_insn_write;
1742
1743        /* Digital I/O subdevice */
1744        s = &dev->subdevices[2];
1745        s->type         = COMEDI_SUBD_DIO;
1746        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1747        s->n_chan       = 8;
1748        s->maxdata      = 1;
1749        s->range_table  = &range_digital;
1750        s->insn_bits    = usbdux_dio_insn_bits;
1751        s->insn_config  = usbdux_dio_insn_config;
1752
1753        /* Counter subdevice */
1754        s = &dev->subdevices[3];
1755        s->type         = COMEDI_SUBD_COUNTER;
1756        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1757        s->n_chan       = 4;
1758        s->maxdata      = 0xffff;
1759        s->insn_read    = usbdux_counter_read;
1760        s->insn_write   = usbdux_counter_write;
1761        s->insn_config  = usbdux_counter_config;
1762
1763        if (devpriv->high_speed) {
1764                /* PWM subdevice */
1765                s = &dev->subdevices[4];
1766                s->type         = COMEDI_SUBD_PWM;
1767                s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
1768                s->n_chan       = 8;
1769                s->maxdata      = devpriv->pwm_buf_sz;
1770                s->insn_write   = usbdux_pwm_write;
1771                s->insn_config  = usbdux_pwm_config;
1772
1773                usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1774        }
1775
1776        return 0;
1777}
1778
1779static void usbdux_detach(struct comedi_device *dev)
1780{
1781        struct usb_interface *intf = comedi_to_usb_interface(dev);
1782        struct usbdux_private *devpriv = dev->private;
1783
1784        usb_set_intfdata(intf, NULL);
1785
1786        if (!devpriv)
1787                return;
1788
1789        down(&devpriv->sem);
1790
1791        /* force unlink all urbs */
1792        usbdux_pwm_stop(dev, 1);
1793        usbdux_ao_stop(dev, 1);
1794        usbdux_ai_stop(dev, 1);
1795
1796        usbdux_free_usb_buffers(dev);
1797
1798        up(&devpriv->sem);
1799}
1800
1801static struct comedi_driver usbdux_driver = {
1802        .driver_name    = "usbdux",
1803        .module         = THIS_MODULE,
1804        .auto_attach    = usbdux_auto_attach,
1805        .detach         = usbdux_detach,
1806};
1807
1808static int usbdux_usb_probe(struct usb_interface *intf,
1809                            const struct usb_device_id *id)
1810{
1811        return comedi_usb_auto_config(intf, &usbdux_driver, 0);
1812}
1813
1814static const struct usb_device_id usbdux_usb_table[] = {
1815        { USB_DEVICE(0x13d8, 0x0001) },
1816        { USB_DEVICE(0x13d8, 0x0002) },
1817        { }
1818};
1819MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
1820
1821static struct usb_driver usbdux_usb_driver = {
1822        .name           = "usbdux",
1823        .probe          = usbdux_usb_probe,
1824        .disconnect     = comedi_usb_auto_unconfig,
1825        .id_table       = usbdux_usb_table,
1826};
1827module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
1828
1829MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1830MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");
1831MODULE_LICENSE("GPL");
1832MODULE_FIRMWARE(USBDUX_FIRMWARE);
1833