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