Version:  2.0.40 2.2.26 2.4.37 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16

Linux/drivers/staging/comedi/drivers/usbdux.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us