linux/drivers/staging/comedi/drivers/usbduxsigma.c
<<
>>
Prefs
   1/*
   2   comedi/drivers/usbdux.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   You should have received a copy of the GNU General Public License
  16   along with this program; if not, write to the Free Software
  17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18
  19 */
  20/*
  21Driver: usbduxsigma
  22Description: University of Stirling USB DAQ & INCITE Technology Limited
  23Devices: [ITL] USB-DUX (usbduxsigma.o)
  24Author: Bernd Porr <BerndPorr@f2s.com>
  25Updated: 8 Nov 2011
  26Status: testing
  27*/
  28/*
  29 * I must give credit here to Chris Baugher who
  30 * wrote the driver for AT-MIO-16d. I used some parts of this
  31 * driver. I also must give credits to David Brownell
  32 * who supported me with the USB development.
  33 *
  34 * Note: the raw data from the A/D converter is 24 bit big endian
  35 * anything else is little endian to/from the dux board
  36 *
  37 *
  38 * Revision history:
  39 *   0.1: initial version
  40 *   0.2: all basic functions implemented, digital I/O only for one port
  41 *   0.3: proper vendor ID and driver name
  42 *   0.4: fixed D/A voltage range
  43 *   0.5: various bug fixes, health check at startup
  44 *   0.6: corrected wrong input range
  45 */
  46
  47/* generates loads of debug info */
  48/* #define NOISY_DUX_DEBUGBUG */
  49
  50#include <linux/kernel.h>
  51#include <linux/module.h>
  52#include <linux/init.h>
  53#include <linux/slab.h>
  54#include <linux/input.h>
  55#include <linux/usb.h>
  56#include <linux/fcntl.h>
  57#include <linux/compiler.h>
  58#include <linux/firmware.h>
  59#include "comedi_fc.h"
  60#include "../comedidev.h"
  61
  62/* timeout for the USB-transfer in ms*/
  63#define BULK_TIMEOUT 1000
  64
  65/* constants for "firmware" upload and download */
  66#define FIRMWARE "usbduxsigma_firmware.bin"
  67#define USBDUXSUB_FIRMWARE 0xA0
  68#define VENDOR_DIR_IN  0xC0
  69#define VENDOR_DIR_OUT 0x40
  70
  71/* internal addresses of the 8051 processor */
  72#define USBDUXSUB_CPUCS 0xE600
  73
  74/*
  75 * the minor device number, major is 180 only for debugging purposes and to
  76 * upload special firmware (programming the eeprom etc) which is not
  77 * compatible with the comedi framwork
  78 */
  79#define USBDUXSUB_MINOR 32
  80
  81/* max lenghth of the transfer-buffer for software upload */
  82#define TB_LEN 0x2000
  83
  84/* Input endpoint number: ISO/IRQ */
  85#define ISOINEP           6
  86
  87/* Output endpoint number: ISO/IRQ */
  88#define ISOOUTEP          2
  89
  90/* This EP sends DUX commands to USBDUX */
  91#define COMMAND_OUT_EP     1
  92
  93/* This EP receives the DUX commands from USBDUX */
  94#define COMMAND_IN_EP        8
  95
  96/* Output endpoint for PWM */
  97#define PWM_EP         4
  98
  99/* 300Hz max frequ under PWM */
 100#define MIN_PWM_PERIOD  ((long)(1E9/300))
 101
 102/* Default PWM frequency */
 103#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
 104
 105/* Number of channels (16 AD and offset)*/
 106#define NUMCHANNELS 16
 107
 108/* Size of one A/D value */
 109#define SIZEADIN          ((sizeof(int32_t)))
 110
 111/*
 112 * Size of the async input-buffer IN BYTES, the DIO state is transmitted
 113 * as the first byte.
 114 */
 115#define SIZEINBUF         (((NUMCHANNELS+1)*SIZEADIN))
 116
 117/* 16 bytes. */
 118#define SIZEINSNBUF       16
 119
 120/* Number of DA channels */
 121#define NUMOUTCHANNELS    8
 122
 123/* size of one value for the D/A converter: channel and value */
 124#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(int16_t)))
 125
 126/*
 127 * Size of the output-buffer in bytes
 128 * Actually only the first 4 triplets are used but for the
 129 * high speed mode we need to pad it to 8 (microframes).
 130 */
 131#define SIZEOUTBUF         ((8*SIZEDAOUT))
 132
 133/*
 134 * Size of the buffer for the dux commands: just now max size is determined
 135 * by the analogue out + command byte + panic bytes...
 136 */
 137#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
 138
 139/* Number of in-URBs which receive the data: min=2 */
 140#define NUMOFINBUFFERSFULL     5
 141
 142/* Number of out-URBs which send the data: min=2 */
 143#define NUMOFOUTBUFFERSFULL    5
 144
 145/* Number of in-URBs which receive the data: min=5 */
 146/* must have more buffers due to buggy USB ctr */
 147#define NUMOFINBUFFERSHIGH     10
 148
 149/* Number of out-URBs which send the data: min=5 */
 150/* must have more buffers due to buggy USB ctr */
 151#define NUMOFOUTBUFFERSHIGH    10
 152
 153/* Total number of usbdux devices */
 154#define NUMUSBDUX             16
 155
 156/* Analogue in subdevice */
 157#define SUBDEV_AD             0
 158
 159/* Analogue out subdevice */
 160#define SUBDEV_DA             1
 161
 162/* Digital I/O */
 163#define SUBDEV_DIO            2
 164
 165/* timer aka pwm output */
 166#define SUBDEV_PWM            3
 167
 168/* number of retries to get the right dux command */
 169#define RETRIES 10
 170
 171/**************************************************/
 172/* comedi constants */
 173static const struct comedi_lrange range_usbdux_ai_range = { 1, {
 174                                                                BIP_RANGE
 175                                                                (2.65/2.0)
 176                                                                }
 177};
 178
 179/*
 180 * private structure of one subdevice
 181 */
 182
 183/*
 184 * This is the structure which holds all the data of
 185 * this driver one sub device just now: A/D
 186 */
 187struct usbduxsub {
 188        /* attached? */
 189        int attached;
 190        /* is it associated with a subdevice? */
 191        int probed;
 192        /* pointer to the usb-device */
 193        struct usb_device *usbdev;
 194        /* actual number of in-buffers */
 195        int numOfInBuffers;
 196        /* actual number of out-buffers */
 197        int numOfOutBuffers;
 198        /* ISO-transfer handling: buffers */
 199        struct urb **urbIn;
 200        struct urb **urbOut;
 201        /* pwm-transfer handling */
 202        struct urb *urbPwm;
 203        /* PWM period */
 204        unsigned int pwmPeriod;
 205        /* PWM internal delay for the GPIF in the FX2 */
 206        uint8_t pwmDelay;
 207        /* size of the PWM buffer which holds the bit pattern */
 208        int sizePwmBuf;
 209        /* input buffer for the ISO-transfer */
 210        int32_t *inBuffer;
 211        /* input buffer for single insn */
 212        int8_t *insnBuffer;
 213        /* output buffer for single DA outputs */
 214        int16_t *outBuffer;
 215        /* interface number */
 216        int ifnum;
 217        /* interface structure in 2.6 */
 218        struct usb_interface *interface;
 219        /* comedi device for the interrupt context */
 220        struct comedi_device *comedidev;
 221        /* is it USB_SPEED_HIGH or not? */
 222        short int high_speed;
 223        /* asynchronous command is running */
 224        short int ai_cmd_running;
 225        short int ao_cmd_running;
 226        /* pwm is running */
 227        short int pwm_cmd_running;
 228        /* continuous acquisition */
 229        short int ai_continuous;
 230        short int ao_continuous;
 231        /* number of samples to acquire */
 232        int ai_sample_count;
 233        int ao_sample_count;
 234        /* time between samples in units of the timer */
 235        unsigned int ai_timer;
 236        unsigned int ao_timer;
 237        /* counter between acquisitions */
 238        unsigned int ai_counter;
 239        unsigned int ao_counter;
 240        /* interval in frames/uframes */
 241        unsigned int ai_interval;
 242        /* D/A commands */
 243        uint8_t *dac_commands;
 244        /* commands */
 245        uint8_t *dux_commands;
 246        struct semaphore sem;
 247};
 248
 249/*
 250 * The pointer to the private usb-data of the driver is also the private data
 251 * for the comedi-device.  This has to be global as the usb subsystem needs
 252 * global variables. The other reason is that this structure must be there
 253 * _before_ any comedi command is issued. The usb subsystem must be initialised
 254 * before comedi can access it.
 255 */
 256static struct usbduxsub usbduxsub[NUMUSBDUX];
 257
 258static DEFINE_SEMAPHORE(start_stop_sem);
 259
 260/*
 261 * Stops the data acquision
 262 * It should be safe to call this function from any context
 263 */
 264static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp)
 265{
 266        int i = 0;
 267        int err = 0;
 268
 269        if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
 270                for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
 271                        if (usbduxsub_tmp->urbIn[i]) {
 272                                /* We wait here until all transfers have been
 273                                 * cancelled. */
 274                                usb_kill_urb(usbduxsub_tmp->urbIn[i]);
 275                        }
 276                        dev_dbg(&usbduxsub_tmp->interface->dev,
 277                                "comedi: usbdux: unlinked InURB %d, err=%d\n",
 278                                i, err);
 279                }
 280        }
 281        return err;
 282}
 283
 284/*
 285 * This will stop a running acquisition operation
 286 * Is called from within this driver from both the
 287 * interrupt context and from comedi
 288 */
 289static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 290{
 291        int ret = 0;
 292
 293        if (!this_usbduxsub) {
 294                pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
 295                return -EFAULT;
 296        }
 297        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
 298
 299        if (do_unlink) {
 300                /* stop aquistion */
 301                ret = usbduxsub_unlink_InURBs(this_usbduxsub);
 302        }
 303
 304        this_usbduxsub->ai_cmd_running = 0;
 305
 306        return ret;
 307}
 308
 309/*
 310 * This will cancel a running acquisition operation.
 311 * This is called by comedi but never from inside the driver.
 312 */
 313static int usbdux_ai_cancel(struct comedi_device *dev,
 314                            struct comedi_subdevice *s)
 315{
 316        struct usbduxsub *this_usbduxsub;
 317        int res = 0;
 318
 319        /* force unlink of all urbs */
 320        this_usbduxsub = dev->private;
 321        if (!this_usbduxsub)
 322                return -EFAULT;
 323
 324        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
 325
 326        /* prevent other CPUs from submitting new commands just now */
 327        down(&this_usbduxsub->sem);
 328        if (!(this_usbduxsub->probed)) {
 329                up(&this_usbduxsub->sem);
 330                return -ENODEV;
 331        }
 332        /* unlink only if the urb really has been submitted */
 333        res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
 334        up(&this_usbduxsub->sem);
 335        return res;
 336}
 337
 338/* analogue IN - interrupt service routine */
 339static void usbduxsub_ai_IsocIrq(struct urb *urb)
 340{
 341        int i, err, n;
 342        struct usbduxsub *this_usbduxsub;
 343        struct comedi_device *this_comedidev;
 344        struct comedi_subdevice *s;
 345        int32_t v;
 346        unsigned int dio_state;
 347
 348        /* the context variable points to the comedi device */
 349        this_comedidev = urb->context;
 350        /* the private structure of the subdevice is struct usbduxsub */
 351        this_usbduxsub = this_comedidev->private;
 352        /* subdevice which is the AD converter */
 353        s = &this_comedidev->subdevices[SUBDEV_AD];
 354
 355        /* first we test if something unusual has just happened */
 356        switch (urb->status) {
 357        case 0:
 358                /* copy the result in the transfer buffer */
 359                memcpy(this_usbduxsub->inBuffer,
 360                       urb->transfer_buffer, SIZEINBUF);
 361                break;
 362        case -EILSEQ:
 363                /* error in the ISOchronous data */
 364                /* we don't copy the data into the transfer buffer */
 365                /* and recycle the last data byte */
 366                dev_dbg(&urb->dev->dev,
 367                        "comedi%d: usbdux: CRC error in ISO IN stream.\n",
 368                        this_usbduxsub->comedidev->minor);
 369
 370                break;
 371
 372        case -ECONNRESET:
 373        case -ENOENT:
 374        case -ESHUTDOWN:
 375        case -ECONNABORTED:
 376                /* happens after an unlink command */
 377                if (this_usbduxsub->ai_cmd_running) {
 378                        /* we are still running a command */
 379                        /* tell this comedi */
 380                        s->async->events |= COMEDI_CB_EOA;
 381                        s->async->events |= COMEDI_CB_ERROR;
 382                        comedi_event(this_usbduxsub->comedidev, s);
 383                        /* stop the transfer w/o unlink */
 384                        usbdux_ai_stop(this_usbduxsub, 0);
 385                }
 386                return;
 387
 388        default:
 389                /* a real error on the bus */
 390                /* pass error to comedi if we are really running a command */
 391                if (this_usbduxsub->ai_cmd_running) {
 392                        dev_err(&urb->dev->dev,
 393                                "Non-zero urb status received in ai intr "
 394                                "context: %d\n", urb->status);
 395                        s->async->events |= COMEDI_CB_EOA;
 396                        s->async->events |= COMEDI_CB_ERROR;
 397                        comedi_event(this_usbduxsub->comedidev, s);
 398                        /* don't do an unlink here */
 399                        usbdux_ai_stop(this_usbduxsub, 0);
 400                }
 401                return;
 402        }
 403
 404        /*
 405         * at this point we are reasonably sure that nothing dodgy has happened
 406         * are we running a command?
 407         */
 408        if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
 409                /*
 410                 * not running a command, do not continue execution if no
 411                 * asynchronous command is running in particular not resubmit
 412                 */
 413                return;
 414        }
 415
 416        urb->dev = this_usbduxsub->usbdev;
 417
 418        /* resubmit the urb */
 419        err = usb_submit_urb(urb, GFP_ATOMIC);
 420        if (unlikely(err < 0)) {
 421                dev_err(&urb->dev->dev,
 422                        "comedi_: urb resubmit failed in int-context!"
 423                        "err=%d\n",
 424                        err);
 425                if (err == -EL2NSYNC)
 426                        dev_err(&urb->dev->dev,
 427                                "buggy USB host controller or bug in IRQ "
 428                                "handler!\n");
 429                s->async->events |= COMEDI_CB_EOA;
 430                s->async->events |= COMEDI_CB_ERROR;
 431                comedi_event(this_usbduxsub->comedidev, s);
 432                /* don't do an unlink here */
 433                usbdux_ai_stop(this_usbduxsub, 0);
 434                return;
 435        }
 436
 437        /* get the state of the dio pins to allow external trigger */
 438        dio_state = be32_to_cpu(this_usbduxsub->inBuffer[0]);
 439
 440        this_usbduxsub->ai_counter--;
 441        if (likely(this_usbduxsub->ai_counter > 0))
 442                return;
 443
 444        /* timer zero, transfer measurements to comedi */
 445        this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
 446
 447        /* test, if we transmit only a fixed number of samples */
 448        if (!(this_usbduxsub->ai_continuous)) {
 449                /* not continuous, fixed number of samples */
 450                this_usbduxsub->ai_sample_count--;
 451                /* all samples received? */
 452                if (this_usbduxsub->ai_sample_count < 0) {
 453                        /* prevent a resubmit next time */
 454                        usbdux_ai_stop(this_usbduxsub, 0);
 455                        /* say comedi that the acquistion is over */
 456                        s->async->events |= COMEDI_CB_EOA;
 457                        comedi_event(this_usbduxsub->comedidev, s);
 458                        return;
 459                }
 460        }
 461        /* get the data from the USB bus and hand it over to comedi */
 462        n = s->async->cmd.chanlist_len;
 463        for (i = 0; i < n; i++) {
 464                /* transfer data, note first byte is the DIO state */
 465                v = be32_to_cpu(this_usbduxsub->inBuffer[i+1]);
 466                /* strip status byte */
 467                v = v & 0x00ffffff;
 468                /* convert to unsigned */
 469                v = v ^ 0x00800000;
 470                /* write the byte to the buffer */
 471                err = cfc_write_array_to_buffer(s, &v, sizeof(uint32_t));
 472                if (unlikely(err == 0)) {
 473                        /* buffer overflow */
 474                        usbdux_ai_stop(this_usbduxsub, 0);
 475                        return;
 476                }
 477        }
 478        /* tell comedi that data is there */
 479        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
 480        comedi_event(this_usbduxsub->comedidev, s);
 481}
 482
 483static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp)
 484{
 485        int i = 0;
 486        int err = 0;
 487
 488        if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
 489                for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
 490                        if (usbduxsub_tmp->urbOut[i])
 491                                usb_kill_urb(usbduxsub_tmp->urbOut[i]);
 492
 493                        dev_dbg(&usbduxsub_tmp->interface->dev,
 494                                "comedi: usbdux: unlinked OutURB %d: res=%d\n",
 495                                i, err);
 496                }
 497        }
 498        return err;
 499}
 500
 501/* This will cancel a running acquisition operation
 502 * in any context.
 503 */
 504static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
 505{
 506        int ret = 0;
 507
 508        if (!this_usbduxsub)
 509                return -EFAULT;
 510        dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
 511
 512        if (do_unlink)
 513                ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
 514
 515        this_usbduxsub->ao_cmd_running = 0;
 516
 517        return ret;
 518}
 519
 520/* force unlink, is called by comedi */
 521static int usbdux_ao_cancel(struct comedi_device *dev,
 522                            struct comedi_subdevice *s)
 523{
 524        struct usbduxsub *this_usbduxsub = dev->private;
 525        int res = 0;
 526
 527        if (!this_usbduxsub)
 528                return -EFAULT;
 529
 530        /* prevent other CPUs from submitting a command just now */
 531        down(&this_usbduxsub->sem);
 532        if (!(this_usbduxsub->probed)) {
 533                up(&this_usbduxsub->sem);
 534                return -ENODEV;
 535        }
 536        /* unlink only if it is really running */
 537        res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
 538        up(&this_usbduxsub->sem);
 539        return res;
 540}
 541
 542static void usbduxsub_ao_IsocIrq(struct urb *urb)
 543{
 544        int i, ret;
 545        uint8_t *datap;
 546        struct usbduxsub *this_usbduxsub;
 547        struct comedi_device *this_comedidev;
 548        struct comedi_subdevice *s;
 549
 550        /* the context variable points to the subdevice */
 551        this_comedidev = urb->context;
 552        /* the private structure of the subdevice is struct usbduxsub */
 553        this_usbduxsub = this_comedidev->private;
 554
 555        s = &this_comedidev->subdevices[SUBDEV_DA];
 556
 557        switch (urb->status) {
 558        case 0:
 559                /* success */
 560                break;
 561
 562        case -ECONNRESET:
 563        case -ENOENT:
 564        case -ESHUTDOWN:
 565        case -ECONNABORTED:
 566                /* after an unlink command, unplug, ... etc */
 567                /* no unlink needed here. Already shutting down. */
 568                if (this_usbduxsub->ao_cmd_running) {
 569                        s->async->events |= COMEDI_CB_EOA;
 570                        comedi_event(this_usbduxsub->comedidev, s);
 571                        usbdux_ao_stop(this_usbduxsub, 0);
 572                }
 573                return;
 574
 575        default:
 576                /* a real error */
 577                if (this_usbduxsub->ao_cmd_running) {
 578                        dev_err(&urb->dev->dev,
 579                                "comedi_: Non-zero urb status received in ao "
 580                                "intr context: %d\n", urb->status);
 581                        s->async->events |= COMEDI_CB_ERROR;
 582                        s->async->events |= COMEDI_CB_EOA;
 583                        comedi_event(this_usbduxsub->comedidev, s);
 584                        /* we do an unlink if we are in the high speed mode */
 585                        usbdux_ao_stop(this_usbduxsub, 0);
 586                }
 587                return;
 588        }
 589
 590        /* are we actually running? */
 591        if (!(this_usbduxsub->ao_cmd_running))
 592                return;
 593
 594        /* normal operation: executing a command in this subdevice */
 595        this_usbduxsub->ao_counter--;
 596        if ((int)this_usbduxsub->ao_counter <= 0) {
 597                /* timer zero */
 598                this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
 599
 600                /* handle non continuous acquisition */
 601                if (!(this_usbduxsub->ao_continuous)) {
 602                        /* fixed number of samples */
 603                        this_usbduxsub->ao_sample_count--;
 604                        if (this_usbduxsub->ao_sample_count < 0) {
 605                                /* all samples transmitted */
 606                                usbdux_ao_stop(this_usbduxsub, 0);
 607                                s->async->events |= COMEDI_CB_EOA;
 608                                comedi_event(this_usbduxsub->comedidev, s);
 609                                /* no resubmit of the urb */
 610                                return;
 611                        }
 612                }
 613                /* transmit data to the USB bus */
 614                ((uint8_t *) (urb->transfer_buffer))[0] =
 615                    s->async->cmd.chanlist_len;
 616                for (i = 0; i < s->async->cmd.chanlist_len; i++) {
 617                        short temp;
 618                        if (i >= NUMOUTCHANNELS)
 619                                break;
 620
 621                        /* pointer to the DA */
 622                        datap =
 623                            (&(((uint8_t *) urb->transfer_buffer)[i * 2 + 1]));
 624                        /* get the data from comedi */
 625                        ret = comedi_buf_get(s->async, &temp);
 626                        datap[0] = temp;
 627                        datap[1] = this_usbduxsub->dac_commands[i];
 628                        /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
 629                        /* datap[0],datap[1],datap[2]); */
 630                        if (ret < 0) {
 631                                dev_err(&urb->dev->dev,
 632                                        "comedi: buffer underflow\n");
 633                                s->async->events |= COMEDI_CB_EOA;
 634                                s->async->events |= COMEDI_CB_OVERFLOW;
 635                        }
 636                        /* transmit data to comedi */
 637                        s->async->events |= COMEDI_CB_BLOCK;
 638                        comedi_event(this_usbduxsub->comedidev, s);
 639                }
 640        }
 641        urb->transfer_buffer_length = SIZEOUTBUF;
 642        urb->dev = this_usbduxsub->usbdev;
 643        urb->status = 0;
 644        if (this_usbduxsub->ao_cmd_running) {
 645                if (this_usbduxsub->high_speed) {
 646                        /* uframes */
 647                        urb->interval = 8;
 648                } else {
 649                        /* frames */
 650                        urb->interval = 1;
 651                }
 652                urb->number_of_packets = 1;
 653                urb->iso_frame_desc[0].offset = 0;
 654                urb->iso_frame_desc[0].length = SIZEOUTBUF;
 655                urb->iso_frame_desc[0].status = 0;
 656                ret = usb_submit_urb(urb, GFP_ATOMIC);
 657                if (ret < 0) {
 658                        dev_err(&urb->dev->dev,
 659                                "comedi_: ao urb resubm failed in int-cont. "
 660                                "ret=%d", ret);
 661                        if (ret == EL2NSYNC)
 662                                dev_err(&urb->dev->dev,
 663                                        "buggy USB host controller or bug in "
 664                                        "IRQ handling!\n");
 665
 666                        s->async->events |= COMEDI_CB_EOA;
 667                        s->async->events |= COMEDI_CB_ERROR;
 668                        comedi_event(this_usbduxsub->comedidev, s);
 669                        /* don't do an unlink here */
 670                        usbdux_ao_stop(this_usbduxsub, 0);
 671                }
 672        }
 673}
 674
 675static int usbduxsub_start(struct usbduxsub *usbduxsub)
 676{
 677        int errcode = 0;
 678        uint8_t *local_transfer_buffer;
 679
 680        local_transfer_buffer = kmalloc(16, GFP_KERNEL);
 681        if (!local_transfer_buffer)
 682                return -ENOMEM;
 683
 684        /* 7f92 to zero */
 685        local_transfer_buffer[0] = 0;
 686        errcode = usb_control_msg(usbduxsub->usbdev,
 687                                  /* create a pipe for a control transfer */
 688                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 689                                  /* bRequest, "Firmware" */
 690                                  USBDUXSUB_FIRMWARE,
 691                                  /* bmRequestType */
 692                                  VENDOR_DIR_OUT,
 693                                  /* Value */
 694                                  USBDUXSUB_CPUCS,
 695                                  /* Index */
 696                                  0x0000,
 697                                  /* address of the transfer buffer */
 698                                  local_transfer_buffer,
 699                                  /* Length */
 700                                  1,
 701                                  /* Timeout */
 702                                  BULK_TIMEOUT);
 703        if (errcode < 0)
 704                dev_err(&usbduxsub->interface->dev,
 705                        "comedi_: control msg failed (start)\n");
 706
 707        kfree(local_transfer_buffer);
 708        return errcode;
 709}
 710
 711static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 712{
 713        int errcode = 0;
 714        uint8_t *local_transfer_buffer;
 715
 716        local_transfer_buffer = kmalloc(16, GFP_KERNEL);
 717        if (!local_transfer_buffer)
 718                return -ENOMEM;
 719
 720        /* 7f92 to one */
 721        local_transfer_buffer[0] = 1;
 722        errcode = usb_control_msg(usbduxsub->usbdev,
 723                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 724                                  /* bRequest, "Firmware" */
 725                                  USBDUXSUB_FIRMWARE,
 726                                  /* bmRequestType */
 727                                  VENDOR_DIR_OUT,
 728                                  /* Value */
 729                                  USBDUXSUB_CPUCS,
 730                                  /* Index */
 731                                  0x0000, local_transfer_buffer,
 732                                  /* Length */
 733                                  1,
 734                                  /* Timeout */
 735                                  BULK_TIMEOUT);
 736        if (errcode < 0)
 737                dev_err(&usbduxsub->interface->dev,
 738                        "comedi_: control msg failed (stop)\n");
 739
 740        kfree(local_transfer_buffer);
 741        return errcode;
 742}
 743
 744static int usbduxsub_upload(struct usbduxsub *usbduxsub,
 745                            uint8_t *local_transfer_buffer,
 746                            unsigned int startAddr, unsigned int len)
 747{
 748        int errcode;
 749
 750        errcode = usb_control_msg(usbduxsub->usbdev,
 751                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
 752                                  /* brequest, firmware */
 753                                  USBDUXSUB_FIRMWARE,
 754                                  /* bmRequestType */
 755                                  VENDOR_DIR_OUT,
 756                                  /* value */
 757                                  startAddr,
 758                                  /* index */
 759                                  0x0000,
 760                                  /* our local safe buffer */
 761                                  local_transfer_buffer,
 762                                  /* length */
 763                                  len,
 764                                  /* timeout */
 765                                  BULK_TIMEOUT);
 766        dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
 767        if (errcode < 0) {
 768                dev_err(&usbduxsub->interface->dev,
 769                        "comedi_: upload failed\n");
 770                return errcode;
 771        }
 772        return 0;
 773}
 774
 775/* the FX2LP has twice as much as the standard FX2 */
 776#define FIRMWARE_MAX_LEN 0x4000
 777
 778static int firmwareUpload(struct usbduxsub *usbduxsub,
 779                          const u8 *firmwareBinary, int sizeFirmware)
 780{
 781        int ret;
 782        uint8_t *fwBuf;
 783
 784        if (!firmwareBinary)
 785                return 0;
 786
 787        if (sizeFirmware > FIRMWARE_MAX_LEN) {
 788                dev_err(&usbduxsub->interface->dev,
 789                        "usbduxsigma firmware binary it too large for FX2.\n");
 790                return -ENOMEM;
 791        }
 792
 793        /* we generate a local buffer for the firmware */
 794        fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL);
 795        if (!fwBuf) {
 796                dev_err(&usbduxsub->interface->dev,
 797                        "comedi_: mem alloc for firmware failed\n");
 798                return -ENOMEM;
 799        }
 800
 801        ret = usbduxsub_stop(usbduxsub);
 802        if (ret < 0) {
 803                dev_err(&usbduxsub->interface->dev,
 804                        "comedi_: can not stop firmware\n");
 805                kfree(fwBuf);
 806                return ret;
 807        }
 808
 809        ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware);
 810        if (ret < 0) {
 811                dev_err(&usbduxsub->interface->dev,
 812                        "comedi_: firmware upload failed\n");
 813                kfree(fwBuf);
 814                return ret;
 815        }
 816        ret = usbduxsub_start(usbduxsub);
 817        if (ret < 0) {
 818                dev_err(&usbduxsub->interface->dev,
 819                        "comedi_: can not start firmware\n");
 820                kfree(fwBuf);
 821                return ret;
 822        }
 823        kfree(fwBuf);
 824        return 0;
 825}
 826
 827static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
 828{
 829        int i, errFlag;
 830
 831        if (!usbduxsub)
 832                return -EFAULT;
 833
 834        /* Submit all URBs and start the transfer on the bus */
 835        for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
 836                /* in case of a resubmission after an unlink... */
 837                usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
 838                usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
 839                usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
 840                usbduxsub->urbIn[i]->status = 0;
 841                usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
 842                dev_dbg(&usbduxsub->interface->dev,
 843                        "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
 844                        usbduxsub->comedidev->minor, i,
 845                        (usbduxsub->urbIn[i]->context),
 846                        (usbduxsub->urbIn[i]->dev),
 847                        (usbduxsub->urbIn[i]->interval));
 848                errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
 849                if (errFlag) {
 850                        dev_err(&usbduxsub->interface->dev,
 851                                "comedi_: ai: usb_submit_urb(%d) error %d\n",
 852                                i, errFlag);
 853                        return errFlag;
 854                }
 855        }
 856        return 0;
 857}
 858
 859static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
 860{
 861        int i, errFlag;
 862
 863        if (!usbduxsub)
 864                return -EFAULT;
 865
 866        for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
 867                dev_dbg(&usbduxsub->interface->dev,
 868                        "comedi_: submitting out-urb[%d]\n", i);
 869                /* in case of a resubmission after an unlink... */
 870                usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
 871                usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
 872                usbduxsub->urbOut[i]->status = 0;
 873                usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
 874                errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
 875                if (errFlag) {
 876                        dev_err(&usbduxsub->interface->dev,
 877                                "comedi_: ao: usb_submit_urb(%d) error %d\n",
 878                                i, errFlag);
 879                        return errFlag;
 880                }
 881        }
 882        return 0;
 883}
 884
 885static int chanToInterval(int nChannels)
 886{
 887        if (nChannels <= 2)
 888                /* 4kHz */
 889                return 2;
 890        if (nChannels <= 8)
 891                /* 2kHz */
 892                return 4;
 893        /* 1kHz */
 894        return 8;
 895}
 896
 897static int usbdux_ai_cmdtest(struct comedi_device *dev,
 898                             struct comedi_subdevice *s,
 899                             struct comedi_cmd *cmd)
 900{
 901        struct usbduxsub *this_usbduxsub = dev->private;
 902        int err = 0, i;
 903        unsigned int tmpTimer;
 904
 905        if (!(this_usbduxsub->probed))
 906                return -ENODEV;
 907
 908        /* Step 1 : check if triggers are trivially valid */
 909
 910        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 911        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
 912        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 913        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 914        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 915
 916        if (err)
 917                return 1;
 918
 919        /* Step 2a : make sure trigger sources are unique */
 920
 921        err |= cfc_check_trigger_is_unique(cmd->start_src);
 922        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 923
 924        /* Step 2b : and mutually compatible */
 925
 926        if (err)
 927                return 2;
 928
 929        /* Step 3: check if arguments are trivially valid */
 930
 931        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 932
 933        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 934                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 935
 936        if (cmd->scan_begin_src == TRIG_TIMER) {
 937                if (this_usbduxsub->high_speed) {
 938                        /*
 939                         * In high speed mode microframes are possible.
 940                         * However, during one microframe we can roughly
 941                         * sample two channels. Thus, the more channels
 942                         * are in the channel list the more time we need.
 943                         */
 944                        i = chanToInterval(cmd->chanlist_len);
 945                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 946                                                         (1000000 / 8 * i));
 947                        /* now calc the real sampling rate with all the
 948                         * rounding errors */
 949                        tmpTimer =
 950                            ((unsigned int)(cmd->scan_begin_arg / 125000)) *
 951                            125000;
 952                } else {
 953                        /* full speed */
 954                        /* 1kHz scans every USB frame */
 955                        err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 956                                                         1000000);
 957                        /*
 958                         * calc the real sampling rate with the rounding errors
 959                         */
 960                        tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
 961                                                   1000000)) * 1000000;
 962                }
 963                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
 964                                                tmpTimer);
 965        }
 966
 967        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 968
 969        if (cmd->stop_src == TRIG_COUNT) {
 970                /* any count is allowed */
 971        } else {
 972                /* TRIG_NONE */
 973                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 974        }
 975
 976        if (err)
 977                return 3;
 978
 979        return 0;
 980}
 981
 982/*
 983 * creates the ADC command for the MAX1271
 984 * range is the range value from comedi
 985 */
 986static void create_adc_command(unsigned int chan,
 987                               uint8_t *muxsg0,
 988                               uint8_t *muxsg1)
 989{
 990        if (chan < 8)
 991                (*muxsg0) = (*muxsg0) | (1 << chan);
 992        else if (chan < 16)
 993                (*muxsg1) = (*muxsg1) | (1 << (chan-8));
 994}
 995
 996
 997/* bulk transfers to usbdux */
 998
 999#define SENDADCOMMANDS            0
1000#define SENDDACOMMANDS            1
1001#define SENDDIOCONFIGCOMMAND      2
1002#define SENDDIOBITSCOMMAND        3
1003#define SENDSINGLEAD              4
1004#define SENDPWMON                 7
1005#define SENDPWMOFF                8
1006
1007static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
1008{
1009        int result, nsent;
1010
1011        this_usbduxsub->dux_commands[0] = cmd_type;
1012#ifdef NOISY_DUX_DEBUGBUG
1013        printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
1014               this_usbduxsub->comedidev->minor);
1015        for (result = 0; result < SIZEOFDUXBUFFER; result++)
1016                printk(" %02x", this_usbduxsub->dux_commands[result]);
1017        printk("\n");
1018#endif
1019        result = usb_bulk_msg(this_usbduxsub->usbdev,
1020                              usb_sndbulkpipe(this_usbduxsub->usbdev,
1021                                              COMMAND_OUT_EP),
1022                              this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
1023                              &nsent, BULK_TIMEOUT);
1024        if (result < 0)
1025                dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1026                        "could not transmit dux_command to the usb-device, "
1027                        "err=%d\n", this_usbduxsub->comedidev->minor, result);
1028
1029        return result;
1030}
1031
1032static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
1033{
1034        int result = (-EFAULT);
1035        int nrec;
1036        int i;
1037
1038        for (i = 0; i < RETRIES; i++) {
1039                result = usb_bulk_msg(this_usbduxsub->usbdev,
1040                                      usb_rcvbulkpipe(this_usbduxsub->usbdev,
1041                                                      COMMAND_IN_EP),
1042                                      this_usbduxsub->insnBuffer, SIZEINSNBUF,
1043                                      &nrec, BULK_TIMEOUT);
1044                if (result < 0) {
1045                        dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1046                                "insn: USB error %d "
1047                                "while receiving DUX command"
1048                                "\n", this_usbduxsub->comedidev->minor,
1049                                result);
1050                        return result;
1051                }
1052                if (this_usbduxsub->insnBuffer[0] == command)
1053                        return result;
1054        }
1055        /* this is only reached if the data has been requested a couple of
1056         * times */
1057        dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
1058                "wrong data returned from firmware: want %d, got %d.\n",
1059                this_usbduxsub->comedidev->minor, command,
1060                this_usbduxsub->insnBuffer[0]);
1061        return -EFAULT;
1062}
1063
1064static int usbdux_ai_inttrig(struct comedi_device *dev,
1065                             struct comedi_subdevice *s, unsigned int trignum)
1066{
1067        int ret;
1068        struct usbduxsub *this_usbduxsub = dev->private;
1069        if (!this_usbduxsub)
1070                return -EFAULT;
1071
1072        down(&this_usbduxsub->sem);
1073        if (!(this_usbduxsub->probed)) {
1074                up(&this_usbduxsub->sem);
1075                return -ENODEV;
1076        }
1077        dev_dbg(&this_usbduxsub->interface->dev,
1078                "comedi%d: usbdux_ai_inttrig\n", dev->minor);
1079
1080        if (trignum != 0) {
1081                dev_err(&this_usbduxsub->interface->dev,
1082                        "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
1083                        dev->minor);
1084                up(&this_usbduxsub->sem);
1085                return -EINVAL;
1086        }
1087        if (!(this_usbduxsub->ai_cmd_running)) {
1088                this_usbduxsub->ai_cmd_running = 1;
1089                ret = usbduxsub_submit_InURBs(this_usbduxsub);
1090                if (ret < 0) {
1091                        dev_err(&this_usbduxsub->interface->dev,
1092                                "comedi%d: usbdux_ai_inttrig: "
1093                                "urbSubmit: err=%d\n", dev->minor, ret);
1094                        this_usbduxsub->ai_cmd_running = 0;
1095                        up(&this_usbduxsub->sem);
1096                        return ret;
1097                }
1098                s->async->inttrig = NULL;
1099        } else {
1100                dev_err(&this_usbduxsub->interface->dev,
1101                        "comedi%d: ai_inttrig but acqu is already running\n",
1102                        dev->minor);
1103        }
1104        up(&this_usbduxsub->sem);
1105        return 1;
1106}
1107
1108static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1109{
1110        struct comedi_cmd *cmd = &s->async->cmd;
1111        unsigned int chan;
1112        int i, ret;
1113        struct usbduxsub *this_usbduxsub = dev->private;
1114        int result;
1115        uint8_t muxsg0 = 0;
1116        uint8_t muxsg1 = 0;
1117        uint8_t sysred = 0;
1118
1119        if (!this_usbduxsub)
1120                return -EFAULT;
1121
1122        dev_dbg(&this_usbduxsub->interface->dev,
1123                "comedi%d: usbdux_ai_cmd\n", dev->minor);
1124
1125        /* block other CPUs from starting an ai_cmd */
1126        down(&this_usbduxsub->sem);
1127
1128        if (!(this_usbduxsub->probed)) {
1129                up(&this_usbduxsub->sem);
1130                return -ENODEV;
1131        }
1132        if (this_usbduxsub->ai_cmd_running) {
1133                dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1134                        "ai_cmd not possible. Another ai_cmd is running.\n",
1135                        dev->minor);
1136                up(&this_usbduxsub->sem);
1137                return -EBUSY;
1138        }
1139        /* set current channel of the running acquisition to zero */
1140        s->async->cur_chan = 0;
1141
1142        /* first the number of channels per time step */
1143        this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
1144
1145        /* CONFIG0 */
1146        this_usbduxsub->dux_commands[2] = 0x12;
1147
1148        /* CONFIG1: 23kHz sampling rate, delay = 0us,  */
1149        this_usbduxsub->dux_commands[3] = 0x03;
1150
1151        /* CONFIG3: differential channels off */
1152        this_usbduxsub->dux_commands[4] = 0x00;
1153
1154        for (i = 0; i < cmd->chanlist_len; i++) {
1155                chan = CR_CHAN(cmd->chanlist[i]);
1156                create_adc_command(chan, &muxsg0, &muxsg1);
1157                if (i >= NUMCHANNELS) {
1158                        dev_err(&this_usbduxsub->interface->dev,
1159                                "comedi%d: channel list too long\n",
1160                                dev->minor);
1161                        break;
1162                }
1163        }
1164        this_usbduxsub->dux_commands[5] = muxsg0;
1165        this_usbduxsub->dux_commands[6] = muxsg1;
1166        this_usbduxsub->dux_commands[7] = sysred;
1167
1168        dev_dbg(&this_usbduxsub->interface->dev,
1169                "comedi %d: sending commands to the usb device: size=%u\n",
1170                dev->minor, NUMCHANNELS);
1171
1172        result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
1173        if (result < 0) {
1174                up(&this_usbduxsub->sem);
1175                return result;
1176        }
1177
1178        if (this_usbduxsub->high_speed) {
1179                /*
1180                 * every 2 channels get a time window of 125us. Thus, if we
1181                 * sample all 16 channels we need 1ms. If we sample only one
1182                 * channel we need only 125us
1183                 */
1184                this_usbduxsub->ai_interval =
1185                        chanToInterval(cmd->chanlist_len);
1186                this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
1187                                                          (this_usbduxsub->
1188                                                           ai_interval));
1189        } else {
1190                /* interval always 1ms */
1191                this_usbduxsub->ai_interval = 1;
1192                this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
1193        }
1194        if (this_usbduxsub->ai_timer < 1) {
1195                dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
1196                        "timer=%d, scan_begin_arg=%d. "
1197                        "Not properly tested by cmdtest?\n", dev->minor,
1198                        this_usbduxsub->ai_timer, cmd->scan_begin_arg);
1199                up(&this_usbduxsub->sem);
1200                return -EINVAL;
1201        }
1202        this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
1203
1204        if (cmd->stop_src == TRIG_COUNT) {
1205                /* data arrives as one packet */
1206                this_usbduxsub->ai_sample_count = cmd->stop_arg;
1207                this_usbduxsub->ai_continuous = 0;
1208        } else {
1209                /* continuous acquisition */
1210                this_usbduxsub->ai_continuous = 1;
1211                this_usbduxsub->ai_sample_count = 0;
1212        }
1213
1214        if (cmd->start_src == TRIG_NOW) {
1215                /* enable this acquisition operation */
1216                this_usbduxsub->ai_cmd_running = 1;
1217                ret = usbduxsub_submit_InURBs(this_usbduxsub);
1218                if (ret < 0) {
1219                        this_usbduxsub->ai_cmd_running = 0;
1220                        /* fixme: unlink here?? */
1221                        up(&this_usbduxsub->sem);
1222                        return ret;
1223                }
1224                s->async->inttrig = NULL;
1225        } else {
1226                /* TRIG_INT */
1227                /* don't enable the acquision operation */
1228                /* wait for an internal signal */
1229                s->async->inttrig = usbdux_ai_inttrig;
1230        }
1231        up(&this_usbduxsub->sem);
1232        return 0;
1233}
1234
1235/* Mode 0 is used to get a single conversion on demand */
1236static int usbdux_ai_insn_read(struct comedi_device *dev,
1237                               struct comedi_subdevice *s,
1238                               struct comedi_insn *insn, unsigned int *data)
1239{
1240        int i;
1241        int32_t one = 0;
1242        int chan;
1243        int err;
1244        struct usbduxsub *this_usbduxsub = dev->private;
1245        uint8_t muxsg0 = 0;
1246        uint8_t muxsg1 = 0;
1247        uint8_t sysred = 0;
1248
1249        if (!this_usbduxsub)
1250                return 0;
1251
1252        dev_dbg(&this_usbduxsub->interface->dev,
1253                "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1254                dev->minor, insn->n, insn->subdev);
1255
1256        down(&this_usbduxsub->sem);
1257        if (!(this_usbduxsub->probed)) {
1258                up(&this_usbduxsub->sem);
1259                return -ENODEV;
1260        }
1261        if (this_usbduxsub->ai_cmd_running) {
1262                dev_err(&this_usbduxsub->interface->dev,
1263                        "comedi%d: ai_insn_read not possible. "
1264                        "Async Command is running.\n", dev->minor);
1265                up(&this_usbduxsub->sem);
1266                return 0;
1267        }
1268
1269        /* sample one channel */
1270        /* CONFIG0: chopper on */
1271        this_usbduxsub->dux_commands[1] = 0x16;
1272
1273        /* CONFIG1: 2kHz sampling rate */
1274        this_usbduxsub->dux_commands[2] = 0x80;
1275
1276        /* CONFIG3: differential channels off */
1277        this_usbduxsub->dux_commands[3] = 0x00;
1278
1279        chan = CR_CHAN(insn->chanspec);
1280        create_adc_command(chan, &muxsg0, &muxsg1);
1281
1282        this_usbduxsub->dux_commands[4] = muxsg0;
1283        this_usbduxsub->dux_commands[5] = muxsg1;
1284        this_usbduxsub->dux_commands[6] = sysred;
1285
1286        /* adc commands */
1287        err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1288        if (err < 0) {
1289                up(&this_usbduxsub->sem);
1290                return err;
1291        }
1292
1293        for (i = 0; i < insn->n; i++) {
1294                err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1295                if (err < 0) {
1296                        up(&this_usbduxsub->sem);
1297                        return 0;
1298                }
1299                /* 32 bits big endian from the A/D converter */
1300                one = be32_to_cpu(*((int32_t *)
1301                                    ((this_usbduxsub->insnBuffer)+1)));
1302                /* mask out the status byte */
1303                one = one & 0x00ffffff;
1304                /* turn it into an unsigned integer */
1305                one = one ^ 0x00800000;
1306                data[i] = one;
1307        }
1308        up(&this_usbduxsub->sem);
1309        return i;
1310}
1311
1312
1313
1314
1315static int usbdux_getstatusinfo(struct comedi_device *dev, int chan)
1316{
1317        struct usbduxsub *this_usbduxsub = dev->private;
1318        uint8_t sysred = 0;
1319        uint32_t one;
1320        int err;
1321
1322        if (!this_usbduxsub)
1323                return 0;
1324
1325        if (this_usbduxsub->ai_cmd_running) {
1326                dev_err(&this_usbduxsub->interface->dev,
1327                        "comedi%d: status read not possible. "
1328                        "Async Command is running.\n", dev->minor);
1329                return 0;
1330        }
1331
1332        /* CONFIG0 */
1333        this_usbduxsub->dux_commands[1] = 0x12;
1334
1335        /* CONFIG1: 2kHz sampling rate */
1336        this_usbduxsub->dux_commands[2] = 0x80;
1337
1338        /* CONFIG3: differential channels off */
1339        this_usbduxsub->dux_commands[3] = 0x00;
1340
1341        if (chan == 1) {
1342                /* ADC offset */
1343                sysred = sysred | 1;
1344        } else if (chan == 2) {
1345                /* VCC */
1346                sysred = sysred | 4;
1347        } else if (chan == 3) {
1348                /* temperature */
1349                sysred = sysred | 8;
1350        } else if (chan == 4) {
1351                /* gain */
1352                sysred = sysred | 16;
1353        } else if (chan == 5) {
1354                /* ref */
1355                sysred = sysred | 32;
1356        }
1357
1358        this_usbduxsub->dux_commands[4] = 0;
1359        this_usbduxsub->dux_commands[5] = 0;
1360        this_usbduxsub->dux_commands[6] = sysred;
1361
1362        /* adc commands */
1363        err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1364        if (err < 0)
1365                return err;
1366
1367        err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1368        if (err < 0)
1369                return err;
1370
1371        /* 32 bits big endian from the A/D converter */
1372        one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1)));
1373        /* mask out the status byte */
1374        one = one & 0x00ffffff;
1375        one = one ^ 0x00800000;
1376
1377        return (int)one;
1378}
1379
1380
1381
1382
1383
1384
1385/************************************/
1386/* analog out */
1387
1388static int usbdux_ao_insn_read(struct comedi_device *dev,
1389                               struct comedi_subdevice *s,
1390                               struct comedi_insn *insn, unsigned int *data)
1391{
1392        int i;
1393        int chan = CR_CHAN(insn->chanspec);
1394        struct usbduxsub *this_usbduxsub = dev->private;
1395
1396        if (!this_usbduxsub)
1397                return -EFAULT;
1398
1399        down(&this_usbduxsub->sem);
1400        if (!(this_usbduxsub->probed)) {
1401                up(&this_usbduxsub->sem);
1402                return -ENODEV;
1403        }
1404        for (i = 0; i < insn->n; i++)
1405                data[i] = this_usbduxsub->outBuffer[chan];
1406
1407        up(&this_usbduxsub->sem);
1408        return i;
1409}
1410
1411static int usbdux_ao_insn_write(struct comedi_device *dev,
1412                                struct comedi_subdevice *s,
1413                                struct comedi_insn *insn, unsigned int *data)
1414{
1415        int i, err;
1416        int chan = CR_CHAN(insn->chanspec);
1417        struct usbduxsub *this_usbduxsub = dev->private;
1418
1419        if (!this_usbduxsub)
1420                return -EFAULT;
1421
1422        dev_dbg(&this_usbduxsub->interface->dev,
1423                "comedi%d: ao_insn_write\n", dev->minor);
1424
1425        down(&this_usbduxsub->sem);
1426        if (!(this_usbduxsub->probed)) {
1427                up(&this_usbduxsub->sem);
1428                return -ENODEV;
1429        }
1430        if (this_usbduxsub->ao_cmd_running) {
1431                dev_err(&this_usbduxsub->interface->dev,
1432                        "comedi%d: ao_insn_write: "
1433                        "ERROR: asynchronous ao_cmd is running\n", dev->minor);
1434                up(&this_usbduxsub->sem);
1435                return 0;
1436        }
1437
1438        for (i = 0; i < insn->n; i++) {
1439                dev_dbg(&this_usbduxsub->interface->dev,
1440                        "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1441                        dev->minor, chan, i, data[i]);
1442
1443                /* number of channels: 1 */
1444                this_usbduxsub->dux_commands[1] = 1;
1445                /* channel number */
1446                this_usbduxsub->dux_commands[2] = data[i];
1447                this_usbduxsub->outBuffer[chan] = data[i];
1448                this_usbduxsub->dux_commands[3] = chan;
1449                err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
1450                if (err < 0) {
1451                        up(&this_usbduxsub->sem);
1452                        return err;
1453                }
1454        }
1455        up(&this_usbduxsub->sem);
1456
1457        return i;
1458}
1459
1460static int usbdux_ao_inttrig(struct comedi_device *dev,
1461                             struct comedi_subdevice *s, unsigned int trignum)
1462{
1463        int ret;
1464        struct usbduxsub *this_usbduxsub = dev->private;
1465
1466        if (!this_usbduxsub)
1467                return -EFAULT;
1468
1469        down(&this_usbduxsub->sem);
1470
1471        if (!(this_usbduxsub->probed)) {
1472                ret = -ENODEV;
1473                goto out;
1474        }
1475        if (trignum != 0) {
1476                dev_err(&this_usbduxsub->interface->dev,
1477                        "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1478                        dev->minor);
1479                ret = -EINVAL;
1480                goto out;
1481        }
1482        if (!(this_usbduxsub->ao_cmd_running)) {
1483                this_usbduxsub->ao_cmd_running = 1;
1484                ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1485                if (ret < 0) {
1486                        dev_err(&this_usbduxsub->interface->dev,
1487                                "comedi%d: usbdux_ao_inttrig: submitURB: "
1488                                "err=%d\n", dev->minor, ret);
1489                        this_usbduxsub->ao_cmd_running = 0;
1490                        goto out;
1491                }
1492                s->async->inttrig = NULL;
1493        } else {
1494                dev_err(&this_usbduxsub->interface->dev,
1495                        "comedi%d: ao_inttrig but acqu is already running.\n",
1496                        dev->minor);
1497        }
1498        ret = 1;
1499out:
1500        up(&this_usbduxsub->sem);
1501        return ret;
1502}
1503
1504static int usbdux_ao_cmdtest(struct comedi_device *dev,
1505                             struct comedi_subdevice *s,
1506                             struct comedi_cmd *cmd)
1507{
1508        struct usbduxsub *this_usbduxsub = dev->private;
1509        int err = 0;
1510        unsigned int flags;
1511
1512        if (!this_usbduxsub)
1513                return -EFAULT;
1514
1515        if (!(this_usbduxsub->probed))
1516                return -ENODEV;
1517
1518        dev_dbg(&this_usbduxsub->interface->dev,
1519                "comedi%d: usbdux_ao_cmdtest\n", dev->minor);
1520
1521        /* Step 1 : check if triggers are trivially valid */
1522
1523        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1524
1525        if (0) {                /* (this_usbduxsub->high_speed) */
1526                /*
1527                 * start immediately a new scan
1528                 * the sampling rate is set by the coversion rate
1529                 */
1530                flags = TRIG_FOLLOW;
1531        } else {
1532                /* start a new scan (output at once) with a timer */
1533                flags = TRIG_TIMER;
1534        }
1535        err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1536
1537        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
1538        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1539        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1540
1541        if (err)
1542                return 1;
1543
1544        /* Step 2a : make sure trigger sources are unique */
1545
1546        err |= cfc_check_trigger_is_unique(cmd->start_src);
1547        err |= cfc_check_trigger_is_unique(cmd->stop_src);
1548
1549        /* Step 2b : and mutually compatible */
1550
1551        if (err)
1552                return 2;
1553
1554        /* Step 3: check if arguments are trivially valid */
1555
1556        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1557
1558        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
1559                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1560
1561        if (cmd->scan_begin_src == TRIG_TIMER)
1562                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1563                                                 1000000);
1564
1565        /* not used now, is for later use */
1566        if (cmd->convert_src == TRIG_TIMER)
1567                err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
1568
1569        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1570
1571        if (cmd->stop_src == TRIG_COUNT) {
1572                /* any count is allowed */
1573        } else {
1574                /* TRIG_NONE */
1575                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1576        }
1577
1578        if (err)
1579                return 3;
1580
1581        return 0;
1582}
1583
1584static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1585{
1586        struct comedi_cmd *cmd = &s->async->cmd;
1587        unsigned int chan, gain;
1588        int i, ret;
1589        struct usbduxsub *this_usbduxsub = dev->private;
1590
1591        if (!this_usbduxsub)
1592                return -EFAULT;
1593
1594        down(&this_usbduxsub->sem);
1595        if (!(this_usbduxsub->probed)) {
1596                up(&this_usbduxsub->sem);
1597                return -ENODEV;
1598        }
1599        dev_dbg(&this_usbduxsub->interface->dev,
1600                "comedi%d: %s\n", dev->minor, __func__);
1601
1602        /* set current channel of the running acquisition to zero */
1603        s->async->cur_chan = 0;
1604        for (i = 0; i < cmd->chanlist_len; ++i) {
1605                chan = CR_CHAN(cmd->chanlist[i]);
1606                gain = CR_RANGE(cmd->chanlist[i]);
1607                if (i >= NUMOUTCHANNELS) {
1608                        dev_err(&this_usbduxsub->interface->dev,
1609                                "comedi%d: %s: channel list too long\n",
1610                                dev->minor, __func__);
1611                        break;
1612                }
1613                this_usbduxsub->dac_commands[i] = chan;
1614                dev_dbg(&this_usbduxsub->interface->dev,
1615                        "comedi%d: dac command for ch %d is %x\n",
1616                        dev->minor, i, this_usbduxsub->dac_commands[i]);
1617        }
1618
1619        /* we count in steps of 1ms (125us) */
1620        /* 125us mode not used yet */
1621        if (0) {                /* (this_usbduxsub->high_speed) */
1622                /* 125us */
1623                /* timing of the conversion itself: every 125 us */
1624                this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1625        } else {
1626                /* 1ms */
1627                /* timing of the scan: we get all channels at once */
1628                this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1629                dev_dbg(&this_usbduxsub->interface->dev,
1630                        "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
1631                        "convert_src=%d, convert_arg=%d\n", dev->minor,
1632                        cmd->scan_begin_src, cmd->scan_begin_arg,
1633                        cmd->convert_src, cmd->convert_arg);
1634                dev_dbg(&this_usbduxsub->interface->dev,
1635                        "comedi%d: ao_timer=%d (ms)\n",
1636                        dev->minor, this_usbduxsub->ao_timer);
1637                if (this_usbduxsub->ao_timer < 1) {
1638                        dev_err(&this_usbduxsub->interface->dev,
1639                                "comedi%d: usbdux: ao_timer=%d, "
1640                                "scan_begin_arg=%d. "
1641                                "Not properly tested by cmdtest?\n",
1642                                dev->minor, this_usbduxsub->ao_timer,
1643                                cmd->scan_begin_arg);
1644                        up(&this_usbduxsub->sem);
1645                        return -EINVAL;
1646                }
1647        }
1648        this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1649
1650        if (cmd->stop_src == TRIG_COUNT) {
1651                /* not continuous */
1652                /* counter */
1653                /* high speed also scans everything at once */
1654                if (0) {        /* (this_usbduxsub->high_speed) */
1655                        this_usbduxsub->ao_sample_count =
1656                            (cmd->stop_arg) * (cmd->scan_end_arg);
1657                } else {
1658                        /* there's no scan as the scan has been */
1659                        /* perf inside the FX2 */
1660                        /* data arrives as one packet */
1661                        this_usbduxsub->ao_sample_count = cmd->stop_arg;
1662                }
1663                this_usbduxsub->ao_continuous = 0;
1664        } else {
1665                /* continuous acquisition */
1666                this_usbduxsub->ao_continuous = 1;
1667                this_usbduxsub->ao_sample_count = 0;
1668        }
1669
1670        if (cmd->start_src == TRIG_NOW) {
1671                /* enable this acquisition operation */
1672                this_usbduxsub->ao_cmd_running = 1;
1673                ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1674                if (ret < 0) {
1675                        this_usbduxsub->ao_cmd_running = 0;
1676                        /* fixme: unlink here?? */
1677                        up(&this_usbduxsub->sem);
1678                        return ret;
1679                }
1680                s->async->inttrig = NULL;
1681        } else {
1682                /* TRIG_INT */
1683                /* submit the urbs later */
1684                /* wait for an internal signal */
1685                s->async->inttrig = usbdux_ao_inttrig;
1686        }
1687
1688        up(&this_usbduxsub->sem);
1689        return 0;
1690}
1691
1692static int usbdux_dio_insn_config(struct comedi_device *dev,
1693                                  struct comedi_subdevice *s,
1694                                  struct comedi_insn *insn, unsigned int *data)
1695{
1696        int chan = CR_CHAN(insn->chanspec);
1697
1698        /* The input or output configuration of each digital line is
1699         * configured by a special insn_config instruction.  chanspec
1700         * contains the channel to be changed, and data[0] contains the
1701         * value COMEDI_INPUT or COMEDI_OUTPUT. */
1702
1703        switch (data[0]) {
1704        case INSN_CONFIG_DIO_OUTPUT:
1705                s->io_bits |= 1 << chan;        /* 1 means Out */
1706                break;
1707        case INSN_CONFIG_DIO_INPUT:
1708                s->io_bits &= ~(1 << chan);
1709                break;
1710        case INSN_CONFIG_DIO_QUERY:
1711                data[1] =
1712                    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1713                break;
1714        default:
1715                return -EINVAL;
1716                break;
1717        }
1718        /* we don't tell the firmware here as it would take 8 frames */
1719        /* to submit the information. We do it in the insn_bits. */
1720        return insn->n;
1721}
1722
1723static int usbdux_dio_insn_bits(struct comedi_device *dev,
1724                                struct comedi_subdevice *s,
1725                                struct comedi_insn *insn,
1726                                unsigned int *data)
1727{
1728
1729        struct usbduxsub *this_usbduxsub = dev->private;
1730        int err;
1731
1732        if (!this_usbduxsub)
1733                return -EFAULT;
1734
1735        down(&this_usbduxsub->sem);
1736
1737        if (!(this_usbduxsub->probed)) {
1738                up(&this_usbduxsub->sem);
1739                return -ENODEV;
1740        }
1741
1742        /* The insn data is a mask in data[0] and the new data
1743         * in data[1], each channel cooresponding to a bit. */
1744        s->state &= ~data[0];
1745        s->state |= data[0] & data[1];
1746        /* The commands are 8 bits wide */
1747        this_usbduxsub->dux_commands[1] = (s->io_bits) & 0x000000FF;
1748        this_usbduxsub->dux_commands[4] = (s->state) & 0x000000FF;
1749        this_usbduxsub->dux_commands[2] = ((s->io_bits) & 0x0000FF00) >> 8;
1750        this_usbduxsub->dux_commands[5] = ((s->state) & 0x0000FF00) >> 8;
1751        this_usbduxsub->dux_commands[3] = ((s->io_bits) & 0x00FF0000) >> 16;
1752        this_usbduxsub->dux_commands[6] = ((s->state) & 0x00FF0000) >> 16;
1753
1754        /* This command also tells the firmware to return */
1755        /* the digital input lines */
1756        err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1757        if (err < 0) {
1758                up(&this_usbduxsub->sem);
1759                return err;
1760        }
1761        err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1762        if (err < 0) {
1763                up(&this_usbduxsub->sem);
1764                return err;
1765        }
1766
1767        data[1] = (((unsigned int)(this_usbduxsub->insnBuffer[1]))&0xff) |
1768                ((((unsigned int)(this_usbduxsub->insnBuffer[2]))&0xff) << 8) |
1769                ((((unsigned int)(this_usbduxsub->insnBuffer[3]))&0xff) << 16);
1770
1771        s->state = data[1];
1772
1773        up(&this_usbduxsub->sem);
1774        return insn->n;
1775}
1776
1777/***********************************/
1778/* PWM */
1779
1780static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
1781{
1782        int err = 0;
1783
1784        if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
1785                if (usbduxsub_tmp->urbPwm)
1786                        usb_kill_urb(usbduxsub_tmp->urbPwm);
1787                dev_dbg(&usbduxsub_tmp->interface->dev,
1788                        "comedi: unlinked PwmURB: res=%d\n", err);
1789        }
1790        return err;
1791}
1792
1793/* This cancels a running acquisition operation
1794 * in any context.
1795 */
1796static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
1797{
1798        int ret = 0;
1799
1800        if (!this_usbduxsub)
1801                return -EFAULT;
1802
1803        dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
1804        if (do_unlink)
1805                ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
1806
1807        this_usbduxsub->pwm_cmd_running = 0;
1808
1809        return ret;
1810}
1811
1812/* force unlink - is called by comedi */
1813static int usbdux_pwm_cancel(struct comedi_device *dev,
1814                             struct comedi_subdevice *s)
1815{
1816        struct usbduxsub *this_usbduxsub = dev->private;
1817        int res = 0;
1818
1819        /* unlink only if it is really running */
1820        res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
1821
1822        dev_dbg(&this_usbduxsub->interface->dev,
1823                "comedi %d: sending pwm off command to the usb device.\n",
1824                dev->minor);
1825        res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
1826        if (res < 0)
1827                return res;
1828
1829        return res;
1830}
1831
1832static void usbduxsub_pwm_irq(struct urb *urb)
1833{
1834        int ret;
1835        struct usbduxsub *this_usbduxsub;
1836        struct comedi_device *this_comedidev;
1837        struct comedi_subdevice *s;
1838
1839        /* printk(KERN_DEBUG "PWM: IRQ\n"); */
1840
1841        /* the context variable points to the subdevice */
1842        this_comedidev = urb->context;
1843        /* the private structure of the subdevice is struct usbduxsub */
1844        this_usbduxsub = this_comedidev->private;
1845
1846        s = &this_comedidev->subdevices[SUBDEV_DA];
1847
1848        switch (urb->status) {
1849        case 0:
1850                /* success */
1851                break;
1852
1853        case -ECONNRESET:
1854        case -ENOENT:
1855        case -ESHUTDOWN:
1856        case -ECONNABORTED:
1857                /*
1858                 * after an unlink command, unplug, ... etc
1859                 * no unlink needed here. Already shutting down.
1860                 */
1861                if (this_usbduxsub->pwm_cmd_running)
1862                        usbdux_pwm_stop(this_usbduxsub, 0);
1863
1864                return;
1865
1866        default:
1867                /* a real error */
1868                if (this_usbduxsub->pwm_cmd_running) {
1869                        dev_err(&this_usbduxsub->interface->dev,
1870                                "comedi_: Non-zero urb status received in "
1871                                "pwm intr context: %d\n", urb->status);
1872                        usbdux_pwm_stop(this_usbduxsub, 0);
1873                }
1874                return;
1875        }
1876
1877        /* are we actually running? */
1878        if (!(this_usbduxsub->pwm_cmd_running))
1879                return;
1880
1881        urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
1882        urb->dev = this_usbduxsub->usbdev;
1883        urb->status = 0;
1884        if (this_usbduxsub->pwm_cmd_running) {
1885                ret = usb_submit_urb(urb, GFP_ATOMIC);
1886                if (ret < 0) {
1887                        dev_err(&this_usbduxsub->interface->dev,
1888                                "comedi_: pwm urb resubm failed in int-cont. "
1889                                "ret=%d", ret);
1890                        if (ret == EL2NSYNC)
1891                                dev_err(&this_usbduxsub->interface->dev,
1892                                        "buggy USB host controller or bug in "
1893                                        "IRQ handling!\n");
1894
1895                        /* don't do an unlink here */
1896                        usbdux_pwm_stop(this_usbduxsub, 0);
1897                }
1898        }
1899}
1900
1901static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
1902{
1903        int errFlag;
1904
1905        if (!usbduxsub)
1906                return -EFAULT;
1907
1908        dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
1909
1910        /* in case of a resubmission after an unlink... */
1911        usb_fill_bulk_urb(usbduxsub->urbPwm,
1912                          usbduxsub->usbdev,
1913                          usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
1914                          usbduxsub->urbPwm->transfer_buffer,
1915                          usbduxsub->sizePwmBuf, usbduxsub_pwm_irq,
1916                          usbduxsub->comedidev);
1917
1918        errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
1919        if (errFlag) {
1920                dev_err(&usbduxsub->interface->dev,
1921                        "comedi_: usbduxsigma: pwm: usb_submit_urb error %d\n",
1922                        errFlag);
1923                return errFlag;
1924        }
1925        return 0;
1926}
1927
1928static int usbdux_pwm_period(struct comedi_device *dev,
1929                             struct comedi_subdevice *s, unsigned int period)
1930{
1931        struct usbduxsub *this_usbduxsub = dev->private;
1932        int fx2delay = 255;
1933
1934        if (period < MIN_PWM_PERIOD) {
1935                dev_err(&this_usbduxsub->interface->dev,
1936                        "comedi%d: illegal period setting for pwm.\n",
1937                        dev->minor);
1938                return -EAGAIN;
1939        } else {
1940                fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
1941                if (fx2delay > 255) {
1942                        dev_err(&this_usbduxsub->interface->dev,
1943                                "comedi%d: period %d for pwm is too low.\n",
1944                                dev->minor, period);
1945                        return -EAGAIN;
1946                }
1947        }
1948        this_usbduxsub->pwmDelay = fx2delay;
1949        this_usbduxsub->pwmPeriod = period;
1950        dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
1951                __func__, period, fx2delay);
1952        return 0;
1953}
1954
1955/* is called from insn so there's no need to do all the sanity checks */
1956static int usbdux_pwm_start(struct comedi_device *dev,
1957                            struct comedi_subdevice *s)
1958{
1959        int ret, i;
1960        struct usbduxsub *this_usbduxsub = dev->private;
1961
1962        dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
1963                dev->minor, __func__);
1964
1965        if (this_usbduxsub->pwm_cmd_running) {
1966                /* already running */
1967                return 0;
1968        }
1969
1970        this_usbduxsub->dux_commands[1] = ((uint8_t) this_usbduxsub->pwmDelay);
1971        ret = send_dux_commands(this_usbduxsub, SENDPWMON);
1972        if (ret < 0)
1973                return ret;
1974
1975        /* initialise the buffer */
1976        for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
1977                ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
1978
1979        this_usbduxsub->pwm_cmd_running = 1;
1980        ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
1981        if (ret < 0) {
1982                this_usbduxsub->pwm_cmd_running = 0;
1983                return ret;
1984        }
1985        return 0;
1986}
1987
1988/* generates the bit pattern for PWM with the optional sign bit */
1989static int usbdux_pwm_pattern(struct comedi_device *dev,
1990                              struct comedi_subdevice *s, int channel,
1991                              unsigned int value, unsigned int sign)
1992{
1993        struct usbduxsub *this_usbduxsub = dev->private;
1994        int i, szbuf;
1995        char *pBuf;
1996        char pwm_mask;
1997        char sgn_mask;
1998        char c;
1999
2000        if (!this_usbduxsub)
2001                return -EFAULT;
2002
2003        /* this is the DIO bit which carries the PWM data */
2004        pwm_mask = (1 << channel);
2005        /* this is the DIO bit which carries the optional direction bit */
2006        sgn_mask = (16 << channel);
2007        /* this is the buffer which will be filled with the with bit */
2008        /* pattern for one period */
2009        szbuf = this_usbduxsub->sizePwmBuf;
2010        pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
2011        for (i = 0; i < szbuf; i++) {
2012                c = *pBuf;
2013                /* reset bits */
2014                c = c & (~pwm_mask);
2015                /* set the bit as long as the index is lower than the value */
2016                if (i < value)
2017                        c = c | pwm_mask;
2018                /* set the optional sign bit for a relay */
2019                if (!sign) {
2020                        /* positive value */
2021                        c = c & (~sgn_mask);
2022                } else {
2023                        /* negative value */
2024                        c = c | sgn_mask;
2025                }
2026                *(pBuf++) = c;
2027        }
2028        return 1;
2029}
2030
2031static int usbdux_pwm_write(struct comedi_device *dev,
2032                            struct comedi_subdevice *s,
2033                            struct comedi_insn *insn, unsigned int *data)
2034{
2035        struct usbduxsub *this_usbduxsub = dev->private;
2036
2037        if (!this_usbduxsub)
2038                return -EFAULT;
2039
2040        if ((insn->n) != 1) {
2041                /*
2042                 * doesn't make sense to have more than one value here because
2043                 * it would just overwrite the PWM buffer a couple of times
2044                 */
2045                return -EINVAL;
2046        }
2047
2048        /*
2049         * the sign is set via a special INSN only, this gives us 8 bits for
2050         * normal operation
2051         * relay sign 0 by default
2052         */
2053        return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
2054}
2055
2056static int usbdux_pwm_read(struct comedi_device *x1,
2057                           struct comedi_subdevice *x2, struct comedi_insn *x3,
2058                           unsigned int *x4)
2059{
2060        /* not needed */
2061        return -EINVAL;
2062};
2063
2064/* switches on/off PWM */
2065static int usbdux_pwm_config(struct comedi_device *dev,
2066                             struct comedi_subdevice *s,
2067                             struct comedi_insn *insn, unsigned int *data)
2068{
2069        struct usbduxsub *this_usbduxsub = dev->private;
2070        switch (data[0]) {
2071        case INSN_CONFIG_ARM:
2072                /* switch it on */
2073                dev_dbg(&this_usbduxsub->interface->dev,
2074                        "comedi%d: %s: pwm on\n", dev->minor, __func__);
2075                /*
2076                 * if not zero the PWM is limited to a certain time which is
2077                 * not supported here
2078                 */
2079                if (data[1] != 0)
2080                        return -EINVAL;
2081                return usbdux_pwm_start(dev, s);
2082        case INSN_CONFIG_DISARM:
2083                dev_dbg(&this_usbduxsub->interface->dev,
2084                        "comedi%d: %s: pwm off\n", dev->minor, __func__);
2085                return usbdux_pwm_cancel(dev, s);
2086        case INSN_CONFIG_GET_PWM_STATUS:
2087                /*
2088                 * to check if the USB transmission has failed or in case PWM
2089                 * was limited to n cycles to check if it has terminated
2090                 */
2091                data[1] = this_usbduxsub->pwm_cmd_running;
2092                return 0;
2093        case INSN_CONFIG_PWM_SET_PERIOD:
2094                dev_dbg(&this_usbduxsub->interface->dev,
2095                        "comedi%d: %s: setting period\n", dev->minor,
2096                        __func__);
2097                return usbdux_pwm_period(dev, s, data[1]);
2098        case INSN_CONFIG_PWM_GET_PERIOD:
2099                data[1] = this_usbduxsub->pwmPeriod;
2100                return 0;
2101        case INSN_CONFIG_PWM_SET_H_BRIDGE:
2102                /* value in the first byte and the sign in the second for a
2103                   relay */
2104                return usbdux_pwm_pattern(dev, s,
2105                                          /* the channel number */
2106                                          CR_CHAN(insn->chanspec),
2107                                          /* actual PWM data */
2108                                          data[1],
2109                                          /* just a sign */
2110                                          (data[2] != 0));
2111        case INSN_CONFIG_PWM_GET_H_BRIDGE:
2112                /* values are not kept in this driver, nothing to return */
2113                return -EINVAL;
2114        }
2115        return -EINVAL;
2116}
2117
2118/* end of PWM */
2119/*****************************************************************/
2120
2121static void tidy_up(struct usbduxsub *usbduxsub_tmp)
2122{
2123        int i;
2124
2125        if (!usbduxsub_tmp)
2126                return;
2127        dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
2128
2129        /* shows the usb subsystem that the driver is down */
2130        if (usbduxsub_tmp->interface)
2131                usb_set_intfdata(usbduxsub_tmp->interface, NULL);
2132
2133        usbduxsub_tmp->probed = 0;
2134
2135        if (usbduxsub_tmp->urbIn) {
2136                if (usbduxsub_tmp->ai_cmd_running) {
2137                        usbduxsub_tmp->ai_cmd_running = 0;
2138                        usbduxsub_unlink_InURBs(usbduxsub_tmp);
2139                }
2140                for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
2141                        kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
2142                        usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
2143                        usb_kill_urb(usbduxsub_tmp->urbIn[i]);
2144                        usb_free_urb(usbduxsub_tmp->urbIn[i]);
2145                        usbduxsub_tmp->urbIn[i] = NULL;
2146                }
2147                kfree(usbduxsub_tmp->urbIn);
2148                usbduxsub_tmp->urbIn = NULL;
2149        }
2150        if (usbduxsub_tmp->urbOut) {
2151                if (usbduxsub_tmp->ao_cmd_running) {
2152                        usbduxsub_tmp->ao_cmd_running = 0;
2153                        usbduxsub_unlink_OutURBs(usbduxsub_tmp);
2154                }
2155                for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
2156                        if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
2157                                kfree(usbduxsub_tmp->
2158                                      urbOut[i]->transfer_buffer);
2159                                usbduxsub_tmp->urbOut[i]->transfer_buffer =
2160                                    NULL;
2161                        }
2162                        if (usbduxsub_tmp->urbOut[i]) {
2163                                usb_kill_urb(usbduxsub_tmp->urbOut[i]);
2164                                usb_free_urb(usbduxsub_tmp->urbOut[i]);
2165                                usbduxsub_tmp->urbOut[i] = NULL;
2166                        }
2167                }
2168                kfree(usbduxsub_tmp->urbOut);
2169                usbduxsub_tmp->urbOut = NULL;
2170        }
2171        if (usbduxsub_tmp->urbPwm) {
2172                if (usbduxsub_tmp->pwm_cmd_running) {
2173                        usbduxsub_tmp->pwm_cmd_running = 0;
2174                        usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
2175                }
2176                kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
2177                usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
2178                usb_kill_urb(usbduxsub_tmp->urbPwm);
2179                usb_free_urb(usbduxsub_tmp->urbPwm);
2180                usbduxsub_tmp->urbPwm = NULL;
2181        }
2182        kfree(usbduxsub_tmp->inBuffer);
2183        usbduxsub_tmp->inBuffer = NULL;
2184        kfree(usbduxsub_tmp->insnBuffer);
2185        usbduxsub_tmp->insnBuffer = NULL;
2186        kfree(usbduxsub_tmp->outBuffer);
2187        usbduxsub_tmp->outBuffer = NULL;
2188        kfree(usbduxsub_tmp->dac_commands);
2189        usbduxsub_tmp->dac_commands = NULL;
2190        kfree(usbduxsub_tmp->dux_commands);
2191        usbduxsub_tmp->dux_commands = NULL;
2192        usbduxsub_tmp->ai_cmd_running = 0;
2193        usbduxsub_tmp->ao_cmd_running = 0;
2194        usbduxsub_tmp->pwm_cmd_running = 0;
2195}
2196
2197static int usbduxsigma_attach_common(struct comedi_device *dev,
2198                                     struct usbduxsub *uds)
2199{
2200        int ret;
2201        struct comedi_subdevice *s;
2202        int n_subdevs;
2203        int offset;
2204
2205        down(&uds->sem);
2206        /* pointer back to the corresponding comedi device */
2207        uds->comedidev = dev;
2208
2209        /* set number of subdevices */
2210        if (uds->high_speed)
2211                n_subdevs = 4;  /* with pwm */
2212        else
2213                n_subdevs = 3;  /* without pwm */
2214        ret = comedi_alloc_subdevices(dev, n_subdevs);
2215        if (ret) {
2216                up(&uds->sem);
2217                return ret;
2218        }
2219        /* private structure is also simply the usb-structure */
2220        dev->private = uds;
2221        /* the first subdevice is the A/D converter */
2222        s = &dev->subdevices[SUBDEV_AD];
2223        /* the URBs get the comedi subdevice */
2224        /* which is responsible for reading */
2225        /* this is the subdevice which reads data */
2226        dev->read_subdev = s;
2227        /* the subdevice receives as private structure the */
2228        /* usb-structure */
2229        s->private = NULL;
2230        /* analog input */
2231        s->type = COMEDI_SUBD_AI;
2232        /* readable and ref is to ground, 32 bit wide data! */
2233        s->subdev_flags = SDF_READABLE | SDF_GROUND |
2234                SDF_CMD_READ | SDF_LSAMPL;
2235        /* 16 A/D channels */
2236        s->n_chan = NUMCHANNELS;
2237        /* length of the channellist */
2238        s->len_chanlist = NUMCHANNELS;
2239        /* callback functions */
2240        s->insn_read = usbdux_ai_insn_read;
2241        s->do_cmdtest = usbdux_ai_cmdtest;
2242        s->do_cmd = usbdux_ai_cmd;
2243        s->cancel = usbdux_ai_cancel;
2244        /* max value from the A/D converter (24bit) */
2245        s->maxdata = 0x00FFFFFF;
2246        /* range table to convert to physical units */
2247        s->range_table = (&range_usbdux_ai_range);
2248        /* analog output subdevice */
2249        s = &dev->subdevices[SUBDEV_DA];
2250        /* analog out */
2251        s->type = COMEDI_SUBD_AO;
2252        /* backward pointer */
2253        dev->write_subdev = s;
2254        /* the subdevice receives as private structure the */
2255        /* usb-structure */
2256        s->private = NULL;
2257        /* are writable */
2258        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
2259        /* 4 channels */
2260        s->n_chan = 4;
2261        /* length of the channellist */
2262        s->len_chanlist = 4;
2263        /* 8 bit resolution */
2264        s->maxdata = 0x00ff;
2265        /* unipolar range */
2266        s->range_table = &range_unipolar2_5;
2267        /* callback */
2268        s->do_cmdtest = usbdux_ao_cmdtest;
2269        s->do_cmd = usbdux_ao_cmd;
2270        s->cancel = usbdux_ao_cancel;
2271        s->insn_read = usbdux_ao_insn_read;
2272        s->insn_write = usbdux_ao_insn_write;
2273        /* digital I/O subdevice */
2274        s = &dev->subdevices[SUBDEV_DIO];
2275        s->type = COMEDI_SUBD_DIO;
2276        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2277        /* 8 external and 16 internal channels */
2278        s->n_chan = 24;
2279        s->maxdata = 1;
2280        s->range_table = (&range_digital);
2281        s->insn_bits = usbdux_dio_insn_bits;
2282        s->insn_config = usbdux_dio_insn_config;
2283        /* we don't use it */
2284        s->private = NULL;
2285        if (uds->high_speed) {
2286                /* timer / pwm subdevice */
2287                s = &dev->subdevices[SUBDEV_PWM];
2288                s->type = COMEDI_SUBD_PWM;
2289                s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
2290                s->n_chan = 8;
2291                /* this defines the max duty cycle resolution */
2292                s->maxdata = uds->sizePwmBuf;
2293                s->insn_write = usbdux_pwm_write;
2294                s->insn_read = usbdux_pwm_read;
2295                s->insn_config = usbdux_pwm_config;
2296                usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
2297        }
2298        /* finally decide that it's attached */
2299        uds->attached = 1;
2300        up(&uds->sem);
2301        offset = usbdux_getstatusinfo(dev, 0);
2302        if (offset < 0)
2303                dev_err(&uds->interface->dev,
2304                        "Communication to USBDUXSIGMA failed! Check firmware and cabling.");
2305        dev_info(&uds->interface->dev,
2306                 "comedi%d: attached, ADC_zero = %x\n", dev->minor, offset);
2307        return 0;
2308}
2309
2310static int usbduxsigma_auto_attach(struct comedi_device *dev,
2311                                   unsigned long context_unused)
2312{
2313        struct usb_interface *uinterf = comedi_to_usb_interface(dev);
2314        int ret;
2315        struct usbduxsub *uds;
2316
2317        dev->private = NULL;
2318        down(&start_stop_sem);
2319        uds = usb_get_intfdata(uinterf);
2320        if (!uds || !uds->probed) {
2321                dev_err(dev->class_dev,
2322                        "usbduxsigma: error: auto_attach failed, not connected\n");
2323                ret = -ENODEV;
2324        } else if (uds->attached) {
2325                dev_err(dev->class_dev,
2326                       "usbduxsigma: error: auto_attach failed, already attached\n");
2327                ret = -ENODEV;
2328        } else
2329                ret = usbduxsigma_attach_common(dev, uds);
2330        up(&start_stop_sem);
2331        return ret;
2332}
2333
2334static void usbduxsigma_detach(struct comedi_device *dev)
2335{
2336        struct usbduxsub *usb = dev->private;
2337
2338        if (usb) {
2339                down(&usb->sem);
2340                dev->private = NULL;
2341                usb->attached = 0;
2342                usb->comedidev = NULL;
2343                up(&usb->sem);
2344        }
2345}
2346
2347static struct comedi_driver usbduxsigma_driver = {
2348        .driver_name    = "usbduxsigma",
2349        .module         = THIS_MODULE,
2350        .auto_attach    = usbduxsigma_auto_attach,
2351        .detach         = usbduxsigma_detach,
2352};
2353
2354static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
2355                                                     void *context)
2356{
2357        struct usbduxsub *usbduxsub_tmp = context;
2358        struct usb_interface *uinterf = usbduxsub_tmp->interface;
2359        int ret;
2360
2361        if (fw == NULL) {
2362                dev_err(&uinterf->dev,
2363                        "Firmware complete handler without firmware!\n");
2364                return;
2365        }
2366
2367        /*
2368         * we need to upload the firmware here because fw will be
2369         * freed once we've left this function
2370         */
2371        ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
2372
2373        if (ret) {
2374                dev_err(&uinterf->dev,
2375                        "Could not upload firmware (err=%d)\n", ret);
2376                goto out;
2377        }
2378        comedi_usb_auto_config(uinterf, &usbduxsigma_driver, 0);
2379out:
2380        release_firmware(fw);
2381}
2382
2383static int usbduxsigma_usb_probe(struct usb_interface *uinterf,
2384                                 const struct usb_device_id *id)
2385{
2386        struct usb_device *udev = interface_to_usbdev(uinterf);
2387        struct device *dev = &uinterf->dev;
2388        int i;
2389        int index;
2390        int ret;
2391
2392        dev_dbg(dev, "comedi_: usbdux_: "
2393                "finding a free structure for the usb-device\n");
2394
2395        down(&start_stop_sem);
2396        /* look for a free place in the usbdux array */
2397        index = -1;
2398        for (i = 0; i < NUMUSBDUX; i++) {
2399                if (!(usbduxsub[i].probed)) {
2400                        index = i;
2401                        break;
2402                }
2403        }
2404
2405        /* no more space */
2406        if (index == -1) {
2407                dev_err(dev, "Too many usbduxsigma-devices connected.\n");
2408                up(&start_stop_sem);
2409                return -EMFILE;
2410        }
2411        dev_dbg(dev, "comedi_: usbdux: "
2412                "usbduxsub[%d] is ready to connect to comedi.\n", index);
2413
2414        sema_init(&(usbduxsub[index].sem), 1);
2415        /* save a pointer to the usb device */
2416        usbduxsub[index].usbdev = udev;
2417
2418        /* save the interface itself */
2419        usbduxsub[index].interface = uinterf;
2420        /* get the interface number from the interface */
2421        usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
2422        /* hand the private data over to the usb subsystem */
2423        /* will be needed for disconnect */
2424        usb_set_intfdata(uinterf, &(usbduxsub[index]));
2425
2426        dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
2427
2428        /* test if it is high speed (USB 2.0) */
2429        usbduxsub[index].high_speed =
2430            (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
2431
2432        /* create space for the commands of the DA converter */
2433        usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
2434        if (!usbduxsub[index].dac_commands) {
2435                tidy_up(&(usbduxsub[index]));
2436                up(&start_stop_sem);
2437                return -ENOMEM;
2438        }
2439        /* create space for the commands going to the usb device */
2440        usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
2441        if (!usbduxsub[index].dux_commands) {
2442                tidy_up(&(usbduxsub[index]));
2443                up(&start_stop_sem);
2444                return -ENOMEM;
2445        }
2446        /* create space for the in buffer and set it to zero */
2447        usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
2448        if (!(usbduxsub[index].inBuffer)) {
2449                tidy_up(&(usbduxsub[index]));
2450                up(&start_stop_sem);
2451                return -ENOMEM;
2452        }
2453        /* create space of the instruction buffer */
2454        usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
2455        if (!(usbduxsub[index].insnBuffer)) {
2456                tidy_up(&(usbduxsub[index]));
2457                up(&start_stop_sem);
2458                return -ENOMEM;
2459        }
2460        /* create space for the outbuffer */
2461        usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
2462        if (!(usbduxsub[index].outBuffer)) {
2463                tidy_up(&(usbduxsub[index]));
2464                up(&start_stop_sem);
2465                return -ENOMEM;
2466        }
2467        /* setting to alternate setting 3: enabling iso ep and bulk ep. */
2468        i = usb_set_interface(usbduxsub[index].usbdev,
2469                              usbduxsub[index].ifnum, 3);
2470        if (i < 0) {
2471                dev_err(dev, "comedi_: usbduxsigma%d: "
2472                        "could not set alternate setting 3 in high speed.\n",
2473                        index);
2474                tidy_up(&(usbduxsub[index]));
2475                up(&start_stop_sem);
2476                return -ENODEV;
2477        }
2478        if (usbduxsub[index].high_speed)
2479                usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
2480        else
2481                usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
2482
2483        usbduxsub[index].urbIn = kcalloc(usbduxsub[index].numOfInBuffers,
2484                                         sizeof(struct urb *),
2485                                         GFP_KERNEL);
2486        if (!(usbduxsub[index].urbIn)) {
2487                tidy_up(&(usbduxsub[index]));
2488                up(&start_stop_sem);
2489                return -ENOMEM;
2490        }
2491        for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
2492                /* one frame: 1ms */
2493                usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
2494                if (usbduxsub[index].urbIn[i] == NULL) {
2495                        dev_err(dev, "comedi_: usbduxsigma%d: "
2496                                "Could not alloc. urb(%d)\n", index, i);
2497                        tidy_up(&(usbduxsub[index]));
2498                        up(&start_stop_sem);
2499                        return -ENOMEM;
2500                }
2501                usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
2502                /* will be filled later with a pointer to the comedi-device */
2503                /* and ONLY then the urb should be submitted */
2504                usbduxsub[index].urbIn[i]->context = NULL;
2505                usbduxsub[index].urbIn[i]->pipe =
2506                    usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
2507                usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
2508                usbduxsub[index].urbIn[i]->transfer_buffer =
2509                    kzalloc(SIZEINBUF, GFP_KERNEL);
2510                if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
2511                        tidy_up(&(usbduxsub[index]));
2512                        up(&start_stop_sem);
2513                        return -ENOMEM;
2514                }
2515                usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
2516                usbduxsub[index].urbIn[i]->number_of_packets = 1;
2517                usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
2518                usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
2519                usbduxsub[index].urbIn[i]->iso_frame_desc[0].length =
2520                        SIZEINBUF;
2521        }
2522
2523        /* out */
2524        if (usbduxsub[index].high_speed)
2525                usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
2526        else
2527                usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
2528
2529        usbduxsub[index].urbOut = kcalloc(usbduxsub[index].numOfOutBuffers,
2530                                          sizeof(struct urb *), GFP_KERNEL);
2531        if (!(usbduxsub[index].urbOut)) {
2532                tidy_up(&(usbduxsub[index]));
2533                up(&start_stop_sem);
2534                return -ENOMEM;
2535        }
2536        for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
2537                /* one frame: 1ms */
2538                usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
2539                if (usbduxsub[index].urbOut[i] == NULL) {
2540                        dev_err(dev, "comedi_: usbduxsigma%d: "
2541                                "Could not alloc. urb(%d)\n", index, i);
2542                        tidy_up(&(usbduxsub[index]));
2543                        up(&start_stop_sem);
2544                        return -ENOMEM;
2545                }
2546                usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
2547                /* will be filled later with a pointer to the comedi-device */
2548                /* and ONLY then the urb should be submitted */
2549                usbduxsub[index].urbOut[i]->context = NULL;
2550                usbduxsub[index].urbOut[i]->pipe =
2551                    usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
2552                usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
2553                usbduxsub[index].urbOut[i]->transfer_buffer =
2554                    kzalloc(SIZEOUTBUF, GFP_KERNEL);
2555                if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
2556                        tidy_up(&(usbduxsub[index]));
2557                        up(&start_stop_sem);
2558                        return -ENOMEM;
2559                }
2560                usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
2561                usbduxsub[index].urbOut[i]->number_of_packets = 1;
2562                usbduxsub[index].urbOut[i]->transfer_buffer_length =
2563                        SIZEOUTBUF;
2564                usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
2565                usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
2566                    SIZEOUTBUF;
2567                if (usbduxsub[index].high_speed) {
2568                        /* uframes */
2569                        usbduxsub[index].urbOut[i]->interval = 8;
2570                } else {
2571                        /* frames */
2572                        usbduxsub[index].urbOut[i]->interval = 1;
2573                }
2574        }
2575
2576        /* pwm */
2577        if (usbduxsub[index].high_speed) {
2578                /* max bulk ep size in high speed */
2579                usbduxsub[index].sizePwmBuf = 512;
2580                usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
2581                if (usbduxsub[index].urbPwm == NULL) {
2582                        dev_err(dev, "comedi_: usbduxsigma%d: "
2583                                "Could not alloc. pwm urb\n", index);
2584                        tidy_up(&(usbduxsub[index]));
2585                        up(&start_stop_sem);
2586                        return -ENOMEM;
2587                }
2588                usbduxsub[index].urbPwm->transfer_buffer =
2589                    kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
2590                if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
2591                        tidy_up(&(usbduxsub[index]));
2592                        up(&start_stop_sem);
2593                        return -ENOMEM;
2594                }
2595        } else {
2596                usbduxsub[index].urbPwm = NULL;
2597                usbduxsub[index].sizePwmBuf = 0;
2598        }
2599
2600        usbduxsub[index].ai_cmd_running = 0;
2601        usbduxsub[index].ao_cmd_running = 0;
2602        usbduxsub[index].pwm_cmd_running = 0;
2603
2604        /* we've reached the bottom of the function */
2605        usbduxsub[index].probed = 1;
2606        up(&start_stop_sem);
2607
2608        ret = request_firmware_nowait(THIS_MODULE,
2609                                      FW_ACTION_HOTPLUG,
2610                                      FIRMWARE,
2611                                      &udev->dev,
2612                                      GFP_KERNEL,
2613                                      usbduxsub + index,
2614                                      usbdux_firmware_request_complete_handler
2615                                      );
2616
2617        if (ret) {
2618                dev_err(dev, "Could not load firmware (err=%d)\n", ret);
2619                return ret;
2620        }
2621
2622        dev_info(dev, "comedi_: successfully initialised.\n");
2623        /* success */
2624        return 0;
2625}
2626
2627static void usbduxsigma_usb_disconnect(struct usb_interface *intf)
2628{
2629        struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
2630        struct usb_device *udev = interface_to_usbdev(intf);
2631
2632        if (!usbduxsub_tmp) {
2633                dev_err(&intf->dev,
2634                        "comedi_: disconnect called with null pointer.\n");
2635                return;
2636        }
2637        if (usbduxsub_tmp->usbdev != udev) {
2638                dev_err(&intf->dev, "comedi_: BUG! wrong ptr!\n");
2639                return;
2640        }
2641        if (usbduxsub_tmp->ai_cmd_running)
2642                /* we are still running a command */
2643                usbdux_ai_stop(usbduxsub_tmp, 1);
2644        if (usbduxsub_tmp->ao_cmd_running)
2645                /* we are still running a command */
2646                usbdux_ao_stop(usbduxsub_tmp, 1);
2647        comedi_usb_auto_unconfig(intf);
2648        down(&start_stop_sem);
2649        down(&usbduxsub_tmp->sem);
2650        tidy_up(usbduxsub_tmp);
2651        up(&usbduxsub_tmp->sem);
2652        up(&start_stop_sem);
2653        dev_info(&intf->dev, "comedi_: disconnected from the usb\n");
2654}
2655
2656static const struct usb_device_id usbduxsigma_usb_table[] = {
2657        { USB_DEVICE(0x13d8, 0x0020) },
2658        { USB_DEVICE(0x13d8, 0x0021) },
2659        { USB_DEVICE(0x13d8, 0x0022) },
2660        { }
2661};
2662MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
2663
2664static struct usb_driver usbduxsigma_usb_driver = {
2665        .name           = "usbduxsigma",
2666        .probe          = usbduxsigma_usb_probe,
2667        .disconnect     = usbduxsigma_usb_disconnect,
2668        .id_table       = usbduxsigma_usb_table,
2669};
2670module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
2671
2672MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
2673MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
2674MODULE_LICENSE("GPL");
2675MODULE_FIRMWARE(FIRMWARE);
2676