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