linux/drivers/staging/comedi/drivers/usbduxsigma.c
<<
>>
Prefs
   1/*
   2 * usbduxsigma.c
   3 * Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16/*
  17 * Driver: usbduxsigma
  18 * Description: University of Stirling USB DAQ & INCITE Technology Limited
  19 * Devices: (ITL) USB-DUX [usbduxsigma]
  20 * Author: Bernd Porr <BerndPorr@f2s.com>
  21 * Updated: 8 Nov 2011
  22 * Status: testing
  23 */
  24
  25/*
  26 * I must give credit here to Chris Baugher who
  27 * wrote the driver for AT-MIO-16d. I used some parts of this
  28 * driver. I also must give credits to David Brownell
  29 * who supported me with the USB development.
  30 *
  31 * Note: the raw data from the A/D converter is 24 bit big endian
  32 * anything else is little endian to/from the dux board
  33 *
  34 *
  35 * Revision history:
  36 *   0.1: initial version
  37 *   0.2: all basic functions implemented, digital I/O only for one port
  38 *   0.3: proper vendor ID and driver name
  39 *   0.4: fixed D/A voltage range
  40 *   0.5: various bug fixes, health check at startup
  41 *   0.6: corrected wrong input range
  42 */
  43
  44#include <linux/kernel.h>
  45#include <linux/module.h>
  46#include <linux/init.h>
  47#include <linux/slab.h>
  48#include <linux/input.h>
  49#include <linux/usb.h>
  50#include <linux/fcntl.h>
  51#include <linux/compiler.h>
  52
  53#include "comedi_fc.h"
  54#include "../comedidev.h"
  55
  56/* timeout for the USB-transfer in ms*/
  57#define BULK_TIMEOUT 1000
  58
  59/* constants for "firmware" upload and download */
  60#define FIRMWARE                "usbduxsigma_firmware.bin"
  61#define FIRMWARE_MAX_LEN        0x4000
  62#define USBDUXSUB_FIRMWARE      0xa0
  63#define VENDOR_DIR_IN           0xc0
  64#define VENDOR_DIR_OUT          0x40
  65
  66/* internal addresses of the 8051 processor */
  67#define USBDUXSUB_CPUCS 0xE600
  68
  69/* USB endpoints */
  70#define USBDUXSIGMA_CMD_OUT_EP          1       /* command output */
  71#define USBDUXSIGMA_ISO_OUT_EP          2       /* analog output ISO/IRQ */
  72#define USBDUXSIGMA_PWM_OUT_EP          4       /* pwm output */
  73#define USBDUXSIGMA_ISO_IN_EP           6       /* analog input ISO/IRQ */
  74#define USBDUXSIGMA_CMD_IN_EP           8       /* command input */
  75
  76/* 300Hz max frequ under PWM */
  77#define MIN_PWM_PERIOD  ((long)(1E9/300))
  78
  79/* Default PWM frequency */
  80#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
  81
  82/* Number of channels (16 AD and offset)*/
  83#define NUMCHANNELS 16
  84
  85#define USBDUXSIGMA_NUM_AO_CHAN         4
  86
  87/* Size of one A/D value */
  88#define SIZEADIN          ((sizeof(int32_t)))
  89
  90/*
  91 * Size of the async input-buffer IN BYTES, the DIO state is transmitted
  92 * as the first byte.
  93 */
  94#define SIZEINBUF         (((NUMCHANNELS+1)*SIZEADIN))
  95
  96/* 16 bytes. */
  97#define SIZEINSNBUF       16
  98
  99/* Number of DA channels */
 100#define NUMOUTCHANNELS    8
 101
 102/* size of one value for the D/A converter: channel and value */
 103#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(int16_t)))
 104
 105/*
 106 * Size of the output-buffer in bytes
 107 * Actually only the first 4 triplets are used but for the
 108 * high speed mode we need to pad it to 8 (microframes).
 109 */
 110#define SIZEOUTBUF         ((8*SIZEDAOUT))
 111
 112/*
 113 * Size of the buffer for the dux commands: just now max size is determined
 114 * by the analogue out + command byte + panic bytes...
 115 */
 116#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
 117
 118/* Number of in-URBs which receive the data: min=2 */
 119#define NUMOFINBUFFERSFULL     5
 120
 121/* Number of out-URBs which send the data: min=2 */
 122#define NUMOFOUTBUFFERSFULL    5
 123
 124/* Number of in-URBs which receive the data: min=5 */
 125/* must have more buffers due to buggy USB ctr */
 126#define NUMOFINBUFFERSHIGH     10
 127
 128/* Number of out-URBs which send the data: min=5 */
 129/* must have more buffers due to buggy USB ctr */
 130#define NUMOFOUTBUFFERSHIGH    10
 131
 132/* number of retries to get the right dux command */
 133#define RETRIES 10
 134
 135/* bulk transfer commands to usbduxsigma */
 136#define USBBUXSIGMA_AD_CMD              0
 137#define USBDUXSIGMA_DA_CMD              1
 138#define USBDUXSIGMA_DIO_CFG_CMD         2
 139#define USBDUXSIGMA_DIO_BITS_CMD        3
 140#define USBDUXSIGMA_SINGLE_AD_CMD       4
 141#define USBDUXSIGMA_PWM_ON_CMD          7
 142#define USBDUXSIGMA_PWM_OFF_CMD         8
 143
 144static const struct comedi_lrange usbduxsigma_ai_range = {
 145        1, {
 146                BIP_RANGE(2.65 / 2.0)
 147        }
 148};
 149
 150struct usbduxsigma_private {
 151        /* actual number of in-buffers */
 152        int n_ai_urbs;
 153        /* actual number of out-buffers */
 154        int n_ao_urbs;
 155        /* ISO-transfer handling: buffers */
 156        struct urb **ai_urbs;
 157        struct urb **ao_urbs;
 158        /* pwm-transfer handling */
 159        struct urb *pwm_urb;
 160        /* PWM period */
 161        unsigned int pwm_period;
 162        /* PWM internal delay for the GPIF in the FX2 */
 163        uint8_t pwm_delay;
 164        /* size of the PWM buffer which holds the bit pattern */
 165        int pwm_buf_sz;
 166        /* input buffer for the ISO-transfer */
 167        int32_t *in_buf;
 168        /* input buffer for single insn */
 169        int8_t *insn_buf;
 170
 171        unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN];
 172
 173        unsigned high_speed:1;
 174        unsigned ai_cmd_running:1;
 175        unsigned ai_continuous:1;
 176        unsigned ao_cmd_running:1;
 177        unsigned ao_continuous:1;
 178        unsigned pwm_cmd_running:1;
 179
 180        /* number of samples to acquire */
 181        int ai_sample_count;
 182        int ao_sample_count;
 183        /* time between samples in units of the timer */
 184        unsigned int ai_timer;
 185        unsigned int ao_timer;
 186        /* counter between acquisitions */
 187        unsigned int ai_counter;
 188        unsigned int ao_counter;
 189        /* interval in frames/uframes */
 190        unsigned int ai_interval;
 191        /* D/A commands */
 192        uint8_t *dac_commands;
 193        /* commands */
 194        uint8_t *dux_commands;
 195        struct semaphore sem;
 196};
 197
 198static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink)
 199{
 200        struct usbduxsigma_private *devpriv = dev->private;
 201
 202        if (do_unlink) {
 203                int i;
 204
 205                for (i = 0; i < devpriv->n_ai_urbs; i++) {
 206                        if (devpriv->ai_urbs[i])
 207                                usb_kill_urb(devpriv->ai_urbs[i]);
 208                }
 209        }
 210
 211        devpriv->ai_cmd_running = 0;
 212}
 213
 214static int usbduxsigma_ai_cancel(struct comedi_device *dev,
 215                                 struct comedi_subdevice *s)
 216{
 217        struct usbduxsigma_private *devpriv = dev->private;
 218
 219        down(&devpriv->sem);
 220        /* unlink only if it is really running */
 221        usbduxsigma_ai_stop(dev, devpriv->ai_cmd_running);
 222        up(&devpriv->sem);
 223
 224        return 0;
 225}
 226
 227static void usbduxsigma_ai_urb_complete(struct urb *urb)
 228{
 229        struct comedi_device *dev = urb->context;
 230        struct usbduxsigma_private *devpriv = dev->private;
 231        struct comedi_subdevice *s = dev->read_subdev;
 232        unsigned int dio_state;
 233        int32_t val;
 234        int ret;
 235        int i;
 236
 237        /* first we test if something unusual has just happened */
 238        switch (urb->status) {
 239        case 0:
 240                /* copy the result in the transfer buffer */
 241                memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
 242                break;
 243        case -EILSEQ:
 244                /*
 245                 * error in the ISOchronous data
 246                 * we don't copy the data into the transfer buffer
 247                 * and recycle the last data byte
 248                 */
 249                dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
 250
 251                break;
 252
 253        case -ECONNRESET:
 254        case -ENOENT:
 255        case -ESHUTDOWN:
 256        case -ECONNABORTED:
 257                /* happens after an unlink command */
 258                if (devpriv->ai_cmd_running) {
 259                        usbduxsigma_ai_stop(dev, 0);    /* w/o unlink */
 260                        /* we are still running a command, tell comedi */
 261                        s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
 262                        comedi_event(dev, s);
 263                }
 264                return;
 265
 266        default:
 267                /*
 268                 * a real error on the bus
 269                 * pass error to comedi if we are really running a command
 270                 */
 271                if (devpriv->ai_cmd_running) {
 272                        dev_err(dev->class_dev,
 273                                "%s: non-zero urb status (%d)\n",
 274                                __func__, urb->status);
 275                        usbduxsigma_ai_stop(dev, 0);    /* w/o unlink */
 276                        s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
 277                        comedi_event(dev, s);
 278                }
 279                return;
 280        }
 281
 282        if (unlikely(!devpriv->ai_cmd_running))
 283                return;
 284
 285        urb->dev = comedi_to_usb_dev(dev);
 286
 287        ret = usb_submit_urb(urb, GFP_ATOMIC);
 288        if (unlikely(ret < 0)) {
 289                dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
 290                        __func__, ret);
 291                if (ret == -EL2NSYNC)
 292                        dev_err(dev->class_dev,
 293                                "buggy USB host controller or bug in IRQ handler\n");
 294                usbduxsigma_ai_stop(dev, 0);    /* w/o unlink */
 295                s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
 296                comedi_event(dev, s);
 297                return;
 298        }
 299
 300        /* get the state of the dio pins to allow external trigger */
 301        dio_state = be32_to_cpu(devpriv->in_buf[0]);
 302
 303        devpriv->ai_counter--;
 304        if (likely(devpriv->ai_counter > 0))
 305                return;
 306
 307        /* timer zero, transfer measurements to comedi */
 308        devpriv->ai_counter = devpriv->ai_timer;
 309
 310        if (!devpriv->ai_continuous) {
 311                /* not continuous, fixed number of samples */
 312                devpriv->ai_sample_count--;
 313                if (devpriv->ai_sample_count < 0) {
 314                        usbduxsigma_ai_stop(dev, 0);    /* w/o unlink */
 315                        /* acquistion is over, tell comedi */
 316                        s->async->events |= COMEDI_CB_EOA;
 317                        comedi_event(dev, s);
 318                        return;
 319                }
 320        }
 321
 322        /* get the data from the USB bus and hand it over to comedi */
 323        for (i = 0; i < s->async->cmd.chanlist_len; i++) {
 324                /* transfer data, note first byte is the DIO state */
 325                val = be32_to_cpu(devpriv->in_buf[i+1]);
 326                val &= 0x00ffffff;      /* strip status byte */
 327                val ^= 0x00800000;      /* convert to unsigned */
 328
 329                ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
 330                if (unlikely(ret == 0)) {
 331                        /* buffer overflow */
 332                        usbduxsigma_ai_stop(dev, 0);    /* w/o unlink */
 333                        return;
 334                }
 335        }
 336        /* tell comedi that data is there */
 337        s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
 338        comedi_event(dev, s);
 339}
 340
 341static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink)
 342{
 343        struct usbduxsigma_private *devpriv = dev->private;
 344
 345        if (do_unlink) {
 346                int i;
 347
 348                for (i = 0; i < devpriv->n_ao_urbs; i++) {
 349                        if (devpriv->ao_urbs[i])
 350                                usb_kill_urb(devpriv->ao_urbs[i]);
 351                }
 352        }
 353
 354        devpriv->ao_cmd_running = 0;
 355}
 356
 357static int usbduxsigma_ao_cancel(struct comedi_device *dev,
 358                                 struct comedi_subdevice *s)
 359{
 360        struct usbduxsigma_private *devpriv = dev->private;
 361
 362        down(&devpriv->sem);
 363        /* unlink only if it is really running */
 364        usbduxsigma_ao_stop(dev, devpriv->ao_cmd_running);
 365        up(&devpriv->sem);
 366
 367        return 0;
 368}
 369
 370static void usbduxsigma_ao_urb_complete(struct urb *urb)
 371{
 372        struct comedi_device *dev = urb->context;
 373        struct usbduxsigma_private *devpriv = dev->private;
 374        struct comedi_subdevice *s = dev->write_subdev;
 375        uint8_t *datap;
 376        int len;
 377        int ret;
 378        int i;
 379
 380        switch (urb->status) {
 381        case 0:
 382                /* success */
 383                break;
 384
 385        case -ECONNRESET:
 386        case -ENOENT:
 387        case -ESHUTDOWN:
 388        case -ECONNABORTED:
 389                /* happens after an unlink command */
 390                if (devpriv->ao_cmd_running) {
 391                        usbduxsigma_ao_stop(dev, 0);    /* w/o unlink */
 392                        s->async->events |= COMEDI_CB_EOA;
 393                        comedi_event(dev, s);
 394                }
 395                return;
 396
 397        default:
 398                /* a real error */
 399                if (devpriv->ao_cmd_running) {
 400                        dev_err(dev->class_dev,
 401                                "%s: non-zero urb status (%d)\n",
 402                                __func__, urb->status);
 403                        usbduxsigma_ao_stop(dev, 0);    /* w/o unlink */
 404                        s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
 405                        comedi_event(dev, s);
 406                }
 407                return;
 408        }
 409
 410        if (!devpriv->ao_cmd_running)
 411                return;
 412
 413        devpriv->ao_counter--;
 414        if ((int)devpriv->ao_counter <= 0) {
 415                /* timer zero, transfer from comedi */
 416                devpriv->ao_counter = devpriv->ao_timer;
 417
 418                if (!devpriv->ao_continuous) {
 419                        /* not continuous, fixed number of samples */
 420                        devpriv->ao_sample_count--;
 421                        if (devpriv->ao_sample_count < 0) {
 422                                usbduxsigma_ao_stop(dev, 0);    /* w/o unlink */
 423                                /* acquistion is over, tell comedi */
 424                                s->async->events |= COMEDI_CB_EOA;
 425                                comedi_event(dev, s);
 426                                return;
 427                        }
 428                }
 429
 430                /* transmit data to the USB bus */
 431                datap = urb->transfer_buffer;
 432                len = s->async->cmd.chanlist_len;
 433                *datap++ = len;
 434                for (i = 0; i < len; i++) {
 435                        unsigned int chan = devpriv->dac_commands[i];
 436                        short val;
 437
 438                        ret = comedi_buf_get(s->async, &val);
 439                        if (ret < 0) {
 440                                dev_err(dev->class_dev, "buffer underflow\n");
 441                                s->async->events |= (COMEDI_CB_EOA |
 442                                                     COMEDI_CB_OVERFLOW);
 443                        }
 444                        *datap++ = val;
 445                        *datap++ = chan;
 446                        devpriv->ao_readback[chan] = val;
 447
 448                        s->async->events |= COMEDI_CB_BLOCK;
 449                        comedi_event(dev, s);
 450                }
 451        }
 452
 453        urb->transfer_buffer_length = SIZEOUTBUF;
 454        urb->dev = comedi_to_usb_dev(dev);
 455        urb->status = 0;
 456        if (devpriv->high_speed)
 457                urb->interval = 8;      /* uframes */
 458        else
 459                urb->interval = 1;      /* frames */
 460        urb->number_of_packets = 1;
 461        urb->iso_frame_desc[0].offset = 0;
 462        urb->iso_frame_desc[0].length = SIZEOUTBUF;
 463        urb->iso_frame_desc[0].status = 0;
 464        ret = usb_submit_urb(urb, GFP_ATOMIC);
 465        if (ret < 0) {
 466                dev_err(dev->class_dev,
 467                        "%s: urb resubmit failed (%d)\n",
 468                        __func__, ret);
 469                if (ret == EL2NSYNC)
 470                        dev_err(dev->class_dev,
 471                                "buggy USB host controller or bug in IRQ handler\n");
 472                usbduxsigma_ao_stop(dev, 0);    /* w/o unlink */
 473                s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
 474                comedi_event(dev, s);
 475        }
 476}
 477
 478static int usbduxsigma_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 usbduxsigma_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 usbduxsigma_chans_to_interval(int num_chan)
 508{
 509        if (num_chan <= 2)
 510                return 2;       /* 4kHz */
 511        if (num_chan <= 8)
 512                return 4;       /* 2kHz */
 513        return 8;               /* 1kHz */
 514}
 515
 516static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
 517                                  struct comedi_subdevice *s,
 518                                  struct comedi_cmd *cmd)
 519{
 520        struct usbduxsigma_private *devpriv = dev->private;
 521        int high_speed = devpriv->high_speed;
 522        int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
 523        int err = 0;
 524
 525        /* Step 1 : check if triggers are trivially valid */
 526
 527        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 528        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
 529        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 530        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 531        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 532
 533        if (err)
 534                return 1;
 535
 536        /* Step 2a : make sure trigger sources are unique */
 537
 538        err |= cfc_check_trigger_is_unique(cmd->start_src);
 539        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 540
 541        /* Step 2b : and mutually compatible */
 542
 543        if (err)
 544                return 2;
 545
 546        /* Step 3: check if arguments are trivially valid */
 547
 548        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 549
 550        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 551                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 552
 553        if (cmd->scan_begin_src == TRIG_TIMER) {
 554                unsigned int tmp;
 555
 556                if (high_speed) {
 557                        /*
 558                         * In high speed mode microframes are possible.
 559                         * However, during one microframe we can roughly
 560                         * sample two channels. Thus, the more channels
 561                         * are in the channel list the more time we need.
 562                         */
 563                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 564                                                (1000000 / 8 * interval));
 565
 566                        tmp = (cmd->scan_begin_arg / 125000) * 125000;
 567                } else {
 568                        /* full speed */
 569                        /* 1kHz scans every USB frame */
 570                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 571                                                         1000000);
 572
 573                        tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
 574                }
 575                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
 576        }
 577
 578        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 579
 580        if (cmd->stop_src == TRIG_COUNT) {
 581                /* any count is allowed */
 582        } else {
 583                /* TRIG_NONE */
 584                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 585        }
 586
 587        if (err)
 588                return 3;
 589
 590        /* Step 4: fix up any arguments */
 591
 592        if (high_speed) {
 593                /*
 594                 * every 2 channels get a time window of 125us. Thus, if we
 595                 * sample all 16 channels we need 1ms. If we sample only one
 596                 * channel we need only 125us
 597                 */
 598                devpriv->ai_interval = interval;
 599                devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
 600        } else {
 601                /* interval always 1ms */
 602                devpriv->ai_interval = 1;
 603                devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
 604        }
 605        if (devpriv->ai_timer < 1)
 606                err |= -EINVAL;
 607
 608        if (cmd->stop_src == TRIG_COUNT) {
 609                /* data arrives as one packet */
 610                devpriv->ai_sample_count = cmd->stop_arg;
 611                devpriv->ai_continuous = 0;
 612        } else {
 613                /* continuous acquisition */
 614                devpriv->ai_continuous = 1;
 615                devpriv->ai_sample_count = 0;
 616        }
 617
 618        if (err)
 619                return 4;
 620
 621        return 0;
 622}
 623
 624/*
 625 * creates the ADC command for the MAX1271
 626 * range is the range value from comedi
 627 */
 628static void create_adc_command(unsigned int chan,
 629                               uint8_t *muxsg0,
 630                               uint8_t *muxsg1)
 631{
 632        if (chan < 8)
 633                (*muxsg0) = (*muxsg0) | (1 << chan);
 634        else if (chan < 16)
 635                (*muxsg1) = (*muxsg1) | (1 << (chan-8));
 636}
 637
 638static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type)
 639{
 640        struct usb_device *usb = comedi_to_usb_dev(dev);
 641        struct usbduxsigma_private *devpriv = dev->private;
 642        int nsent;
 643
 644        devpriv->dux_commands[0] = cmd_type;
 645
 646        return usb_bulk_msg(usb, usb_sndbulkpipe(usb, USBDUXSIGMA_CMD_OUT_EP),
 647                            devpriv->dux_commands, SIZEOFDUXBUFFER,
 648                            &nsent, BULK_TIMEOUT);
 649}
 650
 651static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command)
 652{
 653        struct usb_device *usb = comedi_to_usb_dev(dev);
 654        struct usbduxsigma_private *devpriv = dev->private;
 655        int nrec;
 656        int ret;
 657        int i;
 658
 659        for (i = 0; i < RETRIES; i++) {
 660                ret = usb_bulk_msg(usb,
 661                                   usb_rcvbulkpipe(usb, USBDUXSIGMA_CMD_IN_EP),
 662                                   devpriv->insn_buf, SIZEINSNBUF,
 663                                   &nrec, BULK_TIMEOUT);
 664                if (ret < 0)
 665                        return ret;
 666
 667                if (devpriv->insn_buf[0] == command)
 668                        return 0;
 669        }
 670        /*
 671         * This is only reached if the data has been requested a
 672         * couple of times and the command was not received.
 673         */
 674        return -EFAULT;
 675}
 676
 677static int usbduxsigma_ai_inttrig(struct comedi_device *dev,
 678                                  struct comedi_subdevice *s,
 679                                  unsigned int trignum)
 680{
 681        struct usbduxsigma_private *devpriv = dev->private;
 682        int ret;
 683
 684        if (trignum != 0)
 685                return -EINVAL;
 686
 687        down(&devpriv->sem);
 688        if (!devpriv->ai_cmd_running) {
 689                ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
 690                                              devpriv->n_ai_urbs, 1);
 691                if (ret < 0) {
 692                        up(&devpriv->sem);
 693                        return ret;
 694                }
 695                devpriv->ai_cmd_running = 1;
 696                s->async->inttrig = NULL;
 697        }
 698        up(&devpriv->sem);
 699
 700        return 1;
 701}
 702
 703static int usbduxsigma_ai_cmd(struct comedi_device *dev,
 704                              struct comedi_subdevice *s)
 705{
 706        struct usbduxsigma_private *devpriv = dev->private;
 707        struct comedi_cmd *cmd = &s->async->cmd;
 708        unsigned int len = cmd->chanlist_len;
 709        uint8_t muxsg0 = 0;
 710        uint8_t muxsg1 = 0;
 711        uint8_t sysred = 0;
 712        int ret;
 713        int i;
 714
 715        down(&devpriv->sem);
 716
 717        /* set current channel of the running acquisition to zero */
 718        s->async->cur_chan = 0;
 719        for (i = 0; i < len; i++) {
 720                unsigned int chan  = CR_CHAN(cmd->chanlist[i]);
 721
 722                create_adc_command(chan, &muxsg0, &muxsg1);
 723        }
 724
 725        devpriv->dux_commands[1] = len;  /* num channels per time step */
 726        devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
 727        devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
 728        devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
 729        devpriv->dux_commands[5] = muxsg0;
 730        devpriv->dux_commands[6] = muxsg1;
 731        devpriv->dux_commands[7] = sysred;
 732
 733        ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
 734        if (ret < 0) {
 735                up(&devpriv->sem);
 736                return ret;
 737        }
 738
 739        devpriv->ai_counter = devpriv->ai_timer;
 740
 741        if (cmd->start_src == TRIG_NOW) {
 742                /* enable this acquisition operation */
 743                ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
 744                                              devpriv->n_ai_urbs, 1);
 745                if (ret < 0) {
 746                        up(&devpriv->sem);
 747                        return ret;
 748                }
 749                s->async->inttrig = NULL;
 750                devpriv->ai_cmd_running = 1;
 751        } else {        /* TRIG_INT */
 752                /* wait for an internal signal and submit the urbs later */
 753                s->async->inttrig = usbduxsigma_ai_inttrig;
 754        }
 755
 756        up(&devpriv->sem);
 757
 758        return 0;
 759}
 760
 761static int usbduxsigma_ai_insn_read(struct comedi_device *dev,
 762                                    struct comedi_subdevice *s,
 763                                    struct comedi_insn *insn,
 764                                    unsigned int *data)
 765{
 766        struct usbduxsigma_private *devpriv = dev->private;
 767        unsigned int chan = CR_CHAN(insn->chanspec);
 768        uint8_t muxsg0 = 0;
 769        uint8_t muxsg1 = 0;
 770        uint8_t sysred = 0;
 771        int ret;
 772        int i;
 773
 774        down(&devpriv->sem);
 775        if (devpriv->ai_cmd_running) {
 776                up(&devpriv->sem);
 777                return -EBUSY;
 778        }
 779
 780        create_adc_command(chan, &muxsg0, &muxsg1);
 781
 782        /* Mode 0 is used to get a single conversion on demand */
 783        devpriv->dux_commands[1] = 0x16; /* CONFIG0: chopper on */
 784        devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
 785        devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
 786        devpriv->dux_commands[4] = muxsg0;
 787        devpriv->dux_commands[5] = muxsg1;
 788        devpriv->dux_commands[6] = sysred;
 789
 790        /* adc commands */
 791        ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
 792        if (ret < 0) {
 793                up(&devpriv->sem);
 794                return ret;
 795        }
 796
 797        for (i = 0; i < insn->n; i++) {
 798                int32_t val;
 799
 800                ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
 801                if (ret < 0) {
 802                        up(&devpriv->sem);
 803                        return ret;
 804                }
 805
 806                /* 32 bits big endian from the A/D converter */
 807                val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf) + 1)));
 808                val &= 0x00ffffff;      /* strip status byte */
 809                val ^= 0x00800000;      /* convert to unsigned */
 810
 811                data[i] = val;
 812        }
 813        up(&devpriv->sem);
 814
 815        return insn->n;
 816}
 817
 818static int usbduxsigma_ao_insn_read(struct comedi_device *dev,
 819                                    struct comedi_subdevice *s,
 820                                    struct comedi_insn *insn,
 821                                    unsigned int *data)
 822{
 823        struct usbduxsigma_private *devpriv = dev->private;
 824        unsigned int chan = CR_CHAN(insn->chanspec);
 825        int i;
 826
 827        down(&devpriv->sem);
 828        for (i = 0; i < insn->n; i++)
 829                data[i] = devpriv->ao_readback[chan];
 830        up(&devpriv->sem);
 831
 832        return insn->n;
 833}
 834
 835static int usbduxsigma_ao_insn_write(struct comedi_device *dev,
 836                                     struct comedi_subdevice *s,
 837                                     struct comedi_insn *insn,
 838                                     unsigned int *data)
 839{
 840        struct usbduxsigma_private *devpriv = dev->private;
 841        unsigned int chan = CR_CHAN(insn->chanspec);
 842        int ret;
 843        int i;
 844
 845        down(&devpriv->sem);
 846        if (devpriv->ao_cmd_running) {
 847                up(&devpriv->sem);
 848                return -EBUSY;
 849        }
 850
 851        for (i = 0; i < insn->n; i++) {
 852                devpriv->dux_commands[1] = 1;           /* num channels */
 853                devpriv->dux_commands[2] = data[i];     /* value */
 854                devpriv->dux_commands[3] = chan;        /* channel number */
 855                ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD);
 856                if (ret < 0) {
 857                        up(&devpriv->sem);
 858                        return ret;
 859                }
 860                devpriv->ao_readback[chan] = data[i];
 861        }
 862        up(&devpriv->sem);
 863
 864        return insn->n;
 865}
 866
 867static int usbduxsigma_ao_inttrig(struct comedi_device *dev,
 868                                  struct comedi_subdevice *s,
 869                                  unsigned int trignum)
 870{
 871        struct usbduxsigma_private *devpriv = dev->private;
 872        int ret;
 873
 874        if (trignum != 0)
 875                return -EINVAL;
 876
 877        down(&devpriv->sem);
 878        if (!devpriv->ao_cmd_running) {
 879                ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
 880                                              devpriv->n_ao_urbs, 0);
 881                if (ret < 0) {
 882                        up(&devpriv->sem);
 883                        return ret;
 884                }
 885                devpriv->ao_cmd_running = 1;
 886                s->async->inttrig = NULL;
 887        }
 888        up(&devpriv->sem);
 889
 890        return 1;
 891}
 892
 893static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
 894                                  struct comedi_subdevice *s,
 895                                  struct comedi_cmd *cmd)
 896{
 897        struct usbduxsigma_private *devpriv = dev->private;
 898        int err = 0;
 899        int high_speed;
 900        unsigned int flags;
 901
 902        /* high speed conversions are not used yet */
 903        high_speed = 0;         /* (devpriv->high_speed) */
 904
 905        /* Step 1 : check if triggers are trivially valid */
 906
 907        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 908
 909        if (high_speed) {
 910                /*
 911                 * start immediately a new scan
 912                 * the sampling rate is set by the coversion rate
 913                 */
 914                flags = TRIG_FOLLOW;
 915        } else {
 916                /* start a new scan (output at once) with a timer */
 917                flags = TRIG_TIMER;
 918        }
 919        err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
 920
 921        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 922        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 923        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 924
 925        if (err) {
 926                up(&devpriv->sem);
 927                return 1;
 928        }
 929
 930        /* Step 2a : make sure trigger sources are unique */
 931
 932        err |= cfc_check_trigger_is_unique(cmd->start_src);
 933        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 934
 935        /* Step 2b : and mutually compatible */
 936
 937        if (err)
 938                return 2;
 939
 940        /* Step 3: check if arguments are trivially valid */
 941
 942        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 943
 944        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 945                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 946
 947        if (cmd->scan_begin_src == TRIG_TIMER)
 948                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 949                                                 1000000);
 950
 951        /* not used now, is for later use */
 952        if (cmd->convert_src == TRIG_TIMER)
 953                err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
 954
 955        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 956
 957        if (cmd->stop_src == TRIG_COUNT) {
 958                /* any count is allowed */
 959        } else {
 960                /* TRIG_NONE */
 961                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 962        }
 963
 964        if (err)
 965                return 3;
 966
 967        /* Step 4: fix up any arguments */
 968
 969        /* we count in timer steps */
 970        if (high_speed) {
 971                /* timing of the conversion itself: every 125 us */
 972                devpriv->ao_timer = cmd->convert_arg / 125000;
 973        } else {
 974                /*
 975                 * timing of the scan: every 1ms
 976                 * we get all channels at once
 977                 */
 978                devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
 979        }
 980        if (devpriv->ao_timer < 1)
 981                err |= -EINVAL;
 982
 983        if (cmd->stop_src == TRIG_COUNT) {
 984                /* not continuous, use counter */
 985                if (high_speed) {
 986                        /* high speed also scans everything at once */
 987                        devpriv->ao_sample_count = cmd->stop_arg *
 988                                                   cmd->scan_end_arg;
 989                } else {
 990                        /*
 991                         * There's no scan as the scan has been
 992                         * handled inside the FX2. Data arrives as
 993                         * one packet.
 994                         */
 995                        devpriv->ao_sample_count = cmd->stop_arg;
 996                }
 997                devpriv->ao_continuous = 0;
 998        } else {
 999                /* continuous acquisition */
1000                devpriv->ao_continuous = 1;
1001                devpriv->ao_sample_count = 0;
1002        }
1003
1004        if (err)
1005                return 4;
1006
1007        return 0;
1008}
1009
1010static int usbduxsigma_ao_cmd(struct comedi_device *dev,
1011                              struct comedi_subdevice *s)
1012{
1013        struct usbduxsigma_private *devpriv = dev->private;
1014        struct comedi_cmd *cmd = &s->async->cmd;
1015        int ret;
1016        int i;
1017
1018        down(&devpriv->sem);
1019
1020        /* set current channel of the running acquisition to zero */
1021        s->async->cur_chan = 0;
1022        for (i = 0; i < cmd->chanlist_len; ++i)
1023                devpriv->dac_commands[i] = CR_CHAN(cmd->chanlist[i]);
1024
1025        devpriv->ao_counter = devpriv->ao_timer;
1026
1027        if (cmd->start_src == TRIG_NOW) {
1028                /* enable this acquisition operation */
1029                ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
1030                                              devpriv->n_ao_urbs, 0);
1031                if (ret < 0) {
1032                        up(&devpriv->sem);
1033                        return ret;
1034                }
1035                s->async->inttrig = NULL;
1036                devpriv->ao_cmd_running = 1;
1037        } else {        /* TRIG_INT */
1038                /* wait for an internal signal and submit the urbs later */
1039                s->async->inttrig = usbduxsigma_ao_inttrig;
1040        }
1041
1042        up(&devpriv->sem);
1043
1044        return 0;
1045}
1046
1047static int usbduxsigma_dio_insn_config(struct comedi_device *dev,
1048                                       struct comedi_subdevice *s,
1049                                       struct comedi_insn *insn,
1050                                       unsigned int *data)
1051{
1052        unsigned int chan = CR_CHAN(insn->chanspec);
1053        unsigned int mask = 1 << chan;
1054
1055        switch (data[0]) {
1056        case INSN_CONFIG_DIO_OUTPUT:
1057                s->io_bits |= mask;
1058                break;
1059        case INSN_CONFIG_DIO_INPUT:
1060                s->io_bits &= ~mask;
1061                break;
1062        case INSN_CONFIG_DIO_QUERY:
1063                data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
1064                break;
1065        default:
1066                return -EINVAL;
1067                break;
1068        }
1069
1070        /*
1071         * We don't tell the firmware here as it would take 8 frames
1072         * to submit the information. We do it in the (*insn_bits).
1073         */
1074        return insn->n;
1075}
1076
1077static int usbduxsigma_dio_insn_bits(struct comedi_device *dev,
1078                                     struct comedi_subdevice *s,
1079                                     struct comedi_insn *insn,
1080                                     unsigned int *data)
1081{
1082        struct usbduxsigma_private *devpriv = dev->private;
1083        unsigned int mask = data[0];
1084        unsigned int bits = data[1];
1085        int ret;
1086
1087        down(&devpriv->sem);
1088
1089        s->state &= ~mask;
1090        s->state |= (bits & mask);
1091
1092        devpriv->dux_commands[1] = s->io_bits & 0xff;
1093        devpriv->dux_commands[4] = s->state & 0xff;
1094        devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
1095        devpriv->dux_commands[5] = (s->state >> 8) & 0xff;
1096        devpriv->dux_commands[3] = (s->io_bits >> 16) & 0xff;
1097        devpriv->dux_commands[6] = (s->state >> 16) & 0xff;
1098
1099        ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
1100        if (ret < 0)
1101                goto done;
1102        ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
1103        if (ret < 0)
1104                goto done;
1105
1106        s->state = devpriv->insn_buf[1] |
1107                   (devpriv->insn_buf[2] << 8) |
1108                   (devpriv->insn_buf[3] << 16);
1109
1110        data[1] = s->state;
1111        ret = insn->n;
1112
1113done:
1114        up(&devpriv->sem);
1115
1116        return ret;
1117}
1118
1119static void usbduxsigma_pwm_stop(struct comedi_device *dev, int do_unlink)
1120{
1121        struct usbduxsigma_private *devpriv = dev->private;
1122
1123        if (do_unlink) {
1124                if (devpriv->pwm_urb)
1125                        usb_kill_urb(devpriv->pwm_urb);
1126        }
1127
1128        devpriv->pwm_cmd_running = 0;
1129}
1130
1131static int usbduxsigma_pwm_cancel(struct comedi_device *dev,
1132                                  struct comedi_subdevice *s)
1133{
1134        struct usbduxsigma_private *devpriv = dev->private;
1135
1136        /* unlink only if it is really running */
1137        usbduxsigma_pwm_stop(dev, devpriv->pwm_cmd_running);
1138
1139        return usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_OFF_CMD);
1140}
1141
1142static void usbduxsigma_pwm_urb_complete(struct urb *urb)
1143{
1144        struct comedi_device *dev = urb->context;
1145        struct usbduxsigma_private *devpriv = dev->private;
1146        int ret;
1147
1148        switch (urb->status) {
1149        case 0:
1150                /* success */
1151                break;
1152
1153        case -ECONNRESET:
1154        case -ENOENT:
1155        case -ESHUTDOWN:
1156        case -ECONNABORTED:
1157                /* happens after an unlink command */
1158                if (devpriv->pwm_cmd_running)
1159                        usbduxsigma_pwm_stop(dev, 0);   /* w/o unlink */
1160                return;
1161
1162        default:
1163                /* a real error */
1164                if (devpriv->pwm_cmd_running) {
1165                        dev_err(dev->class_dev,
1166                                "%s: non-zero urb status (%d)\n",
1167                                __func__, urb->status);
1168                        usbduxsigma_pwm_stop(dev, 0);   /* w/o unlink */
1169                }
1170                return;
1171        }
1172
1173        if (!devpriv->pwm_cmd_running)
1174                return;
1175
1176        urb->transfer_buffer_length = devpriv->pwm_buf_sz;
1177        urb->dev = comedi_to_usb_dev(dev);
1178        urb->status = 0;
1179        ret = usb_submit_urb(urb, GFP_ATOMIC);
1180        if (ret < 0) {
1181                dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
1182                        __func__, ret);
1183                if (ret == EL2NSYNC)
1184                        dev_err(dev->class_dev,
1185                                "buggy USB host controller or bug in IRQ handler\n");
1186                usbduxsigma_pwm_stop(dev, 0);   /* w/o unlink */
1187        }
1188}
1189
1190static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev)
1191{
1192        struct usb_device *usb = comedi_to_usb_dev(dev);
1193        struct usbduxsigma_private *devpriv = dev->private;
1194        struct urb *urb = devpriv->pwm_urb;
1195
1196        /* in case of a resubmission after an unlink... */
1197        usb_fill_bulk_urb(urb,
1198                          usb, usb_sndbulkpipe(usb, USBDUXSIGMA_PWM_OUT_EP),
1199                          urb->transfer_buffer, devpriv->pwm_buf_sz,
1200                          usbduxsigma_pwm_urb_complete, dev);
1201
1202        return usb_submit_urb(urb, GFP_ATOMIC);
1203}
1204
1205static int usbduxsigma_pwm_period(struct comedi_device *dev,
1206                                  struct comedi_subdevice *s,
1207                                  unsigned int period)
1208{
1209        struct usbduxsigma_private *devpriv = dev->private;
1210        int fx2delay = 255;
1211
1212        if (period < MIN_PWM_PERIOD) {
1213                return -EAGAIN;
1214        } else {
1215                fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
1216                if (fx2delay > 255)
1217                        return -EAGAIN;
1218        }
1219        devpriv->pwm_delay = fx2delay;
1220        devpriv->pwm_period = period;
1221        return 0;
1222}
1223
1224static int usbduxsigma_pwm_start(struct comedi_device *dev,
1225                                 struct comedi_subdevice *s)
1226{
1227        struct usbduxsigma_private *devpriv = dev->private;
1228        int ret;
1229
1230        if (devpriv->pwm_cmd_running)
1231                return 0;
1232
1233        devpriv->dux_commands[1] = devpriv->pwm_delay;
1234        ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_ON_CMD);
1235        if (ret < 0)
1236                return ret;
1237
1238        memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
1239
1240        ret = usbduxsigma_submit_pwm_urb(dev);
1241        if (ret < 0)
1242                return ret;
1243        devpriv->pwm_cmd_running = 1;
1244
1245        return 0;
1246}
1247
1248static int usbduxsigma_pwm_pattern(struct comedi_device *dev,
1249                                   struct comedi_subdevice *s,
1250                                   unsigned int chan,
1251                                   unsigned int value,
1252                                   unsigned int sign)
1253{
1254        struct usbduxsigma_private *devpriv = dev->private;
1255        char pwm_mask = (1 << chan);    /* DIO bit for the PWM data */
1256        char sgn_mask = (16 << chan);   /* DIO bit for the sign */
1257        char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
1258        int szbuf = devpriv->pwm_buf_sz;
1259        int i;
1260
1261        for (i = 0; i < szbuf; i++) {
1262                char c = *buf;
1263
1264                c &= ~pwm_mask;
1265                if (i < value)
1266                        c |= pwm_mask;
1267                if (!sign)
1268                        c &= ~sgn_mask;
1269                else
1270                        c |= sgn_mask;
1271                *buf++ = c;
1272        }
1273        return 1;
1274}
1275
1276static int usbduxsigma_pwm_write(struct comedi_device *dev,
1277                                 struct comedi_subdevice *s,
1278                                 struct comedi_insn *insn,
1279                                 unsigned int *data)
1280{
1281        unsigned int chan = CR_CHAN(insn->chanspec);
1282
1283        /*
1284         * It doesn't make sense to support more than one value here
1285         * because it would just overwrite the PWM buffer.
1286         */
1287        if (insn->n != 1)
1288                return -EINVAL;
1289
1290        /*
1291         * The sign is set via a special INSN only, this gives us 8 bits
1292         * for normal operation, sign is 0 by default.
1293         */
1294        return usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
1295}
1296
1297static int usbduxsigma_pwm_config(struct comedi_device *dev,
1298                                  struct comedi_subdevice *s,
1299                                  struct comedi_insn *insn,
1300                                  unsigned int *data)
1301{
1302        struct usbduxsigma_private *devpriv = dev->private;
1303        unsigned int chan = CR_CHAN(insn->chanspec);
1304
1305        switch (data[0]) {
1306        case INSN_CONFIG_ARM:
1307                /*
1308                 * if not zero the PWM is limited to a certain time which is
1309                 * not supported here
1310                 */
1311                if (data[1] != 0)
1312                        return -EINVAL;
1313                return usbduxsigma_pwm_start(dev, s);
1314        case INSN_CONFIG_DISARM:
1315                return usbduxsigma_pwm_cancel(dev, s);
1316        case INSN_CONFIG_GET_PWM_STATUS:
1317                data[1] = devpriv->pwm_cmd_running;
1318                return 0;
1319        case INSN_CONFIG_PWM_SET_PERIOD:
1320                return usbduxsigma_pwm_period(dev, s, data[1]);
1321        case INSN_CONFIG_PWM_GET_PERIOD:
1322                data[1] = devpriv->pwm_period;
1323                return 0;
1324        case INSN_CONFIG_PWM_SET_H_BRIDGE:
1325                /*
1326                 * data[1] = value
1327                 * data[2] = sign (for a relay)
1328                 */
1329                return usbduxsigma_pwm_pattern(dev, s, chan,
1330                                               data[1], (data[2] != 0));
1331        case INSN_CONFIG_PWM_GET_H_BRIDGE:
1332                /* values are not kept in this driver, nothing to return */
1333                return -EINVAL;
1334        }
1335        return -EINVAL;
1336}
1337
1338static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
1339{
1340        struct usbduxsigma_private *devpriv = dev->private;
1341        uint8_t sysred;
1342        uint32_t val;
1343        int ret;
1344
1345        switch (chan) {
1346        default:
1347        case 0:
1348                sysred = 0;             /* ADC zero */
1349                break;
1350        case 1:
1351                sysred = 1;             /* ADC offset */
1352                break;
1353        case 2:
1354                sysred = 4;             /* VCC */
1355                break;
1356        case 3:
1357                sysred = 8;             /* temperature */
1358                break;
1359        case 4:
1360                sysred = 16;            /* gain */
1361                break;
1362        case 5:
1363                sysred =  32;           /* ref */
1364                break;
1365        }
1366
1367        devpriv->dux_commands[1] = 0x12; /* CONFIG0 */
1368        devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
1369        devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
1370        devpriv->dux_commands[4] = 0;
1371        devpriv->dux_commands[5] = 0;
1372        devpriv->dux_commands[6] = sysred;
1373        ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
1374        if (ret < 0)
1375                return ret;
1376
1377        ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
1378        if (ret < 0)
1379                return ret;
1380
1381        /* 32 bits big endian from the A/D converter */
1382        val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf)+1)));
1383        val &= 0x00ffffff;      /* strip status byte */
1384        val ^= 0x00800000;      /* convert to unsigned */
1385
1386        return (int)val;
1387}
1388
1389static int usbduxsigma_attach_common(struct comedi_device *dev)
1390{
1391        struct usbduxsigma_private *devpriv = dev->private;
1392        struct comedi_subdevice *s;
1393        int n_subdevs;
1394        int offset;
1395        int ret;
1396
1397        down(&devpriv->sem);
1398
1399        if (devpriv->high_speed)
1400                n_subdevs = 4;  /* with pwm */
1401        else
1402                n_subdevs = 3;  /* without pwm */
1403        ret = comedi_alloc_subdevices(dev, n_subdevs);
1404        if (ret) {
1405                up(&devpriv->sem);
1406                return ret;
1407        }
1408
1409        /* Analog Input subdevice */
1410        s = &dev->subdevices[0];
1411        dev->read_subdev = s;
1412        s->type         = COMEDI_SUBD_AI;
1413        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
1414        s->n_chan       = NUMCHANNELS;
1415        s->len_chanlist = NUMCHANNELS;
1416        s->maxdata      = 0x00ffffff;
1417        s->range_table  = &usbduxsigma_ai_range;
1418        s->insn_read    = usbduxsigma_ai_insn_read;
1419        s->do_cmdtest   = usbduxsigma_ai_cmdtest;
1420        s->do_cmd       = usbduxsigma_ai_cmd;
1421        s->cancel       = usbduxsigma_ai_cancel;
1422
1423        /* Analog Output subdevice */
1424        s = &dev->subdevices[1];
1425        dev->write_subdev = s;
1426        s->type         = COMEDI_SUBD_AO;
1427        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1428        s->n_chan       = USBDUXSIGMA_NUM_AO_CHAN;
1429        s->len_chanlist = s->n_chan;
1430        s->maxdata      = 0x00ff;
1431        s->range_table  = &range_unipolar2_5;
1432        s->insn_write   = usbduxsigma_ao_insn_write;
1433        s->insn_read    = usbduxsigma_ao_insn_read;
1434        s->do_cmdtest   = usbduxsigma_ao_cmdtest;
1435        s->do_cmd       = usbduxsigma_ao_cmd;
1436        s->cancel       = usbduxsigma_ao_cancel;
1437
1438        /* Digital I/O subdevice */
1439        s = &dev->subdevices[2];
1440        s->type         = COMEDI_SUBD_DIO;
1441        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1442        s->n_chan       = 24;
1443        s->maxdata      = 1;
1444        s->range_table  = &range_digital;
1445        s->insn_bits    = usbduxsigma_dio_insn_bits;
1446        s->insn_config  = usbduxsigma_dio_insn_config;
1447
1448        if (devpriv->high_speed) {
1449                /* Timer / pwm subdevice */
1450                s = &dev->subdevices[3];
1451                s->type         = COMEDI_SUBD_PWM;
1452                s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
1453                s->n_chan       = 8;
1454                s->maxdata      = devpriv->pwm_buf_sz;
1455                s->insn_write   = usbduxsigma_pwm_write;
1456                s->insn_config  = usbduxsigma_pwm_config;
1457
1458                usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1459        }
1460
1461        up(&devpriv->sem);
1462
1463        offset = usbduxsigma_getstatusinfo(dev, 0);
1464        if (offset < 0)
1465                dev_err(dev->class_dev,
1466                        "Communication to USBDUXSIGMA failed! Check firmware and cabling\n");
1467
1468        dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset);
1469
1470        return 0;
1471}
1472
1473static int usbduxsigma_firmware_upload(struct comedi_device *dev,
1474                                       const u8 *data, size_t size,
1475                                       unsigned long context)
1476{
1477        struct usb_device *usb = comedi_to_usb_dev(dev);
1478        uint8_t *buf;
1479        uint8_t *tmp;
1480        int ret;
1481
1482        if (!data)
1483                return 0;
1484
1485        if (size > FIRMWARE_MAX_LEN) {
1486                dev_err(dev->class_dev, "firmware binary too large for FX2\n");
1487                return -ENOMEM;
1488        }
1489
1490        /* we generate a local buffer for the firmware */
1491        buf = kmemdup(data, size, GFP_KERNEL);
1492        if (!buf)
1493                return -ENOMEM;
1494
1495        /* we need a malloc'ed buffer for usb_control_msg() */
1496        tmp = kmalloc(1, GFP_KERNEL);
1497        if (!tmp) {
1498                kfree(buf);
1499                return -ENOMEM;
1500        }
1501
1502        /* stop the current firmware on the device */
1503        *tmp = 1;       /* 7f92 to one */
1504        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1505                              USBDUXSUB_FIRMWARE,
1506                              VENDOR_DIR_OUT,
1507                              USBDUXSUB_CPUCS, 0x0000,
1508                              tmp, 1,
1509                              BULK_TIMEOUT);
1510        if (ret < 0) {
1511                dev_err(dev->class_dev, "can not stop firmware\n");
1512                goto done;
1513        }
1514
1515        /* upload the new firmware to the device */
1516        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1517                              USBDUXSUB_FIRMWARE,
1518                              VENDOR_DIR_OUT,
1519                              0, 0x0000,
1520                              buf, size,
1521                              BULK_TIMEOUT);
1522        if (ret < 0) {
1523                dev_err(dev->class_dev, "firmware upload failed\n");
1524                goto done;
1525        }
1526
1527        /* start the new firmware on the device */
1528        *tmp = 0;       /* 7f92 to zero */
1529        ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1530                              USBDUXSUB_FIRMWARE,
1531                              VENDOR_DIR_OUT,
1532                              USBDUXSUB_CPUCS, 0x0000,
1533                              tmp, 1,
1534                              BULK_TIMEOUT);
1535        if (ret < 0)
1536                dev_err(dev->class_dev, "can not start firmware\n");
1537
1538done:
1539        kfree(tmp);
1540        kfree(buf);
1541        return ret;
1542}
1543
1544static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
1545{
1546        struct usb_device *usb = comedi_to_usb_dev(dev);
1547        struct usbduxsigma_private *devpriv = dev->private;
1548        struct urb *urb;
1549        int i;
1550
1551        devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
1552        devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
1553        devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
1554        devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1555        devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb),
1556                                   GFP_KERNEL);
1557        devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb),
1558                                   GFP_KERNEL);
1559        if (!devpriv->dac_commands || !devpriv->dux_commands ||
1560            !devpriv->in_buf || !devpriv->insn_buf ||
1561            !devpriv->ai_urbs || !devpriv->ao_urbs)
1562                return -ENOMEM;
1563
1564        for (i = 0; i < devpriv->n_ai_urbs; i++) {
1565                /* one frame: 1ms */
1566                urb = usb_alloc_urb(1, GFP_KERNEL);
1567                if (!urb)
1568                        return -ENOMEM;
1569                devpriv->ai_urbs[i] = urb;
1570                urb->dev = usb;
1571                /* will be filled later with a pointer to the comedi-device */
1572                /* and ONLY then the urb should be submitted */
1573                urb->context = NULL;
1574                urb->pipe = usb_rcvisocpipe(usb, USBDUXSIGMA_ISO_IN_EP);
1575                urb->transfer_flags = URB_ISO_ASAP;
1576                urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1577                if (!urb->transfer_buffer)
1578                        return -ENOMEM;
1579                urb->complete = usbduxsigma_ai_urb_complete;
1580                urb->number_of_packets = 1;
1581                urb->transfer_buffer_length = SIZEINBUF;
1582                urb->iso_frame_desc[0].offset = 0;
1583                urb->iso_frame_desc[0].length = SIZEINBUF;
1584        }
1585
1586        for (i = 0; i < devpriv->n_ao_urbs; i++) {
1587                /* one frame: 1ms */
1588                urb = usb_alloc_urb(1, GFP_KERNEL);
1589                if (!urb)
1590                        return -ENOMEM;
1591                devpriv->ao_urbs[i] = urb;
1592                urb->dev = usb;
1593                /* will be filled later with a pointer to the comedi-device */
1594                /* and ONLY then the urb should be submitted */
1595                urb->context = NULL;
1596                urb->pipe = usb_sndisocpipe(usb, USBDUXSIGMA_ISO_OUT_EP);
1597                urb->transfer_flags = URB_ISO_ASAP;
1598                urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1599                if (!urb->transfer_buffer)
1600                        return -ENOMEM;
1601                urb->complete = usbduxsigma_ao_urb_complete;
1602                urb->number_of_packets = 1;
1603                urb->transfer_buffer_length = SIZEOUTBUF;
1604                urb->iso_frame_desc[0].offset = 0;
1605                urb->iso_frame_desc[0].length = SIZEOUTBUF;
1606                if (devpriv->high_speed)
1607                        urb->interval = 8;      /* uframes */
1608                else
1609                        urb->interval = 1;      /* frames */
1610        }
1611
1612        if (devpriv->high_speed) {
1613                /* max bulk ep size in high speed */
1614                devpriv->pwm_buf_sz = 512;
1615                urb = usb_alloc_urb(0, GFP_KERNEL);
1616                if (!urb)
1617                        return -ENOMEM;
1618                devpriv->pwm_urb = urb;
1619                urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL);
1620                if (!urb->transfer_buffer)
1621                        return -ENOMEM;
1622        } else {
1623                devpriv->pwm_urb = NULL;
1624                devpriv->pwm_buf_sz = 0;
1625        }
1626
1627        return 0;
1628}
1629
1630static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
1631{
1632        struct usbduxsigma_private *devpriv = dev->private;
1633        struct urb *urb;
1634        int i;
1635
1636        /* force unlink all urbs */
1637        usbduxsigma_ai_stop(dev, 1);
1638        usbduxsigma_ao_stop(dev, 1);
1639        usbduxsigma_pwm_stop(dev, 1);
1640
1641        urb = devpriv->pwm_urb;
1642        if (urb) {
1643                kfree(urb->transfer_buffer);
1644                usb_free_urb(urb);
1645        }
1646        if (devpriv->ao_urbs) {
1647                for (i = 0; i < devpriv->n_ao_urbs; i++) {
1648                        urb = devpriv->ao_urbs[i];
1649                        if (urb) {
1650                                kfree(urb->transfer_buffer);
1651                                usb_free_urb(urb);
1652                        }
1653                }
1654                kfree(devpriv->ao_urbs);
1655        }
1656        if (devpriv->ai_urbs) {
1657                for (i = 0; i < devpriv->n_ai_urbs; i++) {
1658                        urb = devpriv->ai_urbs[i];
1659                        if (urb) {
1660                                kfree(urb->transfer_buffer);
1661                                usb_free_urb(urb);
1662                        }
1663                }
1664                kfree(devpriv->ai_urbs);
1665        }
1666        kfree(devpriv->insn_buf);
1667        kfree(devpriv->in_buf);
1668        kfree(devpriv->dux_commands);
1669        kfree(devpriv->dac_commands);
1670}
1671
1672static int usbduxsigma_auto_attach(struct comedi_device *dev,
1673                                   unsigned long context_unused)
1674{
1675        struct usb_interface *intf = comedi_to_usb_interface(dev);
1676        struct usb_device *usb = comedi_to_usb_dev(dev);
1677        struct usbduxsigma_private *devpriv;
1678        int ret;
1679
1680        devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1681        if (!devpriv)
1682                return -ENOMEM;
1683        dev->private = devpriv;
1684
1685        sema_init(&devpriv->sem, 1);
1686        usb_set_intfdata(intf, devpriv);
1687
1688        ret = usb_set_interface(usb,
1689                                intf->altsetting->desc.bInterfaceNumber, 3);
1690        if (ret < 0) {
1691                dev_err(dev->class_dev,
1692                        "could not set alternate setting 3 in high speed\n");
1693                return -ENODEV;
1694        }
1695
1696        /* test if it is high speed (USB 2.0) */
1697        devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
1698        if (devpriv->high_speed) {
1699                devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
1700                devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
1701        } else {
1702                devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
1703                devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
1704        }
1705
1706        ret = usbduxsigma_alloc_usb_buffers(dev);
1707        if (ret)
1708                return ret;
1709
1710        ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
1711                                   usbduxsigma_firmware_upload, 0);
1712        if (ret)
1713                return ret;
1714
1715        return usbduxsigma_attach_common(dev);
1716}
1717
1718static void usbduxsigma_detach(struct comedi_device *dev)
1719{
1720        struct usb_interface *intf = comedi_to_usb_interface(dev);
1721        struct usbduxsigma_private *devpriv = dev->private;
1722
1723        if (!devpriv)
1724                return;
1725
1726        usb_set_intfdata(intf, NULL);
1727
1728        down(&devpriv->sem);
1729        usbduxsigma_free_usb_buffers(dev);
1730        up(&devpriv->sem);
1731}
1732
1733static struct comedi_driver usbduxsigma_driver = {
1734        .driver_name    = "usbduxsigma",
1735        .module         = THIS_MODULE,
1736        .auto_attach    = usbduxsigma_auto_attach,
1737        .detach         = usbduxsigma_detach,
1738};
1739
1740static int usbduxsigma_usb_probe(struct usb_interface *intf,
1741                                 const struct usb_device_id *id)
1742{
1743        return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);
1744}
1745
1746static const struct usb_device_id usbduxsigma_usb_table[] = {
1747        { USB_DEVICE(0x13d8, 0x0020) },
1748        { USB_DEVICE(0x13d8, 0x0021) },
1749        { USB_DEVICE(0x13d8, 0x0022) },
1750        { }
1751};
1752MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
1753
1754static struct usb_driver usbduxsigma_usb_driver = {
1755        .name           = "usbduxsigma",
1756        .probe          = usbduxsigma_usb_probe,
1757        .disconnect     = comedi_usb_auto_unconfig,
1758        .id_table       = usbduxsigma_usb_table,
1759};
1760module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
1761
1762MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1763MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
1764MODULE_LICENSE("GPL");
1765MODULE_FIRMWARE(FIRMWARE);
1766