Version:  2.0.40 2.2.26 2.4.37 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 3.17 3.18 3.19 4.0

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

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

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