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