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