linux/drivers/staging/comedi/drivers/usbduxfast.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.com
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17 */
  18
  19/*
  20 * I must give credit here to Chris Baugher who
  21 * wrote the driver for AT-MIO-16d. I used some parts of this
  22 * driver. I also must give credits to David Brownell
  23 * who supported me with the USB development.
  24 *
  25 * Bernd Porr
  26 *
  27 *
  28 * Revision history:
  29 * 0.9: Dropping the first data packet which seems to be from the last transfer.
  30 *      Buffer overflows in the FX2 are handed over to comedi.
  31 * 0.92: Dropping now 4 packets. The quad buffer has to be emptied.
  32 *       Added insn command basically for testing. Sample rate is
  33 *       1MHz/16ch=62.5kHz
  34 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
  35 * 0.99a: added external trigger.
  36 * 1.00: added firmware kernel request to the driver which fixed
  37 *       udev coldplug problem
  38 */
  39
  40#include <linux/kernel.h>
  41#include <linux/firmware.h>
  42#include <linux/module.h>
  43#include <linux/init.h>
  44#include <linux/slab.h>
  45#include <linux/input.h>
  46#include <linux/usb.h>
  47#include <linux/smp_lock.h>
  48#include <linux/fcntl.h>
  49#include <linux/compiler.h>
  50#include "comedi_fc.h"
  51#include "../comedidev.h"
  52
  53#define DRIVER_VERSION "v1.0"
  54#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
  55#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com"
  56#define BOARDNAME "usbduxfast"
  57
  58/*
  59 * timeout for the USB-transfer
  60 */
  61#define EZTIMEOUT       30
  62
  63/*
  64 * constants for "firmware" upload and download
  65 */
  66#define USBDUXFASTSUB_FIRMWARE  0xA0
  67#define VENDOR_DIR_IN           0xC0
  68#define VENDOR_DIR_OUT          0x40
  69
  70/*
  71 * internal adresses of the 8051 processor
  72 */
  73#define USBDUXFASTSUB_CPUCS     0xE600
  74
  75/*
  76 * max lenghth of the transfer-buffer for software upload
  77 */
  78#define TB_LEN  0x2000
  79
  80/*
  81 * input endpoint number
  82 */
  83#define BULKINEP        6
  84
  85/*
  86 * endpoint for the A/D channellist: bulk OUT
  87 */
  88#define CHANNELLISTEP   4
  89
  90/*
  91 * number of channels
  92 */
  93#define NUMCHANNELS     32
  94
  95/*
  96 * size of the waveform descriptor
  97 */
  98#define WAVESIZE        0x20
  99
 100/*
 101 * size of one A/D value
 102 */
 103#define SIZEADIN        (sizeof(int16_t))
 104
 105/*
 106 * size of the input-buffer IN BYTES
 107 */
 108#define SIZEINBUF       512
 109
 110/*
 111 * 16 bytes
 112 */
 113#define SIZEINSNBUF     512
 114
 115/*
 116 * size of the buffer for the dux commands in bytes
 117 */
 118#define SIZEOFDUXBUFFER 256
 119
 120/*
 121 * number of in-URBs which receive the data: min=5
 122 */
 123#define NUMOFINBUFFERSHIGH      10
 124
 125/*
 126 * total number of usbduxfast devices
 127 */
 128#define NUMUSBDUXFAST   16
 129
 130/*
 131 * number of subdevices
 132 */
 133#define N_SUBDEVICES    1
 134
 135/*
 136 * analogue in subdevice
 137 */
 138#define SUBDEV_AD       0
 139
 140/*
 141 * min delay steps for more than one channel
 142 * basically when the mux gives up ;-)
 143 *
 144 * steps at 30MHz in the FX2
 145 */
 146#define MIN_SAMPLING_PERIOD     9
 147
 148/*
 149 * max number of 1/30MHz delay steps
 150 */
 151#define MAX_SAMPLING_PERIOD     500
 152
 153/*
 154 * number of received packets to ignore before we start handing data
 155 * over to comedi, it's quad buffering and we have to ignore 4 packets
 156 */
 157#define PACKETS_TO_IGNORE       4
 158
 159/*
 160 * comedi constants
 161 */
 162static const struct comedi_lrange range_usbduxfast_ai_range = {
 163        2, {BIP_RANGE(0.75), BIP_RANGE(0.5)}
 164};
 165
 166/*
 167 * private structure of one subdevice
 168 *
 169 * this is the structure which holds all the data of this driver
 170 * one sub device just now: A/D
 171 */
 172struct usbduxfastsub_s {
 173        int attached;           /* is attached? */
 174        int probed;             /* is it associated with a subdevice? */
 175        struct usb_device *usbdev;      /* pointer to the usb-device */
 176        struct urb *urbIn;      /* BULK-transfer handling: urb */
 177        int8_t *transfer_buffer;
 178        int16_t *insnBuffer;    /* input buffer for single insn */
 179        int ifnum;              /* interface number */
 180        struct usb_interface *interface;        /* interface structure */
 181        struct comedi_device *comedidev;        /* comedi device for the interrupt
 182                                                   context */
 183        short int ai_cmd_running;       /* asynchronous command is running */
 184        short int ai_continous; /* continous aquisition */
 185        long int ai_sample_count;       /* number of samples to aquire */
 186        uint8_t *dux_commands;  /* commands */
 187        int ignore;             /* counter which ignores the first
 188                                   buffers */
 189        struct semaphore sem;
 190};
 191
 192/*
 193 * The pointer to the private usb-data of the driver
 194 * is also the private data for the comedi-device.
 195 * This has to be global as the usb subsystem needs
 196 * global variables. The other reason is that this
 197 * structure must be there _before_ any comedi
 198 * command is issued. The usb subsystem must be
 199 * initialised before comedi can access it.
 200 */
 201static struct usbduxfastsub_s usbduxfastsub[NUMUSBDUXFAST];
 202
 203static DECLARE_MUTEX(start_stop_sem);
 204
 205/*
 206 * bulk transfers to usbduxfast
 207 */
 208#define SENDADCOMMANDS            0
 209#define SENDINITEP6               1
 210
 211static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type)
 212{
 213        int tmp, nsent;
 214
 215        udfs->dux_commands[0] = cmd_type;
 216
 217#ifdef CONFIG_COMEDI_DEBUG
 218        printk(KERN_DEBUG "comedi%d: usbduxfast: dux_commands: ",
 219               udfs->comedidev->minor);
 220        for (tmp = 0; tmp < SIZEOFDUXBUFFER; tmp++)
 221                printk(" %02x", udfs->dux_commands[tmp]);
 222        printk("\n");
 223#endif
 224
 225        tmp = usb_bulk_msg(udfs->usbdev,
 226                           usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP),
 227                           udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000);
 228        if (tmp < 0)
 229                printk(KERN_ERR "comedi%d: could not transmit dux_commands to"
 230                       "the usb-device, err=%d\n", udfs->comedidev->minor, tmp);
 231        return tmp;
 232}
 233
 234/*
 235 * Stops the data acquision.
 236 * It should be safe to call this function from any context.
 237 */
 238static int usbduxfastsub_unlink_InURBs(struct usbduxfastsub_s *udfs)
 239{
 240        int j = 0;
 241        int err = 0;
 242
 243        if (udfs && udfs->urbIn) {
 244                udfs->ai_cmd_running = 0;
 245                /* waits until a running transfer is over */
 246                usb_kill_urb(udfs->urbIn);
 247                j = 0;
 248        }
 249#ifdef CONFIG_COMEDI_DEBUG
 250        printk(KERN_DEBUG "comedi: usbduxfast: unlinked InURB: res=%d\n", j);
 251#endif
 252        return err;
 253}
 254
 255/*
 256 * This will stop a running acquisition operation.
 257 * Is called from within this driver from both the
 258 * interrupt context and from comedi.
 259 */
 260static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink)
 261{
 262        int ret = 0;
 263
 264        if (!udfs) {
 265                printk(KERN_ERR "comedi?: usbduxfast_ai_stop: udfs=NULL!\n");
 266                return -EFAULT;
 267        }
 268#ifdef CONFIG_COMEDI_DEBUG
 269        printk(KERN_DEBUG "comedi: usbduxfast_ai_stop\n");
 270#endif
 271
 272        udfs->ai_cmd_running = 0;
 273
 274        if (do_unlink)
 275                ret = usbduxfastsub_unlink_InURBs(udfs);        /* stop aquistion */
 276
 277        return ret;
 278}
 279
 280/*
 281 * This will cancel a running acquisition operation.
 282 * This is called by comedi but never from inside the driver.
 283 */
 284static int usbduxfast_ai_cancel(struct comedi_device *dev,
 285                                struct comedi_subdevice *s)
 286{
 287        struct usbduxfastsub_s *udfs;
 288        int ret;
 289
 290        /* force unlink of all urbs */
 291#ifdef CONFIG_COMEDI_DEBUG
 292        printk(KERN_DEBUG "comedi: usbduxfast_ai_cancel\n");
 293#endif
 294        udfs = dev->private;
 295        if (!udfs) {
 296                printk(KERN_ERR "comedi: usbduxfast_ai_cancel: udfs=NULL\n");
 297                return -EFAULT;
 298        }
 299        down(&udfs->sem);
 300        if (!udfs->probed) {
 301                up(&udfs->sem);
 302                return -ENODEV;
 303        }
 304        /* unlink */
 305        ret = usbduxfast_ai_stop(udfs, 1);
 306        up(&udfs->sem);
 307
 308        return ret;
 309}
 310
 311/*
 312 * analogue IN
 313 * interrupt service routine
 314 */
 315static void usbduxfastsub_ai_Irq(struct urb *urb)
 316{
 317        int n, err;
 318        struct usbduxfastsub_s *udfs;
 319        struct comedi_device *this_comedidev;
 320        struct comedi_subdevice *s;
 321        uint16_t *p;
 322
 323        /* sanity checks - is the urb there? */
 324        if (!urb) {
 325                printk(KERN_ERR "comedi_: usbduxfast_: ao int-handler called "
 326                       "with urb=NULL!\n");
 327                return;
 328        }
 329        /* the context variable points to the subdevice */
 330        this_comedidev = urb->context;
 331        if (!this_comedidev) {
 332                printk(KERN_ERR "comedi_: usbduxfast_: urb context is a NULL "
 333                       "pointer!\n");
 334                return;
 335        }
 336        /* the private structure of the subdevice is usbduxfastsub_s */
 337        udfs = this_comedidev->private;
 338        if (!udfs) {
 339                printk(KERN_ERR "comedi_: usbduxfast_: private of comedi "
 340                       "subdev is a NULL pointer!\n");
 341                return;
 342        }
 343        /* are we running a command? */
 344        if (unlikely(!udfs->ai_cmd_running)) {
 345                /*
 346                 * not running a command
 347                 * do not continue execution if no asynchronous command
 348                 * is running in particular not resubmit
 349                 */
 350                return;
 351        }
 352
 353        if (unlikely(!udfs->attached)) {
 354                /* no comedi device there */
 355                return;
 356        }
 357        /* subdevice which is the AD converter */
 358        s = this_comedidev->subdevices + SUBDEV_AD;
 359
 360        /* first we test if something unusual has just happened */
 361        switch (urb->status) {
 362        case 0:
 363                break;
 364
 365                /*
 366                 * happens after an unlink command or when the device
 367                 * is plugged out
 368                 */
 369        case -ECONNRESET:
 370        case -ENOENT:
 371        case -ESHUTDOWN:
 372        case -ECONNABORTED:
 373                /* tell this comedi */
 374                s->async->events |= COMEDI_CB_EOA;
 375                s->async->events |= COMEDI_CB_ERROR;
 376                comedi_event(udfs->comedidev, s);
 377                /* stop the transfer w/o unlink */
 378                usbduxfast_ai_stop(udfs, 0);
 379                return;
 380
 381        default:
 382                printk("comedi%d: usbduxfast: non-zero urb status received in "
 383                       "ai intr context: %d\n",
 384                       udfs->comedidev->minor, urb->status);
 385                s->async->events |= COMEDI_CB_EOA;
 386                s->async->events |= COMEDI_CB_ERROR;
 387                comedi_event(udfs->comedidev, s);
 388                usbduxfast_ai_stop(udfs, 0);
 389                return;
 390        }
 391
 392        p = urb->transfer_buffer;
 393        if (!udfs->ignore) {
 394                if (!udfs->ai_continous) {
 395                        /* not continous, fixed number of samples */
 396                        n = urb->actual_length / sizeof(uint16_t);
 397                        if (unlikely(udfs->ai_sample_count < n)) {
 398                                /*
 399                                 * we have send only a fraction of the bytes
 400                                 * received
 401                                 */
 402                                cfc_write_array_to_buffer(s,
 403                                                          urb->transfer_buffer,
 404                                                          udfs->ai_sample_count
 405                                                          * sizeof(uint16_t));
 406                                usbduxfast_ai_stop(udfs, 0);
 407                                /* tell comedi that the acquistion is over */
 408                                s->async->events |= COMEDI_CB_EOA;
 409                                comedi_event(udfs->comedidev, s);
 410                                return;
 411                        }
 412                        udfs->ai_sample_count -= n;
 413                }
 414                /* write the full buffer to comedi */
 415                err = cfc_write_array_to_buffer(s, urb->transfer_buffer,
 416                                                urb->actual_length);
 417                if (unlikely(err == 0)) {
 418                        /* buffer overflow */
 419                        usbduxfast_ai_stop(udfs, 0);
 420                        return;
 421                }
 422
 423                /* tell comedi that data is there */
 424                comedi_event(udfs->comedidev, s);
 425
 426        } else {
 427                /* ignore this packet */
 428                udfs->ignore--;
 429        }
 430
 431        /*
 432         * command is still running
 433         * resubmit urb for BULK transfer
 434         */
 435        urb->dev = udfs->usbdev;
 436        urb->status = 0;
 437        err = usb_submit_urb(urb, GFP_ATOMIC);
 438        if (err < 0) {
 439                printk(KERN_ERR "comedi%d: usbduxfast: urb resubm failed: %d",
 440                       udfs->comedidev->minor, err);
 441                s->async->events |= COMEDI_CB_EOA;
 442                s->async->events |= COMEDI_CB_ERROR;
 443                comedi_event(udfs->comedidev, s);
 444                usbduxfast_ai_stop(udfs, 0);
 445        }
 446}
 447
 448static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
 449{
 450        int ret;
 451        unsigned char local_transfer_buffer[16];
 452
 453        /* 7f92 to zero */
 454        local_transfer_buffer[0] = 0;
 455        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,   /* bRequest, "Firmware" */
 456                              VENDOR_DIR_OUT,   /* bmRequestType */
 457                              USBDUXFASTSUB_CPUCS,      /* Value */
 458                              0x0000,   /* Index */
 459                              local_transfer_buffer,    /* address of the transfer buffer */
 460                              1,        /* Length */
 461                              EZTIMEOUT);       /* Timeout */
 462        if (ret < 0) {
 463                printk("comedi_: usbduxfast_: control msg failed (start)\n");
 464                return ret;
 465        }
 466
 467        return 0;
 468}
 469
 470static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
 471{
 472        int ret;
 473        unsigned char local_transfer_buffer[16];
 474
 475        /* 7f92 to one */
 476        local_transfer_buffer[0] = 1;
 477        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,   /* bRequest, "Firmware" */
 478                              VENDOR_DIR_OUT,   /* bmRequestType */
 479                              USBDUXFASTSUB_CPUCS,      /* Value */
 480                              0x0000,   /* Index */
 481                              local_transfer_buffer, 1, /* Length */
 482                              EZTIMEOUT);       /* Timeout */
 483        if (ret < 0) {
 484                printk(KERN_ERR "comedi_: usbduxfast: control msg failed "
 485                       "(stop)\n");
 486                return ret;
 487        }
 488
 489        return 0;
 490}
 491
 492static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
 493                                unsigned char *local_transfer_buffer,
 494                                unsigned int startAddr, unsigned int len)
 495{
 496        int ret;
 497
 498#ifdef CONFIG_COMEDI_DEBUG
 499        printk(KERN_DEBUG "comedi: usbduxfast: uploading %d bytes", len);
 500        printk(KERN_DEBUG " to addr %d, first byte=%d.\n",
 501               startAddr, local_transfer_buffer[0]);
 502#endif
 503        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE,   /* brequest, firmware */
 504                              VENDOR_DIR_OUT,   /* bmRequestType */
 505                              startAddr,        /* value */
 506                              0x0000,   /* index */
 507                              local_transfer_buffer,    /* our local safe buffer */
 508                              len,      /* length */
 509                              EZTIMEOUT);       /* timeout */
 510
 511#ifdef CONFIG_COMEDI_DEBUG
 512        printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret);
 513#endif
 514
 515        if (ret < 0) {
 516                printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n");
 517                return ret;
 518        }
 519
 520        return 0;
 521}
 522
 523int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
 524{
 525        int ret;
 526
 527        if (!udfs)
 528                return -EFAULT;
 529
 530        usb_fill_bulk_urb(udfs->urbIn, udfs->usbdev,
 531                          usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
 532                          udfs->transfer_buffer,
 533                          SIZEINBUF, usbduxfastsub_ai_Irq, udfs->comedidev);
 534
 535#ifdef CONFIG_COMEDI_DEBUG
 536        printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
 537               "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
 538               udfs->urbIn->dev);
 539#endif
 540        ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC);
 541        if (ret) {
 542                printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error"
 543                       " %d\n", ret);
 544                return ret;
 545        }
 546        return 0;
 547}
 548
 549static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
 550                                 struct comedi_subdevice *s,
 551                                 struct comedi_cmd *cmd)
 552{
 553        int err = 0, stop_mask = 0;
 554        long int steps, tmp;
 555        int minSamplPer;
 556        struct usbduxfastsub_s *udfs = dev->private;
 557
 558        if (!udfs->probed)
 559                return -ENODEV;
 560
 561#ifdef CONFIG_COMEDI_DEBUG
 562        printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmdtest\n", dev->minor);
 563        printk(KERN_DEBUG "comedi%d: usbduxfast: convert_arg=%u "
 564               "scan_begin_arg=%u\n",
 565               dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
 566#endif
 567        /* step 1: make sure trigger sources are trivially valid */
 568
 569        tmp = cmd->start_src;
 570        cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
 571        if (!cmd->start_src || tmp != cmd->start_src)
 572                err++;
 573
 574        tmp = cmd->scan_begin_src;
 575        cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
 576        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
 577                err++;
 578
 579        tmp = cmd->convert_src;
 580        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
 581        if (!cmd->convert_src || tmp != cmd->convert_src)
 582                err++;
 583
 584        tmp = cmd->scan_end_src;
 585        cmd->scan_end_src &= TRIG_COUNT;
 586        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
 587                err++;
 588
 589        tmp = cmd->stop_src;
 590        stop_mask = TRIG_COUNT | TRIG_NONE;
 591        cmd->stop_src &= stop_mask;
 592        if (!cmd->stop_src || tmp != cmd->stop_src)
 593                err++;
 594
 595        if (err)
 596                return 1;
 597
 598        /*
 599         * step 2: make sure trigger sources are unique and mutually compatible
 600         */
 601
 602        if (cmd->start_src != TRIG_NOW &&
 603            cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT)
 604                err++;
 605        if (cmd->scan_begin_src != TRIG_TIMER &&
 606            cmd->scan_begin_src != TRIG_FOLLOW &&
 607            cmd->scan_begin_src != TRIG_EXT)
 608                err++;
 609        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
 610                err++;
 611        if (cmd->stop_src != TRIG_COUNT &&
 612            cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
 613                err++;
 614
 615        /* can't have external stop and start triggers at once */
 616        if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
 617                err++;
 618
 619        if (err)
 620                return 2;
 621
 622        /* step 3: make sure arguments are trivially compatible */
 623
 624        if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) {
 625                cmd->start_arg = 0;
 626                err++;
 627        }
 628
 629        if (!cmd->chanlist_len)
 630                err++;
 631
 632        if (cmd->scan_end_arg != cmd->chanlist_len) {
 633                cmd->scan_end_arg = cmd->chanlist_len;
 634                err++;
 635        }
 636
 637        if (cmd->chanlist_len == 1)
 638                minSamplPer = 1;
 639        else
 640                minSamplPer = MIN_SAMPLING_PERIOD;
 641
 642        if (cmd->convert_src == TRIG_TIMER) {
 643                steps = cmd->convert_arg * 30;
 644                if (steps < (minSamplPer * 1000))
 645                        steps = minSamplPer * 1000;
 646
 647                if (steps > (MAX_SAMPLING_PERIOD * 1000))
 648                        steps = MAX_SAMPLING_PERIOD * 1000;
 649
 650                /* calc arg again */
 651                tmp = steps / 30;
 652                if (cmd->convert_arg != tmp) {
 653                        cmd->convert_arg = tmp;
 654                        err++;
 655                }
 656        }
 657
 658        if (cmd->scan_begin_src == TRIG_TIMER)
 659                err++;
 660
 661        /* stop source */
 662        switch (cmd->stop_src) {
 663        case TRIG_COUNT:
 664                if (!cmd->stop_arg) {
 665                        cmd->stop_arg = 1;
 666                        err++;
 667                }
 668                break;
 669        case TRIG_NONE:
 670                if (cmd->stop_arg != 0) {
 671                        cmd->stop_arg = 0;
 672                        err++;
 673                }
 674                break;
 675                /*
 676                 * TRIG_EXT doesn't care since it doesn't trigger
 677                 * off a numbered channel
 678                 */
 679        default:
 680                break;
 681        }
 682
 683        if (err)
 684                return 3;
 685
 686        /* step 4: fix up any arguments */
 687
 688        return 0;
 689
 690}
 691
 692static int usbduxfast_ai_inttrig(struct comedi_device *dev,
 693                                 struct comedi_subdevice *s,
 694                                 unsigned int trignum)
 695{
 696        int ret;
 697        struct usbduxfastsub_s *udfs = dev->private;
 698
 699        if (!udfs)
 700                return -EFAULT;
 701
 702        down(&udfs->sem);
 703        if (!udfs->probed) {
 704                up(&udfs->sem);
 705                return -ENODEV;
 706        }
 707#ifdef CONFIG_COMEDI_DEBUG
 708        printk(KERN_DEBUG "comedi%d: usbduxfast_ai_inttrig\n", dev->minor);
 709#endif
 710
 711        if (trignum != 0) {
 712                printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid"
 713                       " trignum\n", dev->minor);
 714                up(&udfs->sem);
 715                return -EINVAL;
 716        }
 717        if (!udfs->ai_cmd_running) {
 718                udfs->ai_cmd_running = 1;
 719                ret = usbduxfastsub_submit_InURBs(udfs);
 720                if (ret < 0) {
 721                        printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: "
 722                               "urbSubmit: err=%d\n", dev->minor, ret);
 723                        udfs->ai_cmd_running = 0;
 724                        up(&udfs->sem);
 725                        return ret;
 726                }
 727                s->async->inttrig = NULL;
 728        } else {
 729                printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already"
 730                       " running\n", dev->minor);
 731        }
 732        up(&udfs->sem);
 733        return 1;
 734}
 735
 736/*
 737 * offsets for the GPIF bytes
 738 * the first byte is the command byte
 739 */
 740#define LENBASE (1+0x00)
 741#define OPBASE  (1+0x08)
 742#define OUTBASE (1+0x10)
 743#define LOGBASE (1+0x18)
 744
 745static int usbduxfast_ai_cmd(struct comedi_device *dev,
 746                             struct comedi_subdevice *s)
 747{
 748        struct comedi_cmd *cmd = &s->async->cmd;
 749        unsigned int chan, gain, rngmask = 0xff;
 750        int i, j, ret;
 751        struct usbduxfastsub_s *udfs;
 752        int result;
 753        long steps, steps_tmp;
 754
 755#ifdef CONFIG_COMEDI_DEBUG
 756        printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmd\n", dev->minor);
 757#endif
 758        udfs = dev->private;
 759        if (!udfs)
 760                return -EFAULT;
 761
 762        down(&udfs->sem);
 763        if (!udfs->probed) {
 764                up(&udfs->sem);
 765                return -ENODEV;
 766        }
 767        if (udfs->ai_cmd_running) {
 768                printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd"
 769                       " is running.\n", dev->minor);
 770                up(&udfs->sem);
 771                return -EBUSY;
 772        }
 773        /* set current channel of the running aquisition to zero */
 774        s->async->cur_chan = 0;
 775
 776        /*
 777         * ignore the first buffers from the device if there
 778         * is an error condition
 779         */
 780        udfs->ignore = PACKETS_TO_IGNORE;
 781
 782        if (cmd->chanlist_len > 0) {
 783                gain = CR_RANGE(cmd->chanlist[0]);
 784                for (i = 0; i < cmd->chanlist_len; ++i) {
 785                        chan = CR_CHAN(cmd->chanlist[i]);
 786                        if (chan != i) {
 787                                printk(KERN_ERR "comedi%d: cmd is accepting "
 788                                       "only consecutive channels.\n",
 789                                       dev->minor);
 790                                up(&udfs->sem);
 791                                return -EINVAL;
 792                        }
 793                        if ((gain != CR_RANGE(cmd->chanlist[i]))
 794                            && (cmd->chanlist_len > 3)) {
 795                                printk(KERN_ERR "comedi%d: the gain must be"
 796                                       " the same for all channels.\n",
 797                                       dev->minor);
 798                                up(&udfs->sem);
 799                                return -EINVAL;
 800                        }
 801                        if (i >= NUMCHANNELS) {
 802                                printk(KERN_ERR "comedi%d: channel list too"
 803                                       " long\n", dev->minor);
 804                                break;
 805                        }
 806                }
 807        }
 808        steps = 0;
 809        if (cmd->scan_begin_src == TRIG_TIMER) {
 810                printk(KERN_ERR "comedi%d: usbduxfast: "
 811                       "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
 812                up(&udfs->sem);
 813                return -EINVAL;
 814        }
 815        if (cmd->convert_src == TRIG_TIMER)
 816                steps = (cmd->convert_arg * 30) / 1000;
 817
 818        if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
 819                printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, "
 820                       "scan_begin_arg=%d. Not properly tested by cmdtest?\n",
 821                       dev->minor, steps, cmd->scan_begin_arg);
 822                up(&udfs->sem);
 823                return -EINVAL;
 824        }
 825        if (steps > MAX_SAMPLING_PERIOD) {
 826                printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate "
 827                       "too low.\n", dev->minor);
 828                up(&udfs->sem);
 829                return -EINVAL;
 830        }
 831        if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
 832            && (cmd->chanlist_len != 16)) {
 833                printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only"
 834                       " with 1 or 16 channels possible.\n", dev->minor);
 835                up(&udfs->sem);
 836                return -EINVAL;
 837        }
 838#ifdef CONFIG_COMEDI_DEBUG
 839        printk(KERN_DEBUG "comedi%d: usbduxfast: steps=%ld, convert_arg=%u\n",
 840               dev->minor, steps, cmd->convert_arg);
 841#endif
 842
 843        switch (cmd->chanlist_len) {
 844        case 1:
 845                /*
 846                 * one channel
 847                 */
 848
 849                if (CR_RANGE(cmd->chanlist[0]) > 0)
 850                        rngmask = 0xff - 0x04;
 851                else
 852                        rngmask = 0xff;
 853
 854                /*
 855                 * for external trigger: looping in this state until
 856                 * the RDY0 pin becomes zero
 857                 */
 858
 859                /* we loop here until ready has been set */
 860                if (cmd->start_src == TRIG_EXT) {
 861                        /* branch back to state 0 */
 862                        udfs->dux_commands[LENBASE + 0] = 0x01;
 863                        /* deceision state w/o data */
 864                        udfs->dux_commands[OPBASE + 0] = 0x01;
 865                        udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
 866                        /* RDY0 = 0 */
 867                        udfs->dux_commands[LOGBASE + 0] = 0x00;
 868                } else {        /* we just proceed to state 1 */
 869                        udfs->dux_commands[LENBASE + 0] = 1;
 870                        udfs->dux_commands[OPBASE + 0] = 0;
 871                        udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
 872                        udfs->dux_commands[LOGBASE + 0] = 0;
 873                }
 874
 875                if (steps < MIN_SAMPLING_PERIOD) {
 876                        /* for fast single channel aqu without mux */
 877                        if (steps <= 1) {
 878                                /*
 879                                 * we just stay here at state 1 and rexecute
 880                                 * the same state this gives us 30MHz sampling
 881                                 * rate
 882                                 */
 883
 884                                /* branch back to state 1 */
 885                                udfs->dux_commands[LENBASE + 1] = 0x89;
 886                                /* deceision state with data */
 887                                udfs->dux_commands[OPBASE + 1] = 0x03;
 888                                udfs->dux_commands[OUTBASE + 1] =
 889                                    0xFF & rngmask;
 890                                /* doesn't matter */
 891                                udfs->dux_commands[LOGBASE + 1] = 0xFF;
 892                        } else {
 893                                /*
 894                                 * we loop through two states: data and delay
 895                                 * max rate is 15MHz
 896                                 */
 897                                udfs->dux_commands[LENBASE + 1] = steps - 1;
 898                                /* data */
 899                                udfs->dux_commands[OPBASE + 1] = 0x02;
 900                                udfs->dux_commands[OUTBASE + 1] =
 901                                    0xFF & rngmask;
 902                                /* doesn't matter */
 903                                udfs->dux_commands[LOGBASE + 1] = 0;
 904                                /* branch back to state 1 */
 905                                udfs->dux_commands[LENBASE + 2] = 0x09;
 906                                /* deceision state w/o data */
 907                                udfs->dux_commands[OPBASE + 2] = 0x01;
 908                                udfs->dux_commands[OUTBASE + 2] =
 909                                    0xFF & rngmask;
 910                                /* doesn't matter */
 911                                udfs->dux_commands[LOGBASE + 2] = 0xFF;
 912                        }
 913                } else {
 914                        /*
 915                         * we loop through 3 states: 2x delay and 1x data
 916                         * this gives a min sampling rate of 60kHz
 917                         */
 918
 919                        /* we have 1 state with duration 1 */
 920                        steps = steps - 1;
 921
 922                        /* do the first part of the delay */
 923                        udfs->dux_commands[LENBASE + 1] = steps / 2;
 924                        udfs->dux_commands[OPBASE + 1] = 0;
 925                        udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
 926                        udfs->dux_commands[LOGBASE + 1] = 0;
 927
 928                        /* and the second part */
 929                        udfs->dux_commands[LENBASE + 2] = steps - steps / 2;
 930                        udfs->dux_commands[OPBASE + 2] = 0;
 931                        udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
 932                        udfs->dux_commands[LOGBASE + 2] = 0;
 933
 934                        /* get the data and branch back */
 935
 936                        /* branch back to state 1 */
 937                        udfs->dux_commands[LENBASE + 3] = 0x09;
 938                        /* deceision state w data */
 939                        udfs->dux_commands[OPBASE + 3] = 0x03;
 940                        udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
 941                        /* doesn't matter */
 942                        udfs->dux_commands[LOGBASE + 3] = 0xFF;
 943                }
 944                break;
 945
 946        case 2:
 947                /*
 948                 * two channels
 949                 * commit data to the FIFO
 950                 */
 951
 952                if (CR_RANGE(cmd->chanlist[0]) > 0)
 953                        rngmask = 0xff - 0x04;
 954                else
 955                        rngmask = 0xff;
 956
 957                udfs->dux_commands[LENBASE + 0] = 1;
 958                /* data */
 959                udfs->dux_commands[OPBASE + 0] = 0x02;
 960                udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
 961                udfs->dux_commands[LOGBASE + 0] = 0;
 962
 963                /* we have 1 state with duration 1: state 0 */
 964                steps_tmp = steps - 1;
 965
 966                if (CR_RANGE(cmd->chanlist[1]) > 0)
 967                        rngmask = 0xff - 0x04;
 968                else
 969                        rngmask = 0xff;
 970
 971                /* do the first part of the delay */
 972                udfs->dux_commands[LENBASE + 1] = steps_tmp / 2;
 973                udfs->dux_commands[OPBASE + 1] = 0;
 974                /* count */
 975                udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
 976                udfs->dux_commands[LOGBASE + 1] = 0;
 977
 978                /* and the second part */
 979                udfs->dux_commands[LENBASE + 2] = steps_tmp - steps_tmp / 2;
 980                udfs->dux_commands[OPBASE + 2] = 0;
 981                udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
 982                udfs->dux_commands[LOGBASE + 2] = 0;
 983
 984                udfs->dux_commands[LENBASE + 3] = 1;
 985                /* data */
 986                udfs->dux_commands[OPBASE + 3] = 0x02;
 987                udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
 988                udfs->dux_commands[LOGBASE + 3] = 0;
 989
 990                /*
 991                 * we have 2 states with duration 1: step 6 and
 992                 * the IDLE state
 993                 */
 994                steps_tmp = steps - 2;
 995
 996                if (CR_RANGE(cmd->chanlist[0]) > 0)
 997                        rngmask = 0xff - 0x04;
 998                else
 999                        rngmask = 0xff;
1000
1001                /* do the first part of the delay */
1002                udfs->dux_commands[LENBASE + 4] = steps_tmp / 2;
1003                udfs->dux_commands[OPBASE + 4] = 0;
1004                /* reset */
1005                udfs->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask;
1006                udfs->dux_commands[LOGBASE + 4] = 0;
1007
1008                /* and the second part */
1009                udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2;
1010                udfs->dux_commands[OPBASE + 5] = 0;
1011                udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
1012                udfs->dux_commands[LOGBASE + 5] = 0;
1013
1014                udfs->dux_commands[LENBASE + 6] = 1;
1015                udfs->dux_commands[OPBASE + 6] = 0;
1016                udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1017                udfs->dux_commands[LOGBASE + 6] = 0;
1018                break;
1019
1020        case 3:
1021                /*
1022                 * three channels
1023                 */
1024                for (j = 0; j < 1; j++) {
1025                        if (CR_RANGE(cmd->chanlist[j]) > 0)
1026                                rngmask = 0xff - 0x04;
1027                        else
1028                                rngmask = 0xff;
1029                        /*
1030                         * commit data to the FIFO and do the first part
1031                         * of the delay
1032                         */
1033                        udfs->dux_commands[LENBASE + j * 2] = steps / 2;
1034                        /* data */
1035                        udfs->dux_commands[OPBASE + j * 2] = 0x02;
1036                        /* no change */
1037                        udfs->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask;
1038                        udfs->dux_commands[LOGBASE + j * 2] = 0;
1039
1040                        if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
1041                                rngmask = 0xff - 0x04;
1042                        else
1043                                rngmask = 0xff;
1044
1045                        /* do the second part of the delay */
1046                        udfs->dux_commands[LENBASE + j * 2 + 1] =
1047                            steps - steps / 2;
1048                        /* no data */
1049                        udfs->dux_commands[OPBASE + j * 2 + 1] = 0;
1050                        /* count */
1051                        udfs->dux_commands[OUTBASE + j * 2 + 1] =
1052                            0xFE & rngmask;
1053                        udfs->dux_commands[LOGBASE + j * 2 + 1] = 0;
1054                }
1055
1056                /* 2 steps with duration 1: the idele step and step 6: */
1057                steps_tmp = steps - 2;
1058
1059                /* commit data to the FIFO and do the first part of the delay */
1060                udfs->dux_commands[LENBASE + 4] = steps_tmp / 2;
1061                /* data */
1062                udfs->dux_commands[OPBASE + 4] = 0x02;
1063                udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
1064                udfs->dux_commands[LOGBASE + 4] = 0;
1065
1066                if (CR_RANGE(cmd->chanlist[0]) > 0)
1067                        rngmask = 0xff - 0x04;
1068                else
1069                        rngmask = 0xff;
1070
1071                /* do the second part of the delay */
1072                udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2;
1073                /* no data */
1074                udfs->dux_commands[OPBASE + 5] = 0;
1075                /* reset */
1076                udfs->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask;
1077                udfs->dux_commands[LOGBASE + 5] = 0;
1078
1079                udfs->dux_commands[LENBASE + 6] = 1;
1080                udfs->dux_commands[OPBASE + 6] = 0;
1081                udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1082                udfs->dux_commands[LOGBASE + 6] = 0;
1083
1084        case 16:
1085                if (CR_RANGE(cmd->chanlist[0]) > 0)
1086                        rngmask = 0xff - 0x04;
1087                else
1088                        rngmask = 0xff;
1089
1090                if (cmd->start_src == TRIG_EXT) {
1091                        /*
1092                         * we loop here until ready has been set
1093                         */
1094
1095                        /* branch back to state 0 */
1096                        udfs->dux_commands[LENBASE + 0] = 0x01;
1097                        /* deceision state w/o data */
1098                        udfs->dux_commands[OPBASE + 0] = 0x01;
1099                        /* reset */
1100                        udfs->dux_commands[OUTBASE + 0] =
1101                            (0xFF - 0x02) & rngmask;
1102                        /* RDY0 = 0 */
1103                        udfs->dux_commands[LOGBASE + 0] = 0x00;
1104                } else {
1105                        /*
1106                         * we just proceed to state 1
1107                         */
1108
1109                        /* 30us reset pulse */
1110                        udfs->dux_commands[LENBASE + 0] = 255;
1111                        udfs->dux_commands[OPBASE + 0] = 0;
1112                        /* reset */
1113                        udfs->dux_commands[OUTBASE + 0] =
1114                            (0xFF - 0x02) & rngmask;
1115                        udfs->dux_commands[LOGBASE + 0] = 0;
1116                }
1117
1118                /* commit data to the FIFO */
1119                udfs->dux_commands[LENBASE + 1] = 1;
1120                /* data */
1121                udfs->dux_commands[OPBASE + 1] = 0x02;
1122                udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
1123                udfs->dux_commands[LOGBASE + 1] = 0;
1124
1125                /* we have 2 states with duration 1 */
1126                steps = steps - 2;
1127
1128                /* do the first part of the delay */
1129                udfs->dux_commands[LENBASE + 2] = steps / 2;
1130                udfs->dux_commands[OPBASE + 2] = 0;
1131                udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
1132                udfs->dux_commands[LOGBASE + 2] = 0;
1133
1134                /* and the second part */
1135                udfs->dux_commands[LENBASE + 3] = steps - steps / 2;
1136                udfs->dux_commands[OPBASE + 3] = 0;
1137                udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
1138                udfs->dux_commands[LOGBASE + 3] = 0;
1139
1140                /* branch back to state 1 */
1141                udfs->dux_commands[LENBASE + 4] = 0x09;
1142                /* deceision state w/o data */
1143                udfs->dux_commands[OPBASE + 4] = 0x01;
1144                udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
1145                /* doesn't matter */
1146                udfs->dux_commands[LOGBASE + 4] = 0xFF;
1147
1148                break;
1149
1150        default:
1151                printk(KERN_ERR "comedi %d: unsupported combination of "
1152                       "channels\n", dev->minor);
1153                up(&udfs->sem);
1154                return -EFAULT;
1155        }
1156
1157#ifdef CONFIG_COMEDI_DEBUG
1158        printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
1159               dev->minor);
1160#endif
1161        /* 0 means that the AD commands are sent */
1162        result = send_dux_commands(udfs, SENDADCOMMANDS);
1163        if (result < 0) {
1164                printk(KERN_ERR "comedi%d: adc command could not be submitted."
1165                       "Aborting...\n", dev->minor);
1166                up(&udfs->sem);
1167                return result;
1168        }
1169        if (cmd->stop_src == TRIG_COUNT) {
1170                udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg;
1171                if (udfs->ai_sample_count < 1) {
1172                        printk(KERN_ERR "comedi%d: "
1173                               "(cmd->stop_arg)*(cmd->scan_end_arg)<1, "
1174                               "aborting.\n", dev->minor);
1175                        up(&udfs->sem);
1176                        return -EFAULT;
1177                }
1178                udfs->ai_continous = 0;
1179        } else {
1180                /* continous aquisition */
1181                udfs->ai_continous = 1;
1182                udfs->ai_sample_count = 0;
1183        }
1184
1185        if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
1186                /* enable this acquisition operation */
1187                udfs->ai_cmd_running = 1;
1188                ret = usbduxfastsub_submit_InURBs(udfs);
1189                if (ret < 0) {
1190                        udfs->ai_cmd_running = 0;
1191                        /* fixme: unlink here?? */
1192                        up(&udfs->sem);
1193                        return ret;
1194                }
1195                s->async->inttrig = NULL;
1196        } else {
1197                /*
1198                 * TRIG_INT
1199                 * don't enable the acquision operation
1200                 * wait for an internal signal
1201                 */
1202                s->async->inttrig = usbduxfast_ai_inttrig;
1203        }
1204        up(&udfs->sem);
1205
1206        return 0;
1207}
1208
1209/*
1210 * Mode 0 is used to get a single conversion on demand.
1211 */
1212static int usbduxfast_ai_insn_read(struct comedi_device *dev,
1213                                   struct comedi_subdevice *s,
1214                                   struct comedi_insn *insn, unsigned int *data)
1215{
1216        int i, j, n, actual_length;
1217        int chan, range, rngmask;
1218        int err;
1219        struct usbduxfastsub_s *udfs;
1220
1221        udfs = dev->private;
1222        if (!udfs) {
1223                printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n",
1224                       dev->minor);
1225                return -ENODEV;
1226        }
1227#ifdef CONFIG_COMEDI_DEBUG
1228        printk(KERN_DEBUG "comedi%d: ai_insn_read, insn->n=%d, "
1229               "insn->subdev=%d\n", dev->minor, insn->n, insn->subdev);
1230#endif
1231        down(&udfs->sem);
1232        if (!udfs->probed) {
1233                up(&udfs->sem);
1234                return -ENODEV;
1235        }
1236        if (udfs->ai_cmd_running) {
1237                printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async "
1238                       "Command is running.\n", dev->minor);
1239                up(&udfs->sem);
1240                return -EBUSY;
1241        }
1242        /* sample one channel */
1243        chan = CR_CHAN(insn->chanspec);
1244        range = CR_RANGE(insn->chanspec);
1245        /* set command for the first channel */
1246
1247        if (range > 0)
1248                rngmask = 0xff - 0x04;
1249        else
1250                rngmask = 0xff;
1251
1252        /* commit data to the FIFO */
1253        udfs->dux_commands[LENBASE + 0] = 1;
1254        /* data */
1255        udfs->dux_commands[OPBASE + 0] = 0x02;
1256        udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
1257        udfs->dux_commands[LOGBASE + 0] = 0;
1258
1259        /* do the first part of the delay */
1260        udfs->dux_commands[LENBASE + 1] = 12;
1261        udfs->dux_commands[OPBASE + 1] = 0;
1262        udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
1263        udfs->dux_commands[LOGBASE + 1] = 0;
1264
1265        udfs->dux_commands[LENBASE + 2] = 1;
1266        udfs->dux_commands[OPBASE + 2] = 0;
1267        udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
1268        udfs->dux_commands[LOGBASE + 2] = 0;
1269
1270        udfs->dux_commands[LENBASE + 3] = 1;
1271        udfs->dux_commands[OPBASE + 3] = 0;
1272        udfs->dux_commands[OUTBASE + 3] = 0xFE & rngmask;
1273        udfs->dux_commands[LOGBASE + 3] = 0;
1274
1275        udfs->dux_commands[LENBASE + 4] = 1;
1276        udfs->dux_commands[OPBASE + 4] = 0;
1277        udfs->dux_commands[OUTBASE + 4] = 0xFE & rngmask;
1278        udfs->dux_commands[LOGBASE + 4] = 0;
1279
1280        /* second part */
1281        udfs->dux_commands[LENBASE + 5] = 12;
1282        udfs->dux_commands[OPBASE + 5] = 0;
1283        udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
1284        udfs->dux_commands[LOGBASE + 5] = 0;
1285
1286        udfs->dux_commands[LENBASE + 6] = 1;
1287        udfs->dux_commands[OPBASE + 6] = 0;
1288        udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1289        udfs->dux_commands[LOGBASE + 0] = 0;
1290
1291#ifdef CONFIG_COMEDI_DEBUG
1292        printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
1293               dev->minor);
1294#endif
1295        /* 0 means that the AD commands are sent */
1296        err = send_dux_commands(udfs, SENDADCOMMANDS);
1297        if (err < 0) {
1298                printk(KERN_ERR "comedi%d: adc command could not be submitted."
1299                       "Aborting...\n", dev->minor);
1300                up(&udfs->sem);
1301                return err;
1302        }
1303#ifdef CONFIG_COMEDI_DEBUG
1304        printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
1305               "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
1306               udfs->urbIn->dev);
1307#endif
1308        for (i = 0; i < PACKETS_TO_IGNORE; i++) {
1309                err = usb_bulk_msg(udfs->usbdev,
1310                                   usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
1311                                   udfs->transfer_buffer, SIZEINBUF,
1312                                   &actual_length, 10000);
1313                if (err < 0) {
1314                        printk(KERN_ERR "comedi%d: insn timeout. No data.\n",
1315                               dev->minor);
1316                        up(&udfs->sem);
1317                        return err;
1318                }
1319        }
1320        /* data points */
1321        for (i = 0; i < insn->n;) {
1322                err = usb_bulk_msg(udfs->usbdev,
1323                                   usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
1324                                   udfs->transfer_buffer, SIZEINBUF,
1325                                   &actual_length, 10000);
1326                if (err < 0) {
1327                        printk(KERN_ERR "comedi%d: insn data error: %d\n",
1328                               dev->minor, err);
1329                        up(&udfs->sem);
1330                        return err;
1331                }
1332                n = actual_length / sizeof(uint16_t);
1333                if ((n % 16) != 0) {
1334                        printk(KERN_ERR "comedi%d: insn data packet "
1335                               "corrupted.\n", dev->minor);
1336                        up(&udfs->sem);
1337                        return -EINVAL;
1338                }
1339                for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
1340                        data[i] = ((uint16_t *) (udfs->transfer_buffer))[j];
1341                        i++;
1342                }
1343        }
1344        up(&udfs->sem);
1345        return i;
1346}
1347
1348#define FIRMWARE_MAX_LEN 0x2000
1349
1350static int firmwareUpload(struct usbduxfastsub_s *usbduxfastsub,
1351                          const u8 * firmwareBinary, int sizeFirmware)
1352{
1353        int ret;
1354        uint8_t *fwBuf;
1355
1356        if (!firmwareBinary)
1357                return 0;
1358
1359        if (sizeFirmware > FIRMWARE_MAX_LEN) {
1360                dev_err(&usbduxfastsub->interface->dev,
1361                        "comedi_: usbduxfast firmware binary it too large for FX2.\n");
1362                return -ENOMEM;
1363        }
1364
1365        /* we generate a local buffer for the firmware */
1366        fwBuf = kzalloc(sizeFirmware, GFP_KERNEL);
1367        if (!fwBuf) {
1368                dev_err(&usbduxfastsub->interface->dev,
1369                        "comedi_: mem alloc for firmware failed\n");
1370                return -ENOMEM;
1371        }
1372        memcpy(fwBuf, firmwareBinary, sizeFirmware);
1373
1374        ret = usbduxfastsub_stop(usbduxfastsub);
1375        if (ret < 0) {
1376                dev_err(&usbduxfastsub->interface->dev,
1377                        "comedi_: can not stop firmware\n");
1378                kfree(fwBuf);
1379                return ret;
1380        }
1381
1382        ret = usbduxfastsub_upload(usbduxfastsub, fwBuf, 0, sizeFirmware);
1383        if (ret < 0) {
1384                dev_err(&usbduxfastsub->interface->dev,
1385                        "comedi_: firmware upload failed\n");
1386                kfree(fwBuf);
1387                return ret;
1388        }
1389        ret = usbduxfastsub_start(usbduxfastsub);
1390        if (ret < 0) {
1391                dev_err(&usbduxfastsub->interface->dev,
1392                        "comedi_: can not start firmware\n");
1393                kfree(fwBuf);
1394                return ret;
1395        }
1396        kfree(fwBuf);
1397        return 0;
1398}
1399
1400static void tidy_up(struct usbduxfastsub_s *udfs)
1401{
1402#ifdef CONFIG_COMEDI_DEBUG
1403        printk(KERN_DEBUG "comedi_: usbduxfast: tiding up\n");
1404#endif
1405
1406        if (!udfs)
1407                return;
1408
1409        /* shows the usb subsystem that the driver is down */
1410        if (udfs->interface)
1411                usb_set_intfdata(udfs->interface, NULL);
1412
1413        udfs->probed = 0;
1414
1415        if (udfs->urbIn) {
1416                /* waits until a running transfer is over */
1417                usb_kill_urb(udfs->urbIn);
1418
1419                kfree(udfs->transfer_buffer);
1420                udfs->transfer_buffer = NULL;
1421
1422                usb_free_urb(udfs->urbIn);
1423                udfs->urbIn = NULL;
1424        }
1425
1426        kfree(udfs->insnBuffer);
1427        udfs->insnBuffer = NULL;
1428
1429        kfree(udfs->dux_commands);
1430        udfs->dux_commands = NULL;
1431
1432        udfs->ai_cmd_running = 0;
1433}
1434
1435static void usbduxfast_firmware_request_complete_handler(const struct firmware
1436                                                         *fw, void *context)
1437{
1438        struct usbduxfastsub_s *usbduxfastsub_tmp = context;
1439        struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
1440        int ret;
1441
1442        if (fw == NULL)
1443                return;
1444
1445        /*
1446         * we need to upload the firmware here because fw will be
1447         * freed once we've left this function
1448         */
1449        ret = firmwareUpload(usbduxfastsub_tmp, fw->data, fw->size);
1450
1451        if (ret) {
1452                dev_err(&usbdev->dev,
1453                        "Could not upload firmware (err=%d)\n", ret);
1454                return;
1455        }
1456
1457        comedi_usb_auto_config(usbdev, BOARDNAME);
1458}
1459
1460/*
1461 * allocate memory for the urbs and initialise them
1462 */
1463static int usbduxfastsub_probe(struct usb_interface *uinterf,
1464                               const struct usb_device_id *id)
1465{
1466        struct usb_device *udev = interface_to_usbdev(uinterf);
1467        int i;
1468        int index;
1469        int ret;
1470
1471        if (udev->speed != USB_SPEED_HIGH) {
1472                printk(KERN_ERR "comedi_: usbduxfast_: This driver needs"
1473                       "USB 2.0 to operate. Aborting...\n");
1474                return -ENODEV;
1475        }
1476#ifdef CONFIG_COMEDI_DEBUG
1477        printk(KERN_DEBUG "comedi_: usbduxfast_: finding a free structure for "
1478               "the usb-device\n");
1479#endif
1480        down(&start_stop_sem);
1481        /* look for a free place in the usbduxfast array */
1482        index = -1;
1483        for (i = 0; i < NUMUSBDUXFAST; i++) {
1484                if (!usbduxfastsub[i].probed) {
1485                        index = i;
1486                        break;
1487                }
1488        }
1489
1490        /* no more space */
1491        if (index == -1) {
1492                printk(KERN_ERR "Too many usbduxfast-devices connected.\n");
1493                up(&start_stop_sem);
1494                return -EMFILE;
1495        }
1496#ifdef CONFIG_COMEDI_DEBUG
1497        printk(KERN_DEBUG "comedi_: usbduxfast: usbduxfastsub[%d] is ready to "
1498               "connect to comedi.\n", index);
1499#endif
1500
1501        init_MUTEX(&(usbduxfastsub[index].sem));
1502        /* save a pointer to the usb device */
1503        usbduxfastsub[index].usbdev = udev;
1504
1505        /* save the interface itself */
1506        usbduxfastsub[index].interface = uinterf;
1507        /* get the interface number from the interface */
1508        usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
1509        /*
1510         * hand the private data over to the usb subsystem
1511         * will be needed for disconnect
1512         */
1513        usb_set_intfdata(uinterf, &(usbduxfastsub[index]));
1514
1515#ifdef CONFIG_COMEDI_DEBUG
1516        printk(KERN_DEBUG "comedi_: usbduxfast: ifnum=%d\n",
1517               usbduxfastsub[index].ifnum);
1518#endif
1519        /* create space for the commands going to the usb device */
1520        usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
1521                                                    GFP_KERNEL);
1522        if (!usbduxfastsub[index].dux_commands) {
1523                printk(KERN_ERR "comedi_: usbduxfast: error alloc space for "
1524                       "dac commands\n");
1525                tidy_up(&(usbduxfastsub[index]));
1526                up(&start_stop_sem);
1527                return -ENOMEM;
1528        }
1529        /* create space of the instruction buffer */
1530        usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
1531        if (!usbduxfastsub[index].insnBuffer) {
1532                printk(KERN_ERR "comedi_: usbduxfast: could not alloc space "
1533                       "for insnBuffer\n");
1534                tidy_up(&(usbduxfastsub[index]));
1535                up(&start_stop_sem);
1536                return -ENOMEM;
1537        }
1538        /* setting to alternate setting 1: enabling bulk ep */
1539        i = usb_set_interface(usbduxfastsub[index].usbdev,
1540                              usbduxfastsub[index].ifnum, 1);
1541        if (i < 0) {
1542                printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to "
1543                       "alternate setting 1.\n", index);
1544                tidy_up(&(usbduxfastsub[index]));
1545                up(&start_stop_sem);
1546                return -ENODEV;
1547        }
1548        usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
1549        if (!usbduxfastsub[index].urbIn) {
1550                printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc."
1551                       "urb\n", index);
1552                tidy_up(&(usbduxfastsub[index]));
1553                up(&start_stop_sem);
1554                return -ENOMEM;
1555        }
1556        usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
1557        if (!usbduxfastsub[index].transfer_buffer) {
1558                printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. "
1559                       "transb.\n", index);
1560                tidy_up(&(usbduxfastsub[index]));
1561                up(&start_stop_sem);
1562                return -ENOMEM;
1563        }
1564        /* we've reached the bottom of the function */
1565        usbduxfastsub[index].probed = 1;
1566        up(&start_stop_sem);
1567
1568        ret = request_firmware_nowait(THIS_MODULE,
1569                                      FW_ACTION_HOTPLUG,
1570                                      "usbduxfast_firmware.bin",
1571                                      &udev->dev,
1572                                      usbduxfastsub + index,
1573                                      usbduxfast_firmware_request_complete_handler);
1574
1575        if (ret) {
1576                dev_err(&udev->dev, "could not load firmware (err=%d)\n", ret);
1577                return ret;
1578        }
1579
1580        printk(KERN_INFO "comedi_: usbduxfast%d has been successfully "
1581               "initialized.\n", index);
1582        /* success */
1583        return 0;
1584}
1585
1586static void usbduxfastsub_disconnect(struct usb_interface *intf)
1587{
1588        struct usbduxfastsub_s *udfs = usb_get_intfdata(intf);
1589        struct usb_device *udev = interface_to_usbdev(intf);
1590
1591        if (!udfs) {
1592                printk(KERN_ERR "comedi_: usbduxfast: disconnect called with "
1593                       "null pointer.\n");
1594                return;
1595        }
1596        if (udfs->usbdev != udev) {
1597                printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong "
1598                       "ptr!!!\n");
1599                return;
1600        }
1601
1602        comedi_usb_auto_unconfig(udev);
1603
1604        down(&start_stop_sem);
1605        down(&udfs->sem);
1606        tidy_up(udfs);
1607        up(&udfs->sem);
1608        up(&start_stop_sem);
1609
1610#ifdef CONFIG_COMEDI_DEBUG
1611        printk(KERN_DEBUG "comedi_: usbduxfast: disconnected from the usb\n");
1612#endif
1613}
1614
1615/*
1616 * is called when comedi-config is called
1617 */
1618static int usbduxfast_attach(struct comedi_device *dev,
1619                             struct comedi_devconfig *it)
1620{
1621        int ret;
1622        int index;
1623        int i;
1624        struct comedi_subdevice *s = NULL;
1625        dev->private = NULL;
1626
1627        down(&start_stop_sem);
1628        /*
1629         * find a valid device which has been detected by the
1630         * probe function of the usb
1631         */
1632        index = -1;
1633        for (i = 0; i < NUMUSBDUXFAST; i++) {
1634                if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) {
1635                        index = i;
1636                        break;
1637                }
1638        }
1639
1640        if (index < 0) {
1641                printk(KERN_ERR "comedi%d: usbduxfast: error: attach failed, "
1642                       "no usbduxfast devs connected to the usb bus.\n",
1643                       dev->minor);
1644                up(&start_stop_sem);
1645                return -ENODEV;
1646        }
1647
1648        down(&(usbduxfastsub[index].sem));
1649        /* pointer back to the corresponding comedi device */
1650        usbduxfastsub[index].comedidev = dev;
1651
1652        /* trying to upload the firmware into the chip */
1653        if (comedi_aux_data(it->options, 0) &&
1654            it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
1655                firmwareUpload(&usbduxfastsub[index],
1656                               comedi_aux_data(it->options, 0),
1657                               it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
1658        }
1659
1660        dev->board_name = BOARDNAME;
1661
1662        /* set number of subdevices */
1663        dev->n_subdevices = N_SUBDEVICES;
1664
1665        /* allocate space for the subdevices */
1666        ret = alloc_subdevices(dev, N_SUBDEVICES);
1667        if (ret < 0) {
1668                printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for "
1669                       "subdev\n", dev->minor);
1670                up(&(usbduxfastsub[index].sem));
1671                up(&start_stop_sem);
1672                return ret;
1673        }
1674
1675        printk(KERN_INFO "comedi%d: usbduxfast: usb-device %d is attached to "
1676               "comedi.\n", dev->minor, index);
1677        /* private structure is also simply the usb-structure */
1678        dev->private = usbduxfastsub + index;
1679        /* the first subdevice is the A/D converter */
1680        s = dev->subdevices + SUBDEV_AD;
1681        /*
1682         * the URBs get the comedi subdevice which is responsible for reading
1683         * this is the subdevice which reads data
1684         */
1685        dev->read_subdev = s;
1686        /* the subdevice receives as private structure the usb-structure */
1687        s->private = NULL;
1688        /* analog input */
1689        s->type = COMEDI_SUBD_AI;
1690        /* readable and ref is to ground */
1691        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
1692        /* 16 channels */
1693        s->n_chan = 16;
1694        /* length of the channellist */
1695        s->len_chanlist = 16;
1696        /* callback functions */
1697        s->insn_read = usbduxfast_ai_insn_read;
1698        s->do_cmdtest = usbduxfast_ai_cmdtest;
1699        s->do_cmd = usbduxfast_ai_cmd;
1700        s->cancel = usbduxfast_ai_cancel;
1701        /* max value from the A/D converter (12bit+1 bit for overflow) */
1702        s->maxdata = 0x1000;
1703        /* range table to convert to physical units */
1704        s->range_table = &range_usbduxfast_ai_range;
1705
1706        /* finally decide that it's attached */
1707        usbduxfastsub[index].attached = 1;
1708
1709        up(&(usbduxfastsub[index].sem));
1710        up(&start_stop_sem);
1711        printk(KERN_INFO "comedi%d: successfully attached to usbduxfast.\n",
1712               dev->minor);
1713
1714        return 0;
1715}
1716
1717static int usbduxfast_detach(struct comedi_device *dev)
1718{
1719        struct usbduxfastsub_s *udfs;
1720
1721        if (!dev) {
1722                printk(KERN_ERR "comedi?: usbduxfast: detach without dev "
1723                       "variable...\n");
1724                return -EFAULT;
1725        }
1726#ifdef CONFIG_COMEDI_DEBUG
1727        printk(KERN_DEBUG "comedi%d: usbduxfast: detach usb device\n",
1728               dev->minor);
1729#endif
1730
1731        udfs = dev->private;
1732        if (!udfs) {
1733                printk(KERN_ERR "comedi?: usbduxfast: detach without ptr to "
1734                       "usbduxfastsub[]\n");
1735                return -EFAULT;
1736        }
1737
1738        down(&udfs->sem);
1739        down(&start_stop_sem);
1740        /*
1741         * Don't allow detach to free the private structure
1742         * It's one entry of of usbduxfastsub[]
1743         */
1744        dev->private = NULL;
1745        udfs->attached = 0;
1746        udfs->comedidev = NULL;
1747#ifdef CONFIG_COMEDI_DEBUG
1748        printk(KERN_DEBUG "comedi%d: usbduxfast: detach: successfully "
1749               "removed\n", dev->minor);
1750#endif
1751        up(&start_stop_sem);
1752        up(&udfs->sem);
1753        return 0;
1754}
1755
1756/*
1757 * main driver struct
1758 */
1759static struct comedi_driver driver_usbduxfast = {
1760        .driver_name = "usbduxfast",
1761        .module = THIS_MODULE,
1762        .attach = usbduxfast_attach,
1763        .detach = usbduxfast_detach
1764};
1765
1766/*
1767 * Table with the USB-devices: just now only testing IDs
1768 */
1769static struct usb_device_id usbduxfastsub_table[] = {
1770        /* { USB_DEVICE(0x4b4, 0x8613) }, testing */
1771        {USB_DEVICE(0x13d8, 0x0010)},   /* real ID */
1772        {USB_DEVICE(0x13d8, 0x0011)},   /* real ID */
1773        {}                      /* Terminating entry */
1774};
1775
1776MODULE_DEVICE_TABLE(usb, usbduxfastsub_table);
1777
1778/*
1779 * The usbduxfastsub-driver
1780 */
1781static struct usb_driver usbduxfastsub_driver = {
1782#ifdef COMEDI_HAVE_USB_DRIVER_OWNER
1783        .owner = THIS_MODULE,
1784#endif
1785        .name = BOARDNAME,
1786        .probe = usbduxfastsub_probe,
1787        .disconnect = usbduxfastsub_disconnect,
1788        .id_table = usbduxfastsub_table
1789};
1790
1791/*
1792 * Can't use the nice macro as I have also to initialise the USB subsystem:
1793 * registering the usb-system _and_ the comedi-driver
1794 */
1795static int __init init_usbduxfast(void)
1796{
1797        printk(KERN_INFO
1798               KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n");
1799        usb_register(&usbduxfastsub_driver);
1800        comedi_driver_register(&driver_usbduxfast);
1801        return 0;
1802}
1803
1804/*
1805 * deregistering the comedi driver and the usb-subsystem
1806 */
1807static void __exit exit_usbduxfast(void)
1808{
1809        comedi_driver_unregister(&driver_usbduxfast);
1810        usb_deregister(&usbduxfastsub_driver);
1811}
1812
1813module_init(init_usbduxfast);
1814module_exit(exit_usbduxfast);
1815
1816MODULE_AUTHOR(DRIVER_AUTHOR);
1817MODULE_DESCRIPTION(DRIVER_DESC);
1818MODULE_LICENSE("GPL");
1819