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