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