root/drivers/staging/comedi/drivers/usbdux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbdux_unlink_urbs
  2. usbdux_ai_stop
  3. usbdux_ai_cancel
  4. usbduxsub_ai_handle_urb
  5. usbduxsub_ai_isoc_irq
  6. usbdux_ao_stop
  7. usbdux_ao_cancel
  8. usbduxsub_ao_handle_urb
  9. usbduxsub_ao_isoc_irq
  10. usbdux_submit_urbs
  11. usbdux_ai_cmdtest
  12. create_adc_command
  13. send_dux_commands
  14. receive_dux_commands
  15. usbdux_ai_inttrig
  16. usbdux_ai_cmd
  17. usbdux_ai_insn_read
  18. usbdux_ao_insn_read
  19. usbdux_ao_insn_write
  20. usbdux_ao_inttrig
  21. usbdux_ao_cmdtest
  22. usbdux_ao_cmd
  23. usbdux_dio_insn_config
  24. usbdux_dio_insn_bits
  25. usbdux_counter_read
  26. usbdux_counter_write
  27. usbdux_counter_config
  28. usbduxsub_unlink_pwm_urbs
  29. usbdux_pwm_stop
  30. usbdux_pwm_cancel
  31. usbduxsub_pwm_irq
  32. usbduxsub_submit_pwm_urbs
  33. usbdux_pwm_period
  34. usbdux_pwm_start
  35. usbdux_pwm_pattern
  36. usbdux_pwm_write
  37. usbdux_pwm_config
  38. usbdux_firmware_upload
  39. usbdux_alloc_usb_buffers
  40. usbdux_free_usb_buffers
  41. usbdux_auto_attach
  42. usbdux_detach
  43. usbdux_usb_probe

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

/* [<][>][^][v][top][bottom][index][help] */