]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/comedi/drivers/usbdux.c
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / 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    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19  */
20 /*
21 Driver: usbdux
22 Description: University of Stirling USB DAQ & INCITE Technology Limited
23 Devices: [ITL] USB-DUX (usbdux.o)
24 Author: Bernd Porr <BerndPorr@f2s.com>
25 Updated: 8 Dec 2008
26 Status: Stable
27 Configuration options:
28   You have to upload firmware with the -i option. The
29   firmware is usually installed under /usr/share/usb or
30   /usr/local/share/usb or /lib/firmware.
31
32 Connection scheme for the counter at the digital port:
33   0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
34   The sampling rate of the counter is approximately 500Hz.
35
36 Please note that under USB2.0 the length of the channel list determines
37 the max sampling rate. If you sample only one channel you get 8kHz
38 sampling rate. If you sample two channels you get 4kHz and so on.
39 */
40 /*
41  * I must give credit here to Chris Baugher who
42  * wrote the driver for AT-MIO-16d. I used some parts of this
43  * driver. I also must give credits to David Brownell
44  * who supported me with the USB development.
45  *
46  * Bernd Porr
47  *
48  *
49  * Revision history:
50  * 0.94: D/A output should work now with any channel list combinations
51  * 0.95: .owner commented out for kernel vers below 2.4.19
52  *       sanity checks in ai/ao_cmd
53  * 0.96: trying to get it working with 2.6, moved all memory alloc to comedi's
54  *       attach final USB IDs
55  *       moved memory allocation completely to the corresponding comedi
56  *       functions firmware upload is by fxload and no longer by comedi (due to
57  *       enumeration)
58  * 0.97: USB IDs received, adjusted table
59  * 0.98: SMP, locking, memroy alloc: moved all usb memory alloc
60  *       to the usb subsystem and moved all comedi related memory
61  *       alloc to comedi.
62  *       | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
63  * 0.99: USB 2.0: changed protocol to isochronous transfer
64  *                IRQ transfer is too buggy and too risky in 2.0
65  *                for the high speed ISO transfer is now a working version
66  *                available
67  * 0.99b: Increased the iso transfer buffer for high sp.to 10 buffers. Some VIA
68  *        chipsets miss out IRQs. Deeper buffering is needed.
69  * 1.00: full USB 2.0 support for the A/D converter. Now: max 8kHz sampling
70  *       rate.
71  *       Firmware vers 1.00 is needed for this.
72  *       Two 16 bit up/down/reset counter with a sampling rate of 1kHz
73  *       And loads of cleaning up, in particular streamlining the
74  *       bulk transfers.
75  * 1.1:  moved EP4 transfers to EP1 to make space for a PWM output on EP4
76  * 1.2:  added PWM suport via EP4
77  * 2.0:  PWM seems to be stable and is not interfering with the other functions
78  * 2.1:  changed PWM API
79  * 2.2:  added firmware kernel request to fix an udev problem
80  * 2.3:  corrected a bug in bulk timeouts which were far too short
81  * 2.4:  fixed a bug which causes the driver to hang when it ran out of data.
82  *       Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
83  *
84  */
85
86 /* generates loads of debug info */
87 /* #define NOISY_DUX_DEBUGBUG */
88
89 #include <linux/kernel.h>
90 #include <linux/module.h>
91 #include <linux/init.h>
92 #include <linux/slab.h>
93 #include <linux/input.h>
94 #include <linux/usb.h>
95 #include <linux/fcntl.h>
96 #include <linux/compiler.h>
97 #include <linux/firmware.h>
98
99 #include "../comedidev.h"
100
101 /* timeout for the USB-transfer in ms*/
102 #define BULK_TIMEOUT 1000
103
104 /* constants for "firmware" upload and download */
105 #define FIRMWARE "usbdux_firmware.bin"
106 #define USBDUXSUB_FIRMWARE 0xA0
107 #define VENDOR_DIR_IN  0xC0
108 #define VENDOR_DIR_OUT 0x40
109
110 /* internal addresses of the 8051 processor */
111 #define USBDUXSUB_CPUCS 0xE600
112
113 /*
114  * the minor device number, major is 180 only for debugging purposes and to
115  * upload special firmware (programming the eeprom etc) which is not compatible
116  * with the comedi framwork
117  */
118 #define USBDUXSUB_MINOR 32
119
120 /* max lenghth of the transfer-buffer for software upload */
121 #define TB_LEN 0x2000
122
123 /* Input endpoint number: ISO/IRQ */
124 #define ISOINEP           6
125
126 /* Output endpoint number: ISO/IRQ */
127 #define ISOOUTEP          2
128
129 /* This EP sends DUX commands to USBDUX */
130 #define COMMAND_OUT_EP     1
131
132 /* This EP receives the DUX commands from USBDUX */
133 #define COMMAND_IN_EP        8
134
135 /* Output endpoint for PWM */
136 #define PWM_EP         4
137
138 /* 300Hz max frequ under PWM */
139 #define MIN_PWM_PERIOD  ((long)(1E9/300))
140
141 /* Default PWM frequency */
142 #define PWM_DEFAULT_PERIOD ((long)(1E9/100))
143
144 /* Number of channels */
145 #define NUMCHANNELS       8
146
147 /* Size of one A/D value */
148 #define SIZEADIN          ((sizeof(int16_t)))
149
150 /*
151  * Size of the input-buffer IN BYTES
152  * Always multiple of 8 for 8 microframes which is needed in the highspeed mode
153  */
154 #define SIZEINBUF         ((8*SIZEADIN))
155
156 /* 16 bytes. */
157 #define SIZEINSNBUF       16
158
159 /* Number of DA channels */
160 #define NUMOUTCHANNELS    8
161
162 /* size of one value for the D/A converter: channel and value */
163 #define SIZEDAOUT          ((sizeof(int8_t)+sizeof(int16_t)))
164
165 /*
166  * Size of the output-buffer in bytes
167  * Actually only the first 4 triplets are used but for the
168  * high speed mode we need to pad it to 8 (microframes).
169  */
170 #define SIZEOUTBUF         ((8*SIZEDAOUT))
171
172 /*
173  * Size of the buffer for the dux commands: just now max size is determined
174  * by the analogue out + command byte + panic bytes...
175  */
176 #define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
177
178 /* Number of in-URBs which receive the data: min=2 */
179 #define NUMOFINBUFFERSFULL     5
180
181 /* Number of out-URBs which send the data: min=2 */
182 #define NUMOFOUTBUFFERSFULL    5
183
184 /* Number of in-URBs which receive the data: min=5 */
185 /* must have more buffers due to buggy USB ctr */
186 #define NUMOFINBUFFERSHIGH     10
187
188 /* Number of out-URBs which send the data: min=5 */
189 /* must have more buffers due to buggy USB ctr */
190 #define NUMOFOUTBUFFERSHIGH    10
191
192 /* Total number of usbdux devices */
193 #define NUMUSBDUX             16
194
195 /* Analogue in subdevice */
196 #define SUBDEV_AD             0
197
198 /* Analogue out subdevice */
199 #define SUBDEV_DA             1
200
201 /* Digital I/O */
202 #define SUBDEV_DIO            2
203
204 /* counter */
205 #define SUBDEV_COUNTER        3
206
207 /* timer aka pwm output */
208 #define SUBDEV_PWM            4
209
210 /* number of retries to get the right dux command */
211 #define RETRIES 10
212
213 /**************************************************/
214 /* comedi constants */
215 static const struct comedi_lrange range_usbdux_ai_range = { 4, {
216                                                                 BIP_RANGE
217                                                                 (4.096),
218                                                                 BIP_RANGE(4.096
219                                                                           / 2),
220                                                                 UNI_RANGE
221                                                                 (4.096),
222                                                                 UNI_RANGE(4.096
223                                                                           / 2)
224                                                                 }
225 };
226
227 static const struct comedi_lrange range_usbdux_ao_range = { 2, {
228                                                                 BIP_RANGE
229                                                                 (4.096),
230                                                                 UNI_RANGE
231                                                                 (4.096),
232                                                                 }
233 };
234
235 /*
236  * private structure of one subdevice
237  */
238
239 /*
240  * This is the structure which holds all the data of
241  * this driver one sub device just now: A/D
242  */
243 struct usbduxsub {
244         /* attached? */
245         int attached;
246         /* is it associated with a subdevice? */
247         int probed;
248         /* pointer to the usb-device */
249         struct usb_device *usbdev;
250         /* actual number of in-buffers */
251         int numOfInBuffers;
252         /* actual number of out-buffers */
253         int numOfOutBuffers;
254         /* ISO-transfer handling: buffers */
255         struct urb **urbIn;
256         struct urb **urbOut;
257         /* pwm-transfer handling */
258         struct urb *urbPwm;
259         /* PWM period */
260         unsigned int pwmPeriod;
261         /* PWM internal delay for the GPIF in the FX2 */
262         int8_t pwmDelay;
263         /* size of the PWM buffer which holds the bit pattern */
264         int sizePwmBuf;
265         /* input buffer for the ISO-transfer */
266         int16_t *inBuffer;
267         /* input buffer for single insn */
268         int16_t *insnBuffer;
269         /* output buffer for single DA outputs */
270         int16_t *outBuffer;
271         /* interface number */
272         int ifnum;
273         /* interface structure in 2.6 */
274         struct usb_interface *interface;
275         /* comedi device for the interrupt context */
276         struct comedi_device *comedidev;
277         /* is it USB_SPEED_HIGH or not? */
278         short int high_speed;
279         /* asynchronous command is running */
280         short int ai_cmd_running;
281         short int ao_cmd_running;
282         /* pwm is running */
283         short int pwm_cmd_running;
284         /* continous acquisition */
285         short int ai_continous;
286         short int ao_continous;
287         /* number of samples to acquire */
288         int ai_sample_count;
289         int ao_sample_count;
290         /* time between samples in units of the timer */
291         unsigned int ai_timer;
292         unsigned int ao_timer;
293         /* counter between aquisitions */
294         unsigned int ai_counter;
295         unsigned int ao_counter;
296         /* interval in frames/uframes */
297         unsigned int ai_interval;
298         /* D/A commands */
299         int8_t *dac_commands;
300         /* commands */
301         int8_t *dux_commands;
302         struct semaphore sem;
303 };
304
305 /*
306  * The pointer to the private usb-data of the driver is also the private data
307  * for the comedi-device.  This has to be global as the usb subsystem needs
308  * global variables. The other reason is that this structure must be there
309  * _before_ any comedi command is issued. The usb subsystem must be initialised
310  * before comedi can access it.
311  */
312 static struct usbduxsub usbduxsub[NUMUSBDUX];
313
314 static DEFINE_SEMAPHORE(start_stop_sem);
315
316 /*
317  * Stops the data acquision
318  * It should be safe to call this function from any context
319  */
320 static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp)
321 {
322         int i = 0;
323         int err = 0;
324
325         if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
326                 for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
327                         if (usbduxsub_tmp->urbIn[i]) {
328                                 /* We wait here until all transfers have been
329                                  * cancelled. */
330                                 usb_kill_urb(usbduxsub_tmp->urbIn[i]);
331                         }
332                         dev_dbg(&usbduxsub_tmp->interface->dev,
333                                 "comedi: usbdux: unlinked InURB %d, err=%d\n",
334                                 i, err);
335                 }
336         }
337         return err;
338 }
339
340 /*
341  * This will stop a running acquisition operation
342  * Is called from within this driver from both the
343  * interrupt context and from comedi
344  */
345 static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
346 {
347         int ret = 0;
348
349         if (!this_usbduxsub) {
350                 pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
351                 return -EFAULT;
352         }
353         dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
354
355         if (do_unlink) {
356                 /* stop aquistion */
357                 ret = usbduxsub_unlink_InURBs(this_usbduxsub);
358         }
359
360         this_usbduxsub->ai_cmd_running = 0;
361
362         return ret;
363 }
364
365 /*
366  * This will cancel a running acquisition operation.
367  * This is called by comedi but never from inside the driver.
368  */
369 static int usbdux_ai_cancel(struct comedi_device *dev,
370                             struct comedi_subdevice *s)
371 {
372         struct usbduxsub *this_usbduxsub;
373         int res = 0;
374
375         /* force unlink of all urbs */
376         this_usbduxsub = dev->private;
377         if (!this_usbduxsub)
378                 return -EFAULT;
379
380         dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
381
382         /* prevent other CPUs from submitting new commands just now */
383         down(&this_usbduxsub->sem);
384         if (!(this_usbduxsub->probed)) {
385                 up(&this_usbduxsub->sem);
386                 return -ENODEV;
387         }
388         /* unlink only if the urb really has been submitted */
389         res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
390         up(&this_usbduxsub->sem);
391         return res;
392 }
393
394 /* analogue IN - interrupt service routine */
395 static void usbduxsub_ai_IsocIrq(struct urb *urb)
396 {
397         int i, err, n;
398         struct usbduxsub *this_usbduxsub;
399         struct comedi_device *this_comedidev;
400         struct comedi_subdevice *s;
401
402         /* the context variable points to the subdevice */
403         this_comedidev = urb->context;
404         /* the private structure of the subdevice is struct usbduxsub */
405         this_usbduxsub = this_comedidev->private;
406         /* subdevice which is the AD converter */
407         s = this_comedidev->subdevices + SUBDEV_AD;
408
409         /* first we test if something unusual has just happened */
410         switch (urb->status) {
411         case 0:
412                 /* copy the result in the transfer buffer */
413                 memcpy(this_usbduxsub->inBuffer,
414                        urb->transfer_buffer, SIZEINBUF);
415                 break;
416         case -EILSEQ:
417                 /* error in the ISOchronous data */
418                 /* we don't copy the data into the transfer buffer */
419                 /* and recycle the last data byte */
420                 dev_dbg(&urb->dev->dev,
421                         "comedi%d: usbdux: CRC error in ISO IN stream.\n",
422                         this_usbduxsub->comedidev->minor);
423
424                 break;
425
426         case -ECONNRESET:
427         case -ENOENT:
428         case -ESHUTDOWN:
429         case -ECONNABORTED:
430                 /* happens after an unlink command */
431                 if (this_usbduxsub->ai_cmd_running) {
432                         /* we are still running a command */
433                         /* tell this comedi */
434                         s->async->events |= COMEDI_CB_EOA;
435                         s->async->events |= COMEDI_CB_ERROR;
436                         comedi_event(this_usbduxsub->comedidev, s);
437                         /* stop the transfer w/o unlink */
438                         usbdux_ai_stop(this_usbduxsub, 0);
439                 }
440                 return;
441
442         default:
443                 /* a real error on the bus */
444                 /* pass error to comedi if we are really running a command */
445                 if (this_usbduxsub->ai_cmd_running) {
446                         dev_err(&urb->dev->dev,
447                                 "Non-zero urb status received in ai intr "
448                                 "context: %d\n", urb->status);
449                         s->async->events |= COMEDI_CB_EOA;
450                         s->async->events |= COMEDI_CB_ERROR;
451                         comedi_event(this_usbduxsub->comedidev, s);
452                         /* don't do an unlink here */
453                         usbdux_ai_stop(this_usbduxsub, 0);
454                 }
455                 return;
456         }
457
458         /*
459          * at this point we are reasonably sure that nothing dodgy has happened
460          * are we running a command?
461          */
462         if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
463                 /*
464                  * not running a command, do not continue execution if no
465                  * asynchronous command is running in particular not resubmit
466                  */
467                 return;
468         }
469
470         urb->dev = this_usbduxsub->usbdev;
471
472         /* resubmit the urb */
473         err = usb_submit_urb(urb, GFP_ATOMIC);
474         if (unlikely(err < 0)) {
475                 dev_err(&urb->dev->dev,
476                         "comedi_: urb resubmit failed in int-context! err=%d\n",
477                         err);
478                 if (err == -EL2NSYNC)
479                         dev_err(&urb->dev->dev,
480                                 "buggy USB host controller or bug in IRQ "
481                                 "handler!\n");
482                 s->async->events |= COMEDI_CB_EOA;
483                 s->async->events |= COMEDI_CB_ERROR;
484                 comedi_event(this_usbduxsub->comedidev, s);
485                 /* don't do an unlink here */
486                 usbdux_ai_stop(this_usbduxsub, 0);
487                 return;
488         }
489
490         this_usbduxsub->ai_counter--;
491         if (likely(this_usbduxsub->ai_counter > 0))
492                 return;
493
494         /* timer zero, transfer measurements to comedi */
495         this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
496
497         /* test, if we transmit only a fixed number of samples */
498         if (!(this_usbduxsub->ai_continous)) {
499                 /* not continuous, fixed number of samples */
500                 this_usbduxsub->ai_sample_count--;
501                 /* all samples received? */
502                 if (this_usbduxsub->ai_sample_count < 0) {
503                         /* prevent a resubmit next time */
504                         usbdux_ai_stop(this_usbduxsub, 0);
505                         /* say comedi that the acquistion is over */
506                         s->async->events |= COMEDI_CB_EOA;
507                         comedi_event(this_usbduxsub->comedidev, s);
508                         return;
509                 }
510         }
511         /* get the data from the USB bus and hand it over to comedi */
512         n = s->async->cmd.chanlist_len;
513         for (i = 0; i < n; i++) {
514                 /* transfer data */
515                 if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
516                         err = comedi_buf_put
517                             (s->async,
518                              le16_to_cpu(this_usbduxsub->inBuffer[i]) ^ 0x800);
519                 } else {
520                         err = comedi_buf_put
521                             (s->async,
522                              le16_to_cpu(this_usbduxsub->inBuffer[i]));
523                 }
524                 if (unlikely(err == 0)) {
525                         /* buffer overflow */
526                         usbdux_ai_stop(this_usbduxsub, 0);
527                         return;
528                 }
529         }
530         /* tell comedi that data is there */
531         s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
532         comedi_event(this_usbduxsub->comedidev, s);
533 }
534
535 static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp)
536 {
537         int i = 0;
538         int err = 0;
539
540         if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
541                 for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
542                         if (usbduxsub_tmp->urbOut[i])
543                                 usb_kill_urb(usbduxsub_tmp->urbOut[i]);
544
545                         dev_dbg(&usbduxsub_tmp->interface->dev,
546                                 "comedi: usbdux: unlinked OutURB %d: res=%d\n",
547                                 i, err);
548                 }
549         }
550         return err;
551 }
552
553 /* This will cancel a running acquisition operation
554  * in any context.
555  */
556 static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
557 {
558         int ret = 0;
559
560         if (!this_usbduxsub)
561                 return -EFAULT;
562         dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
563
564         if (do_unlink)
565                 ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
566
567         this_usbduxsub->ao_cmd_running = 0;
568
569         return ret;
570 }
571
572 /* force unlink, is called by comedi */
573 static int usbdux_ao_cancel(struct comedi_device *dev,
574                             struct comedi_subdevice *s)
575 {
576         struct usbduxsub *this_usbduxsub = dev->private;
577         int res = 0;
578
579         if (!this_usbduxsub)
580                 return -EFAULT;
581
582         /* prevent other CPUs from submitting a command just now */
583         down(&this_usbduxsub->sem);
584         if (!(this_usbduxsub->probed)) {
585                 up(&this_usbduxsub->sem);
586                 return -ENODEV;
587         }
588         /* unlink only if it is really running */
589         res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
590         up(&this_usbduxsub->sem);
591         return res;
592 }
593
594 static void usbduxsub_ao_IsocIrq(struct urb *urb)
595 {
596         int i, ret;
597         int8_t *datap;
598         struct usbduxsub *this_usbduxsub;
599         struct comedi_device *this_comedidev;
600         struct comedi_subdevice *s;
601
602         /* the context variable points to the subdevice */
603         this_comedidev = urb->context;
604         /* the private structure of the subdevice is struct usbduxsub */
605         this_usbduxsub = this_comedidev->private;
606
607         s = this_comedidev->subdevices + SUBDEV_DA;
608
609         switch (urb->status) {
610         case 0:
611                 /* success */
612                 break;
613
614         case -ECONNRESET:
615         case -ENOENT:
616         case -ESHUTDOWN:
617         case -ECONNABORTED:
618                 /* after an unlink command, unplug, ... etc */
619                 /* no unlink needed here. Already shutting down. */
620                 if (this_usbduxsub->ao_cmd_running) {
621                         s->async->events |= COMEDI_CB_EOA;
622                         comedi_event(this_usbduxsub->comedidev, s);
623                         usbdux_ao_stop(this_usbduxsub, 0);
624                 }
625                 return;
626
627         default:
628                 /* a real error */
629                 if (this_usbduxsub->ao_cmd_running) {
630                         dev_err(&urb->dev->dev,
631                                 "comedi_: Non-zero urb status received in ao "
632                                 "intr context: %d\n", urb->status);
633                         s->async->events |= COMEDI_CB_ERROR;
634                         s->async->events |= COMEDI_CB_EOA;
635                         comedi_event(this_usbduxsub->comedidev, s);
636                         /* we do an unlink if we are in the high speed mode */
637                         usbdux_ao_stop(this_usbduxsub, 0);
638                 }
639                 return;
640         }
641
642         /* are we actually running? */
643         if (!(this_usbduxsub->ao_cmd_running))
644                 return;
645
646         /* normal operation: executing a command in this subdevice */
647         this_usbduxsub->ao_counter--;
648         if ((int)this_usbduxsub->ao_counter <= 0) {
649                 /* timer zero */
650                 this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
651
652                 /* handle non continous acquisition */
653                 if (!(this_usbduxsub->ao_continous)) {
654                         /* fixed number of samples */
655                         this_usbduxsub->ao_sample_count--;
656                         if (this_usbduxsub->ao_sample_count < 0) {
657                                 /* all samples transmitted */
658                                 usbdux_ao_stop(this_usbduxsub, 0);
659                                 s->async->events |= COMEDI_CB_EOA;
660                                 comedi_event(this_usbduxsub->comedidev, s);
661                                 /* no resubmit of the urb */
662                                 return;
663                         }
664                 }
665                 /* transmit data to the USB bus */
666                 ((uint8_t *) (urb->transfer_buffer))[0] =
667                     s->async->cmd.chanlist_len;
668                 for (i = 0; i < s->async->cmd.chanlist_len; i++) {
669                         short temp;
670                         if (i >= NUMOUTCHANNELS)
671                                 break;
672
673                         /* pointer to the DA */
674                         datap =
675                             (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1]));
676                         /* get the data from comedi */
677                         ret = comedi_buf_get(s->async, &temp);
678                         datap[0] = temp;
679                         datap[1] = temp >> 8;
680                         datap[2] = this_usbduxsub->dac_commands[i];
681                         /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
682                         /* datap[0],datap[1],datap[2]); */
683                         if (ret < 0) {
684                                 dev_err(&urb->dev->dev,
685                                         "comedi: buffer underflow\n");
686                                 s->async->events |= COMEDI_CB_EOA;
687                                 s->async->events |= COMEDI_CB_OVERFLOW;
688                         }
689                         /* transmit data to comedi */
690                         s->async->events |= COMEDI_CB_BLOCK;
691                         comedi_event(this_usbduxsub->comedidev, s);
692                 }
693         }
694         urb->transfer_buffer_length = SIZEOUTBUF;
695         urb->dev = this_usbduxsub->usbdev;
696         urb->status = 0;
697         if (this_usbduxsub->ao_cmd_running) {
698                 if (this_usbduxsub->high_speed) {
699                         /* uframes */
700                         urb->interval = 8;
701                 } else {
702                         /* frames */
703                         urb->interval = 1;
704                 }
705                 urb->number_of_packets = 1;
706                 urb->iso_frame_desc[0].offset = 0;
707                 urb->iso_frame_desc[0].length = SIZEOUTBUF;
708                 urb->iso_frame_desc[0].status = 0;
709                 ret = usb_submit_urb(urb, GFP_ATOMIC);
710                 if (ret < 0) {
711                         dev_err(&urb->dev->dev,
712                                 "comedi_: ao urb resubm failed in int-cont. "
713                                 "ret=%d", ret);
714                         if (ret == EL2NSYNC)
715                                 dev_err(&urb->dev->dev,
716                                         "buggy USB host controller or bug in "
717                                         "IRQ handling!\n");
718
719                         s->async->events |= COMEDI_CB_EOA;
720                         s->async->events |= COMEDI_CB_ERROR;
721                         comedi_event(this_usbduxsub->comedidev, s);
722                         /* don't do an unlink here */
723                         usbdux_ao_stop(this_usbduxsub, 0);
724                 }
725         }
726 }
727
728 static int usbduxsub_start(struct usbduxsub *usbduxsub)
729 {
730         int errcode = 0;
731         uint8_t local_transfer_buffer[16];
732
733         /* 7f92 to zero */
734         local_transfer_buffer[0] = 0;
735         errcode = usb_control_msg(usbduxsub->usbdev,
736                                   /* create a pipe for a control transfer */
737                                   usb_sndctrlpipe(usbduxsub->usbdev, 0),
738                                   /* bRequest, "Firmware" */
739                                   USBDUXSUB_FIRMWARE,
740                                   /* bmRequestType */
741                                   VENDOR_DIR_OUT,
742                                   /* Value */
743                                   USBDUXSUB_CPUCS,
744                                   /* Index */
745                                   0x0000,
746                                   /* address of the transfer buffer */
747                                   local_transfer_buffer,
748                                   /* Length */
749                                   1,
750                                   /* Timeout */
751                                   BULK_TIMEOUT);
752         if (errcode < 0) {
753                 dev_err(&usbduxsub->interface->dev,
754                         "comedi_: control msg failed (start)\n");
755                 return errcode;
756         }
757         return 0;
758 }
759
760 static int usbduxsub_stop(struct usbduxsub *usbduxsub)
761 {
762         int errcode = 0;
763
764         uint8_t local_transfer_buffer[16];
765
766         /* 7f92 to one */
767         local_transfer_buffer[0] = 1;
768         errcode = usb_control_msg(usbduxsub->usbdev,
769                                   usb_sndctrlpipe(usbduxsub->usbdev, 0),
770                                   /* bRequest, "Firmware" */
771                                   USBDUXSUB_FIRMWARE,
772                                   /* bmRequestType */
773                                   VENDOR_DIR_OUT,
774                                   /* Value */
775                                   USBDUXSUB_CPUCS,
776                                   /* Index */
777                                   0x0000, local_transfer_buffer,
778                                   /* Length */
779                                   1,
780                                   /* Timeout */
781                                   BULK_TIMEOUT);
782         if (errcode < 0) {
783                 dev_err(&usbduxsub->interface->dev,
784                         "comedi_: control msg failed (stop)\n");
785                 return errcode;
786         }
787         return 0;
788 }
789
790 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
791                             uint8_t *local_transfer_buffer,
792                             unsigned int startAddr, unsigned int len)
793 {
794         int errcode;
795
796         errcode = usb_control_msg(usbduxsub->usbdev,
797                                   usb_sndctrlpipe(usbduxsub->usbdev, 0),
798                                   /* brequest, firmware */
799                                   USBDUXSUB_FIRMWARE,
800                                   /* bmRequestType */
801                                   VENDOR_DIR_OUT,
802                                   /* value */
803                                   startAddr,
804                                   /* index */
805                                   0x0000,
806                                   /* our local safe buffer */
807                                   local_transfer_buffer,
808                                   /* length */
809                                   len,
810                                   /* timeout */
811                                   BULK_TIMEOUT);
812         dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode);
813         if (errcode < 0) {
814                 dev_err(&usbduxsub->interface->dev, "comedi_: upload failed\n");
815                 return errcode;
816         }
817         return 0;
818 }
819
820 #define FIRMWARE_MAX_LEN 0x2000
821
822 static int firmwareUpload(struct usbduxsub *usbduxsub,
823                           const u8 *firmwareBinary, int sizeFirmware)
824 {
825         int ret;
826         uint8_t *fwBuf;
827
828         if (!firmwareBinary)
829                 return 0;
830
831         if (sizeFirmware > FIRMWARE_MAX_LEN) {
832                 dev_err(&usbduxsub->interface->dev,
833                         "usbdux firmware binary it too large for FX2.\n");
834                 return -ENOMEM;
835         }
836
837         /* we generate a local buffer for the firmware */
838         fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL);
839         if (!fwBuf) {
840                 dev_err(&usbduxsub->interface->dev,
841                         "comedi_: mem alloc for firmware failed\n");
842                 return -ENOMEM;
843         }
844
845         ret = usbduxsub_stop(usbduxsub);
846         if (ret < 0) {
847                 dev_err(&usbduxsub->interface->dev,
848                         "comedi_: can not stop firmware\n");
849                 kfree(fwBuf);
850                 return ret;
851         }
852
853         ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware);
854         if (ret < 0) {
855                 dev_err(&usbduxsub->interface->dev,
856                         "comedi_: firmware upload failed\n");
857                 kfree(fwBuf);
858                 return ret;
859         }
860         ret = usbduxsub_start(usbduxsub);
861         if (ret < 0) {
862                 dev_err(&usbduxsub->interface->dev,
863                         "comedi_: can not start firmware\n");
864                 kfree(fwBuf);
865                 return ret;
866         }
867         kfree(fwBuf);
868         return 0;
869 }
870
871 static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
872 {
873         int i, errFlag;
874
875         if (!usbduxsub)
876                 return -EFAULT;
877
878         /* Submit all URBs and start the transfer on the bus */
879         for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
880                 /* in case of a resubmission after an unlink... */
881                 usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
882                 usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
883                 usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
884                 usbduxsub->urbIn[i]->status = 0;
885                 usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
886                 dev_dbg(&usbduxsub->interface->dev,
887                         "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
888                         usbduxsub->comedidev->minor, i,
889                         (usbduxsub->urbIn[i]->context),
890                         (usbduxsub->urbIn[i]->dev),
891                         (usbduxsub->urbIn[i]->interval));
892                 errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
893                 if (errFlag) {
894                         dev_err(&usbduxsub->interface->dev,
895                                 "comedi_: ai: usb_submit_urb(%d) error %d\n",
896                                 i, errFlag);
897                         return errFlag;
898                 }
899         }
900         return 0;
901 }
902
903 static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
904 {
905         int i, errFlag;
906
907         if (!usbduxsub)
908                 return -EFAULT;
909
910         for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
911                 dev_dbg(&usbduxsub->interface->dev,
912                         "comedi_: submitting out-urb[%d]\n", i);
913                 /* in case of a resubmission after an unlink... */
914                 usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
915                 usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
916                 usbduxsub->urbOut[i]->status = 0;
917                 usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
918                 errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
919                 if (errFlag) {
920                         dev_err(&usbduxsub->interface->dev,
921                                 "comedi_: ao: usb_submit_urb(%d) error %d\n",
922                                 i, errFlag);
923                         return errFlag;
924                 }
925         }
926         return 0;
927 }
928
929 static int usbdux_ai_cmdtest(struct comedi_device *dev,
930                              struct comedi_subdevice *s, struct comedi_cmd *cmd)
931 {
932         int err = 0, tmp, i;
933         unsigned int tmpTimer;
934         struct usbduxsub *this_usbduxsub = dev->private;
935
936         if (!(this_usbduxsub->probed))
937                 return -ENODEV;
938
939         dev_dbg(&this_usbduxsub->interface->dev,
940                 "comedi%d: usbdux_ai_cmdtest\n", dev->minor);
941
942         /* make sure triggers are valid */
943         /* Only immediate triggers are allowed */
944         tmp = cmd->start_src;
945         cmd->start_src &= TRIG_NOW | TRIG_INT;
946         if (!cmd->start_src || tmp != cmd->start_src)
947                 err++;
948
949         /* trigger should happen timed */
950         tmp = cmd->scan_begin_src;
951         /* start a new _scan_ with a timer */
952         cmd->scan_begin_src &= TRIG_TIMER;
953         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
954                 err++;
955
956         /* scanning is continuous */
957         tmp = cmd->convert_src;
958         cmd->convert_src &= TRIG_NOW;
959         if (!cmd->convert_src || tmp != cmd->convert_src)
960                 err++;
961
962         /* issue a trigger when scan is finished and start a new scan */
963         tmp = cmd->scan_end_src;
964         cmd->scan_end_src &= TRIG_COUNT;
965         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
966                 err++;
967
968         /* trigger at the end of count events or not, stop condition or not */
969         tmp = cmd->stop_src;
970         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
971         if (!cmd->stop_src || tmp != cmd->stop_src)
972                 err++;
973
974         if (err)
975                 return 1;
976
977         /*
978          * step 2: make sure trigger sources are unique and mutually compatible
979          * note that mutual compatibility is not an issue here
980          */
981         if (cmd->scan_begin_src != TRIG_FOLLOW &&
982             cmd->scan_begin_src != TRIG_EXT &&
983             cmd->scan_begin_src != TRIG_TIMER)
984                 err++;
985         if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
986                 err++;
987
988         if (err)
989                 return 2;
990
991         /* step 3: make sure arguments are trivially compatible */
992         if (cmd->start_arg != 0) {
993                 cmd->start_arg = 0;
994                 err++;
995         }
996
997         if (cmd->scan_begin_src == TRIG_FOLLOW) {
998                 /* internal trigger */
999                 if (cmd->scan_begin_arg != 0) {
1000                         cmd->scan_begin_arg = 0;
1001                         err++;
1002                 }
1003         }
1004
1005         if (cmd->scan_begin_src == TRIG_TIMER) {
1006                 if (this_usbduxsub->high_speed) {
1007                         /*
1008                          * In high speed mode microframes are possible.
1009                          * However, during one microframe we can roughly
1010                          * sample one channel. Thus, the more channels
1011                          * are in the channel list the more time we need.
1012                          */
1013                         i = 1;
1014                         /* find a power of 2 for the number of channels */
1015                         while (i < (cmd->chanlist_len))
1016                                 i = i * 2;
1017
1018                         if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
1019                                 cmd->scan_begin_arg = 1000000 / 8 * i;
1020                                 err++;
1021                         }
1022                         /* now calc the real sampling rate with all the
1023                          * rounding errors */
1024                         tmpTimer =
1025                             ((unsigned int)(cmd->scan_begin_arg / 125000)) *
1026                             125000;
1027                         if (cmd->scan_begin_arg != tmpTimer) {
1028                                 cmd->scan_begin_arg = tmpTimer;
1029                                 err++;
1030                         }
1031                 } else {
1032                         /* full speed */
1033                         /* 1kHz scans every USB frame */
1034                         if (cmd->scan_begin_arg < 1000000) {
1035                                 cmd->scan_begin_arg = 1000000;
1036                                 err++;
1037                         }
1038                         /*
1039                          * calc the real sampling rate with the rounding errors
1040                          */
1041                         tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
1042                                                    1000000)) * 1000000;
1043                         if (cmd->scan_begin_arg != tmpTimer) {
1044                                 cmd->scan_begin_arg = tmpTimer;
1045                                 err++;
1046                         }
1047                 }
1048         }
1049         /* the same argument */
1050         if (cmd->scan_end_arg != cmd->chanlist_len) {
1051                 cmd->scan_end_arg = cmd->chanlist_len;
1052                 err++;
1053         }
1054
1055         if (cmd->stop_src == TRIG_COUNT) {
1056                 /* any count is allowed */
1057         } else {
1058                 /* TRIG_NONE */
1059                 if (cmd->stop_arg != 0) {
1060                         cmd->stop_arg = 0;
1061                         err++;
1062                 }
1063         }
1064
1065         if (err)
1066                 return 3;
1067
1068         return 0;
1069 }
1070
1071 /*
1072  * creates the ADC command for the MAX1271
1073  * range is the range value from comedi
1074  */
1075 static int8_t create_adc_command(unsigned int chan, int range)
1076 {
1077         int8_t p = (range <= 1);
1078         int8_t r = ((range % 2) == 0);
1079         return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
1080 }
1081
1082 /* bulk transfers to usbdux */
1083
1084 #define SENDADCOMMANDS            0
1085 #define SENDDACOMMANDS            1
1086 #define SENDDIOCONFIGCOMMAND      2
1087 #define SENDDIOBITSCOMMAND        3
1088 #define SENDSINGLEAD              4
1089 #define READCOUNTERCOMMAND        5
1090 #define WRITECOUNTERCOMMAND       6
1091 #define SENDPWMON                 7
1092 #define SENDPWMOFF                8
1093
1094 static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
1095 {
1096         int result, nsent;
1097
1098         this_usbduxsub->dux_commands[0] = cmd_type;
1099 #ifdef NOISY_DUX_DEBUGBUG
1100         printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
1101                this_usbduxsub->comedidev->minor);
1102         for (result = 0; result < SIZEOFDUXBUFFER; result++)
1103                 printk(" %02x", this_usbduxsub->dux_commands[result]);
1104         printk("\n");
1105 #endif
1106         result = usb_bulk_msg(this_usbduxsub->usbdev,
1107                               usb_sndbulkpipe(this_usbduxsub->usbdev,
1108                                               COMMAND_OUT_EP),
1109                               this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
1110                               &nsent, BULK_TIMEOUT);
1111         if (result < 0)
1112                 dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1113                         "could not transmit dux_command to the usb-device, "
1114                         "err=%d\n", this_usbduxsub->comedidev->minor, result);
1115
1116         return result;
1117 }
1118
1119 static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
1120 {
1121         int result = (-EFAULT);
1122         int nrec;
1123         int i;
1124
1125         for (i = 0; i < RETRIES; i++) {
1126                 result = usb_bulk_msg(this_usbduxsub->usbdev,
1127                                       usb_rcvbulkpipe(this_usbduxsub->usbdev,
1128                                                       COMMAND_IN_EP),
1129                                       this_usbduxsub->insnBuffer, SIZEINSNBUF,
1130                                       &nrec, BULK_TIMEOUT);
1131                 if (result < 0) {
1132                         dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1133                                 "insn: USB error %d while receiving DUX command"
1134                                 "\n", this_usbduxsub->comedidev->minor, result);
1135                         return result;
1136                 }
1137                 if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command)
1138                         return result;
1139         }
1140         /* this is only reached if the data has been requested a couple of
1141          * times */
1142         dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
1143                 "wrong data returned from firmware: want cmd %d, got cmd %d.\n",
1144                 this_usbduxsub->comedidev->minor, command,
1145                 le16_to_cpu(this_usbduxsub->insnBuffer[0]));
1146         return -EFAULT;
1147 }
1148
1149 static int usbdux_ai_inttrig(struct comedi_device *dev,
1150                              struct comedi_subdevice *s, unsigned int trignum)
1151 {
1152         int ret;
1153         struct usbduxsub *this_usbduxsub = dev->private;
1154         if (!this_usbduxsub)
1155                 return -EFAULT;
1156
1157         down(&this_usbduxsub->sem);
1158         if (!(this_usbduxsub->probed)) {
1159                 up(&this_usbduxsub->sem);
1160                 return -ENODEV;
1161         }
1162         dev_dbg(&this_usbduxsub->interface->dev,
1163                 "comedi%d: usbdux_ai_inttrig\n", dev->minor);
1164
1165         if (trignum != 0) {
1166                 dev_err(&this_usbduxsub->interface->dev,
1167                         "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
1168                         dev->minor);
1169                 up(&this_usbduxsub->sem);
1170                 return -EINVAL;
1171         }
1172         if (!(this_usbduxsub->ai_cmd_running)) {
1173                 this_usbduxsub->ai_cmd_running = 1;
1174                 ret = usbduxsub_submit_InURBs(this_usbduxsub);
1175                 if (ret < 0) {
1176                         dev_err(&this_usbduxsub->interface->dev,
1177                                 "comedi%d: usbdux_ai_inttrig: "
1178                                 "urbSubmit: err=%d\n", dev->minor, ret);
1179                         this_usbduxsub->ai_cmd_running = 0;
1180                         up(&this_usbduxsub->sem);
1181                         return ret;
1182                 }
1183                 s->async->inttrig = NULL;
1184         } else {
1185                 dev_err(&this_usbduxsub->interface->dev,
1186                         "comedi%d: ai_inttrig but acqu is already running\n",
1187                         dev->minor);
1188         }
1189         up(&this_usbduxsub->sem);
1190         return 1;
1191 }
1192
1193 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1194 {
1195         struct comedi_cmd *cmd = &s->async->cmd;
1196         unsigned int chan, range;
1197         int i, ret;
1198         struct usbduxsub *this_usbduxsub = dev->private;
1199         int result;
1200
1201         if (!this_usbduxsub)
1202                 return -EFAULT;
1203
1204         dev_dbg(&this_usbduxsub->interface->dev,
1205                 "comedi%d: usbdux_ai_cmd\n", dev->minor);
1206
1207         /* block other CPUs from starting an ai_cmd */
1208         down(&this_usbduxsub->sem);
1209
1210         if (!(this_usbduxsub->probed)) {
1211                 up(&this_usbduxsub->sem);
1212                 return -ENODEV;
1213         }
1214         if (this_usbduxsub->ai_cmd_running) {
1215                 dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1216                         "ai_cmd not possible. Another ai_cmd is running.\n",
1217                         dev->minor);
1218                 up(&this_usbduxsub->sem);
1219                 return -EBUSY;
1220         }
1221         /* set current channel of the running acquisition to zero */
1222         s->async->cur_chan = 0;
1223
1224         this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
1225         for (i = 0; i < cmd->chanlist_len; ++i) {
1226                 chan = CR_CHAN(cmd->chanlist[i]);
1227                 range = CR_RANGE(cmd->chanlist[i]);
1228                 if (i >= NUMCHANNELS) {
1229                         dev_err(&this_usbduxsub->interface->dev,
1230                                 "comedi%d: channel list too long\n",
1231                                 dev->minor);
1232                         break;
1233                 }
1234                 this_usbduxsub->dux_commands[i + 2] =
1235                     create_adc_command(chan, range);
1236         }
1237
1238         dev_dbg(&this_usbduxsub->interface->dev,
1239                 "comedi %d: sending commands to the usb device: size=%u\n",
1240                 dev->minor, NUMCHANNELS);
1241
1242         result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
1243         if (result < 0) {
1244                 up(&this_usbduxsub->sem);
1245                 return result;
1246         }
1247
1248         if (this_usbduxsub->high_speed) {
1249                 /*
1250                  * every channel gets a time window of 125us. Thus, if we
1251                  * sample all 8 channels we need 1ms. If we sample only one
1252                  * channel we need only 125us
1253                  */
1254                 this_usbduxsub->ai_interval = 1;
1255                 /* find a power of 2 for the interval */
1256                 while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
1257                         this_usbduxsub->ai_interval =
1258                             (this_usbduxsub->ai_interval) * 2;
1259                 }
1260                 this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
1261                                                           (this_usbduxsub->
1262                                                            ai_interval));
1263         } else {
1264                 /* interval always 1ms */
1265                 this_usbduxsub->ai_interval = 1;
1266                 this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
1267         }
1268         if (this_usbduxsub->ai_timer < 1) {
1269                 dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
1270                         "timer=%d, scan_begin_arg=%d. "
1271                         "Not properly tested by cmdtest?\n", dev->minor,
1272                         this_usbduxsub->ai_timer, cmd->scan_begin_arg);
1273                 up(&this_usbduxsub->sem);
1274                 return -EINVAL;
1275         }
1276         this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
1277
1278         if (cmd->stop_src == TRIG_COUNT) {
1279                 /* data arrives as one packet */
1280                 this_usbduxsub->ai_sample_count = cmd->stop_arg;
1281                 this_usbduxsub->ai_continous = 0;
1282         } else {
1283                 /* continous acquisition */
1284                 this_usbduxsub->ai_continous = 1;
1285                 this_usbduxsub->ai_sample_count = 0;
1286         }
1287
1288         if (cmd->start_src == TRIG_NOW) {
1289                 /* enable this acquisition operation */
1290                 this_usbduxsub->ai_cmd_running = 1;
1291                 ret = usbduxsub_submit_InURBs(this_usbduxsub);
1292                 if (ret < 0) {
1293                         this_usbduxsub->ai_cmd_running = 0;
1294                         /* fixme: unlink here?? */
1295                         up(&this_usbduxsub->sem);
1296                         return ret;
1297                 }
1298                 s->async->inttrig = NULL;
1299         } else {
1300                 /* TRIG_INT */
1301                 /* don't enable the acquision operation */
1302                 /* wait for an internal signal */
1303                 s->async->inttrig = usbdux_ai_inttrig;
1304         }
1305         up(&this_usbduxsub->sem);
1306         return 0;
1307 }
1308
1309 /* Mode 0 is used to get a single conversion on demand */
1310 static int usbdux_ai_insn_read(struct comedi_device *dev,
1311                                struct comedi_subdevice *s,
1312                                struct comedi_insn *insn, unsigned int *data)
1313 {
1314         int i;
1315         unsigned int one = 0;
1316         int chan, range;
1317         int err;
1318         struct usbduxsub *this_usbduxsub = dev->private;
1319
1320         if (!this_usbduxsub)
1321                 return 0;
1322
1323         dev_dbg(&this_usbduxsub->interface->dev,
1324                 "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1325                 dev->minor, insn->n, insn->subdev);
1326
1327         down(&this_usbduxsub->sem);
1328         if (!(this_usbduxsub->probed)) {
1329                 up(&this_usbduxsub->sem);
1330                 return -ENODEV;
1331         }
1332         if (this_usbduxsub->ai_cmd_running) {
1333                 dev_err(&this_usbduxsub->interface->dev,
1334                         "comedi%d: ai_insn_read not possible. "
1335                         "Async Command is running.\n", dev->minor);
1336                 up(&this_usbduxsub->sem);
1337                 return 0;
1338         }
1339
1340         /* sample one channel */
1341         chan = CR_CHAN(insn->chanspec);
1342         range = CR_RANGE(insn->chanspec);
1343         /* set command for the first channel */
1344         this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
1345
1346         /* adc commands */
1347         err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1348         if (err < 0) {
1349                 up(&this_usbduxsub->sem);
1350                 return err;
1351         }
1352
1353         for (i = 0; i < insn->n; i++) {
1354                 err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1355                 if (err < 0) {
1356                         up(&this_usbduxsub->sem);
1357                         return 0;
1358                 }
1359                 one = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1360                 if (CR_RANGE(insn->chanspec) <= 1)
1361                         one = one ^ 0x800;
1362
1363                 data[i] = one;
1364         }
1365         up(&this_usbduxsub->sem);
1366         return i;
1367 }
1368
1369 /************************************/
1370 /* analog out */
1371
1372 static int usbdux_ao_insn_read(struct comedi_device *dev,
1373                                struct comedi_subdevice *s,
1374                                struct comedi_insn *insn, unsigned int *data)
1375 {
1376         int i;
1377         int chan = CR_CHAN(insn->chanspec);
1378         struct usbduxsub *this_usbduxsub = dev->private;
1379
1380         if (!this_usbduxsub)
1381                 return -EFAULT;
1382
1383         down(&this_usbduxsub->sem);
1384         if (!(this_usbduxsub->probed)) {
1385                 up(&this_usbduxsub->sem);
1386                 return -ENODEV;
1387         }
1388         for (i = 0; i < insn->n; i++)
1389                 data[i] = this_usbduxsub->outBuffer[chan];
1390
1391         up(&this_usbduxsub->sem);
1392         return i;
1393 }
1394
1395 static int usbdux_ao_insn_write(struct comedi_device *dev,
1396                                 struct comedi_subdevice *s,
1397                                 struct comedi_insn *insn, unsigned int *data)
1398 {
1399         int i, err;
1400         int chan = CR_CHAN(insn->chanspec);
1401         struct usbduxsub *this_usbduxsub = dev->private;
1402
1403         if (!this_usbduxsub)
1404                 return -EFAULT;
1405
1406         dev_dbg(&this_usbduxsub->interface->dev,
1407                 "comedi%d: ao_insn_write\n", dev->minor);
1408
1409         down(&this_usbduxsub->sem);
1410         if (!(this_usbduxsub->probed)) {
1411                 up(&this_usbduxsub->sem);
1412                 return -ENODEV;
1413         }
1414         if (this_usbduxsub->ao_cmd_running) {
1415                 dev_err(&this_usbduxsub->interface->dev,
1416                         "comedi%d: ao_insn_write: "
1417                         "ERROR: asynchronous ao_cmd is running\n", dev->minor);
1418                 up(&this_usbduxsub->sem);
1419                 return 0;
1420         }
1421
1422         for (i = 0; i < insn->n; i++) {
1423                 dev_dbg(&this_usbduxsub->interface->dev,
1424                         "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1425                         dev->minor, chan, i, data[i]);
1426
1427                 /* number of channels: 1 */
1428                 this_usbduxsub->dux_commands[1] = 1;
1429                 /* one 16 bit value */
1430                 *((int16_t *) (this_usbduxsub->dux_commands + 2)) =
1431                     cpu_to_le16(data[i]);
1432                 this_usbduxsub->outBuffer[chan] = data[i];
1433                 /* channel number */
1434                 this_usbduxsub->dux_commands[4] = (chan << 6);
1435                 err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
1436                 if (err < 0) {
1437                         up(&this_usbduxsub->sem);
1438                         return err;
1439                 }
1440         }
1441         up(&this_usbduxsub->sem);
1442
1443         return i;
1444 }
1445
1446 static int usbdux_ao_inttrig(struct comedi_device *dev,
1447                              struct comedi_subdevice *s, unsigned int trignum)
1448 {
1449         int ret;
1450         struct usbduxsub *this_usbduxsub = dev->private;
1451
1452         if (!this_usbduxsub)
1453                 return -EFAULT;
1454
1455         down(&this_usbduxsub->sem);
1456         if (!(this_usbduxsub->probed)) {
1457                 up(&this_usbduxsub->sem);
1458                 return -ENODEV;
1459         }
1460         if (trignum != 0) {
1461                 dev_err(&this_usbduxsub->interface->dev,
1462                         "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1463                         dev->minor);
1464                 up(&this_usbduxsub->sem);
1465                 return -EINVAL;
1466         }
1467         if (!(this_usbduxsub->ao_cmd_running)) {
1468                 this_usbduxsub->ao_cmd_running = 1;
1469                 ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1470                 if (ret < 0) {
1471                         dev_err(&this_usbduxsub->interface->dev,
1472                                 "comedi%d: usbdux_ao_inttrig: submitURB: "
1473                                 "err=%d\n", dev->minor, ret);
1474                         this_usbduxsub->ao_cmd_running = 0;
1475                         up(&this_usbduxsub->sem);
1476                         return ret;
1477                 }
1478                 s->async->inttrig = NULL;
1479         } else {
1480                 dev_err(&this_usbduxsub->interface->dev,
1481                         "comedi%d: ao_inttrig but acqu is already running.\n",
1482                         dev->minor);
1483         }
1484         up(&this_usbduxsub->sem);
1485         return 1;
1486 }
1487
1488 static int usbdux_ao_cmdtest(struct comedi_device *dev,
1489                              struct comedi_subdevice *s, struct comedi_cmd *cmd)
1490 {
1491         int err = 0, tmp;
1492         struct usbduxsub *this_usbduxsub = dev->private;
1493
1494         if (!this_usbduxsub)
1495                 return -EFAULT;
1496
1497         if (!(this_usbduxsub->probed))
1498                 return -ENODEV;
1499
1500         dev_dbg(&this_usbduxsub->interface->dev,
1501                 "comedi%d: usbdux_ao_cmdtest\n", dev->minor);
1502
1503         /* make sure triggers are valid */
1504         /* Only immediate triggers are allowed */
1505         tmp = cmd->start_src;
1506         cmd->start_src &= TRIG_NOW | TRIG_INT;
1507         if (!cmd->start_src || tmp != cmd->start_src)
1508                 err++;
1509
1510         /* trigger should happen timed */
1511         tmp = cmd->scan_begin_src;
1512         /* just now we scan also in the high speed mode every frame */
1513         /* this is due to ehci driver limitations */
1514         if (0) {                /* (this_usbduxsub->high_speed) */
1515                 /* start immediately a new scan */
1516                 /* the sampling rate is set by the coversion rate */
1517                 cmd->scan_begin_src &= TRIG_FOLLOW;
1518         } else {
1519                 /* start a new scan (output at once) with a timer */
1520                 cmd->scan_begin_src &= TRIG_TIMER;
1521         }
1522         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1523                 err++;
1524
1525         /* scanning is continuous */
1526         tmp = cmd->convert_src;
1527         /* we always output at 1kHz just now all channels at once */
1528         if (0) {                /* (this_usbduxsub->high_speed) */
1529                 /*
1530                  * in usb-2.0 only one conversion it transmitted but with 8kHz/n
1531                  */
1532                 cmd->convert_src &= TRIG_TIMER;
1533         } else {
1534                 /* all conversion events happen simultaneously with a rate of
1535                  * 1kHz/n */
1536                 cmd->convert_src &= TRIG_NOW;
1537         }
1538         if (!cmd->convert_src || tmp != cmd->convert_src)
1539                 err++;
1540
1541         /* issue a trigger when scan is finished and start a new scan */
1542         tmp = cmd->scan_end_src;
1543         cmd->scan_end_src &= TRIG_COUNT;
1544         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1545                 err++;
1546
1547         /* trigger at the end of count events or not, stop condition or not */
1548         tmp = cmd->stop_src;
1549         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1550         if (!cmd->stop_src || tmp != cmd->stop_src)
1551                 err++;
1552
1553         if (err)
1554                 return 1;
1555
1556         /*
1557          * step 2: make sure trigger sources are unique and mutually compatible
1558          * note that mutual compatibility is not an issue here
1559          */
1560         if (cmd->scan_begin_src != TRIG_FOLLOW &&
1561             cmd->scan_begin_src != TRIG_EXT &&
1562             cmd->scan_begin_src != TRIG_TIMER)
1563                 err++;
1564         if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1565                 err++;
1566
1567         if (err)
1568                 return 2;
1569
1570         /* step 3: make sure arguments are trivially compatible */
1571
1572         if (cmd->start_arg != 0) {
1573                 cmd->start_arg = 0;
1574                 err++;
1575         }
1576
1577         if (cmd->scan_begin_src == TRIG_FOLLOW) {
1578                 /* internal trigger */
1579                 if (cmd->scan_begin_arg != 0) {
1580                         cmd->scan_begin_arg = 0;
1581                         err++;
1582                 }
1583         }
1584
1585         if (cmd->scan_begin_src == TRIG_TIMER) {
1586                 /* timer */
1587                 if (cmd->scan_begin_arg < 1000000) {
1588                         cmd->scan_begin_arg = 1000000;
1589                         err++;
1590                 }
1591         }
1592         /* not used now, is for later use */
1593         if (cmd->convert_src == TRIG_TIMER) {
1594                 if (cmd->convert_arg < 125000) {
1595                         cmd->convert_arg = 125000;
1596                         err++;
1597                 }
1598         }
1599
1600         /* the same argument */
1601         if (cmd->scan_end_arg != cmd->chanlist_len) {
1602                 cmd->scan_end_arg = cmd->chanlist_len;
1603                 err++;
1604         }
1605
1606         if (cmd->stop_src == TRIG_COUNT) {
1607                 /* any count is allowed */
1608         } else {
1609                 /* TRIG_NONE */
1610                 if (cmd->stop_arg != 0) {
1611                         cmd->stop_arg = 0;
1612                         err++;
1613                 }
1614         }
1615
1616         dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, "
1617                 "scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, "
1618                 "convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src,
1619                 cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
1620
1621         if (err)
1622                 return 3;
1623
1624         return 0;
1625 }
1626
1627 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1628 {
1629         struct comedi_cmd *cmd = &s->async->cmd;
1630         unsigned int chan, gain;
1631         int i, ret;
1632         struct usbduxsub *this_usbduxsub = dev->private;
1633
1634         if (!this_usbduxsub)
1635                 return -EFAULT;
1636
1637         down(&this_usbduxsub->sem);
1638         if (!(this_usbduxsub->probed)) {
1639                 up(&this_usbduxsub->sem);
1640                 return -ENODEV;
1641         }
1642         dev_dbg(&this_usbduxsub->interface->dev,
1643                 "comedi%d: %s\n", dev->minor, __func__);
1644
1645         /* set current channel of the running acquisition to zero */
1646         s->async->cur_chan = 0;
1647         for (i = 0; i < cmd->chanlist_len; ++i) {
1648                 chan = CR_CHAN(cmd->chanlist[i]);
1649                 gain = CR_RANGE(cmd->chanlist[i]);
1650                 if (i >= NUMOUTCHANNELS) {
1651                         dev_err(&this_usbduxsub->interface->dev,
1652                                 "comedi%d: %s: channel list too long\n",
1653                                 dev->minor, __func__);
1654                         break;
1655                 }
1656                 this_usbduxsub->dac_commands[i] = (chan << 6);
1657                 dev_dbg(&this_usbduxsub->interface->dev,
1658                         "comedi%d: dac command for ch %d is %x\n",
1659                         dev->minor, i, this_usbduxsub->dac_commands[i]);
1660         }
1661
1662         /* we count in steps of 1ms (125us) */
1663         /* 125us mode not used yet */
1664         if (0) {                /* (this_usbduxsub->high_speed) */
1665                 /* 125us */
1666                 /* timing of the conversion itself: every 125 us */
1667                 this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1668         } else {
1669                 /* 1ms */
1670                 /* timing of the scan: we get all channels at once */
1671                 this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1672                 dev_dbg(&this_usbduxsub->interface->dev,
1673                         "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
1674                         "convert_src=%d, convert_arg=%d\n", dev->minor,
1675                         cmd->scan_begin_src, cmd->scan_begin_arg,
1676                         cmd->convert_src, cmd->convert_arg);
1677                 dev_dbg(&this_usbduxsub->interface->dev,
1678                         "comedi%d: ao_timer=%d (ms)\n",
1679                         dev->minor, this_usbduxsub->ao_timer);
1680                 if (this_usbduxsub->ao_timer < 1) {
1681                         dev_err(&this_usbduxsub->interface->dev,
1682                                 "comedi%d: usbdux: ao_timer=%d, "
1683                                 "scan_begin_arg=%d. "
1684                                 "Not properly tested by cmdtest?\n",
1685                                 dev->minor, this_usbduxsub->ao_timer,
1686                                 cmd->scan_begin_arg);
1687                         up(&this_usbduxsub->sem);
1688                         return -EINVAL;
1689                 }
1690         }
1691         this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1692
1693         if (cmd->stop_src == TRIG_COUNT) {
1694                 /* not continuous */
1695                 /* counter */
1696                 /* high speed also scans everything at once */
1697                 if (0) {        /* (this_usbduxsub->high_speed) */
1698                         this_usbduxsub->ao_sample_count =
1699                             (cmd->stop_arg) * (cmd->scan_end_arg);
1700                 } else {
1701                         /* there's no scan as the scan has been */
1702                         /* perf inside the FX2 */
1703                         /* data arrives as one packet */
1704                         this_usbduxsub->ao_sample_count = cmd->stop_arg;
1705                 }
1706                 this_usbduxsub->ao_continous = 0;
1707         } else {
1708                 /* continous acquisition */
1709                 this_usbduxsub->ao_continous = 1;
1710                 this_usbduxsub->ao_sample_count = 0;
1711         }
1712
1713         if (cmd->start_src == TRIG_NOW) {
1714                 /* enable this acquisition operation */
1715                 this_usbduxsub->ao_cmd_running = 1;
1716                 ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1717                 if (ret < 0) {
1718                         this_usbduxsub->ao_cmd_running = 0;
1719                         /* fixme: unlink here?? */
1720                         up(&this_usbduxsub->sem);
1721                         return ret;
1722                 }
1723                 s->async->inttrig = NULL;
1724         } else {
1725                 /* TRIG_INT */
1726                 /* submit the urbs later */
1727                 /* wait for an internal signal */
1728                 s->async->inttrig = usbdux_ao_inttrig;
1729         }
1730
1731         up(&this_usbduxsub->sem);
1732         return 0;
1733 }
1734
1735 static int usbdux_dio_insn_config(struct comedi_device *dev,
1736                                   struct comedi_subdevice *s,
1737                                   struct comedi_insn *insn, unsigned int *data)
1738 {
1739         int chan = CR_CHAN(insn->chanspec);
1740
1741         /* The input or output configuration of each digital line is
1742          * configured by a special insn_config instruction.  chanspec
1743          * contains the channel to be changed, and data[0] contains the
1744          * value COMEDI_INPUT or COMEDI_OUTPUT. */
1745
1746         switch (data[0]) {
1747         case INSN_CONFIG_DIO_OUTPUT:
1748                 s->io_bits |= 1 << chan;        /* 1 means Out */
1749                 break;
1750         case INSN_CONFIG_DIO_INPUT:
1751                 s->io_bits &= ~(1 << chan);
1752                 break;
1753         case INSN_CONFIG_DIO_QUERY:
1754                 data[1] =
1755                     (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1756                 break;
1757         default:
1758                 return -EINVAL;
1759                 break;
1760         }
1761         /* we don't tell the firmware here as it would take 8 frames */
1762         /* to submit the information. We do it in the insn_bits. */
1763         return insn->n;
1764 }
1765
1766 static int usbdux_dio_insn_bits(struct comedi_device *dev,
1767                                 struct comedi_subdevice *s,
1768                                 struct comedi_insn *insn, unsigned int *data)
1769 {
1770
1771         struct usbduxsub *this_usbduxsub = dev->private;
1772         int err;
1773
1774         if (!this_usbduxsub)
1775                 return -EFAULT;
1776
1777         down(&this_usbduxsub->sem);
1778
1779         if (!(this_usbduxsub->probed)) {
1780                 up(&this_usbduxsub->sem);
1781                 return -ENODEV;
1782         }
1783
1784         /* The insn data is a mask in data[0] and the new data
1785          * in data[1], each channel cooresponding to a bit. */
1786         s->state &= ~data[0];
1787         s->state |= data[0] & data[1];
1788         this_usbduxsub->dux_commands[1] = s->io_bits;
1789         this_usbduxsub->dux_commands[2] = s->state;
1790
1791         /* This command also tells the firmware to return */
1792         /* the digital input lines */
1793         err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1794         if (err < 0) {
1795                 up(&this_usbduxsub->sem);
1796                 return err;
1797         }
1798         err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1799         if (err < 0) {
1800                 up(&this_usbduxsub->sem);
1801                 return err;
1802         }
1803
1804         data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1805         up(&this_usbduxsub->sem);
1806         return insn->n;
1807 }
1808
1809 /* reads the 4 counters, only two are used just now */
1810 static int usbdux_counter_read(struct comedi_device *dev,
1811                                struct comedi_subdevice *s,
1812                                struct comedi_insn *insn, unsigned int *data)
1813 {
1814         struct usbduxsub *this_usbduxsub = dev->private;
1815         int chan = insn->chanspec;
1816         int err;
1817
1818         if (!this_usbduxsub)
1819                 return -EFAULT;
1820
1821         down(&this_usbduxsub->sem);
1822
1823         if (!(this_usbduxsub->probed)) {
1824                 up(&this_usbduxsub->sem);
1825                 return -ENODEV;
1826         }
1827
1828         err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1829         if (err < 0) {
1830                 up(&this_usbduxsub->sem);
1831                 return err;
1832         }
1833
1834         err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1835         if (err < 0) {
1836                 up(&this_usbduxsub->sem);
1837                 return err;
1838         }
1839
1840         data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]);
1841         up(&this_usbduxsub->sem);
1842         return 1;
1843 }
1844
1845 static int usbdux_counter_write(struct comedi_device *dev,
1846                                 struct comedi_subdevice *s,
1847                                 struct comedi_insn *insn, unsigned int *data)
1848 {
1849         struct usbduxsub *this_usbduxsub = dev->private;
1850         int err;
1851
1852         if (!this_usbduxsub)
1853                 return -EFAULT;
1854
1855         down(&this_usbduxsub->sem);
1856
1857         if (!(this_usbduxsub->probed)) {
1858                 up(&this_usbduxsub->sem);
1859                 return -ENODEV;
1860         }
1861
1862         this_usbduxsub->dux_commands[1] = insn->chanspec;
1863         *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
1864
1865         err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
1866         if (err < 0) {
1867                 up(&this_usbduxsub->sem);
1868                 return err;
1869         }
1870
1871         up(&this_usbduxsub->sem);
1872
1873         return 1;
1874 }
1875
1876 static int usbdux_counter_config(struct comedi_device *dev,
1877                                  struct comedi_subdevice *s,
1878                                  struct comedi_insn *insn, unsigned int *data)
1879 {
1880         /* nothing to do so far */
1881         return 2;
1882 }
1883
1884 /***********************************/
1885 /* PWM */
1886
1887 static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
1888 {
1889         int err = 0;
1890
1891         if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
1892                 if (usbduxsub_tmp->urbPwm)
1893                         usb_kill_urb(usbduxsub_tmp->urbPwm);
1894                 dev_dbg(&usbduxsub_tmp->interface->dev,
1895                         "comedi: unlinked PwmURB: res=%d\n", err);
1896         }
1897         return err;
1898 }
1899
1900 /* This cancels a running acquisition operation
1901  * in any context.
1902  */
1903 static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
1904 {
1905         int ret = 0;
1906
1907         if (!this_usbduxsub)
1908                 return -EFAULT;
1909
1910         dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
1911         if (do_unlink)
1912                 ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
1913
1914         this_usbduxsub->pwm_cmd_running = 0;
1915
1916         return ret;
1917 }
1918
1919 /* force unlink - is called by comedi */
1920 static int usbdux_pwm_cancel(struct comedi_device *dev,
1921                              struct comedi_subdevice *s)
1922 {
1923         struct usbduxsub *this_usbduxsub = dev->private;
1924         int res = 0;
1925
1926         /* unlink only if it is really running */
1927         res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
1928
1929         dev_dbg(&this_usbduxsub->interface->dev,
1930                 "comedi %d: sending pwm off command to the usb device.\n",
1931                 dev->minor);
1932
1933         return send_dux_commands(this_usbduxsub, SENDPWMOFF);
1934 }
1935
1936 static void usbduxsub_pwm_irq(struct urb *urb)
1937 {
1938         int ret;
1939         struct usbduxsub *this_usbduxsub;
1940         struct comedi_device *this_comedidev;
1941         struct comedi_subdevice *s;
1942
1943         /* printk(KERN_DEBUG "PWM: IRQ\n"); */
1944
1945         /* the context variable points to the subdevice */
1946         this_comedidev = urb->context;
1947         /* the private structure of the subdevice is struct usbduxsub */
1948         this_usbduxsub = this_comedidev->private;
1949
1950         s = this_comedidev->subdevices + SUBDEV_DA;
1951
1952         switch (urb->status) {
1953         case 0:
1954                 /* success */
1955                 break;
1956
1957         case -ECONNRESET:
1958         case -ENOENT:
1959         case -ESHUTDOWN:
1960         case -ECONNABORTED:
1961                 /*
1962                  * after an unlink command, unplug, ... etc
1963                  * no unlink needed here. Already shutting down.
1964                  */
1965                 if (this_usbduxsub->pwm_cmd_running)
1966                         usbdux_pwm_stop(this_usbduxsub, 0);
1967
1968                 return;
1969
1970         default:
1971                 /* a real error */
1972                 if (this_usbduxsub->pwm_cmd_running) {
1973                         dev_err(&this_usbduxsub->interface->dev,
1974                                 "comedi_: Non-zero urb status received in "
1975                                 "pwm intr context: %d\n", urb->status);
1976                         usbdux_pwm_stop(this_usbduxsub, 0);
1977                 }
1978                 return;
1979         }
1980
1981         /* are we actually running? */
1982         if (!(this_usbduxsub->pwm_cmd_running))
1983                 return;
1984
1985         urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
1986         urb->dev = this_usbduxsub->usbdev;
1987         urb->status = 0;
1988         if (this_usbduxsub->pwm_cmd_running) {
1989                 ret = usb_submit_urb(urb, GFP_ATOMIC);
1990                 if (ret < 0) {
1991                         dev_err(&this_usbduxsub->interface->dev,
1992                                 "comedi_: pwm urb resubm failed in int-cont. "
1993                                 "ret=%d", ret);
1994                         if (ret == EL2NSYNC)
1995                                 dev_err(&this_usbduxsub->interface->dev,
1996                                         "buggy USB host controller or bug in "
1997                                         "IRQ handling!\n");
1998
1999                         /* don't do an unlink here */
2000                         usbdux_pwm_stop(this_usbduxsub, 0);
2001                 }
2002         }
2003 }
2004
2005 static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
2006 {
2007         int errFlag;
2008
2009         if (!usbduxsub)
2010                 return -EFAULT;
2011
2012         dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
2013
2014         /* in case of a resubmission after an unlink... */
2015         usb_fill_bulk_urb(usbduxsub->urbPwm,
2016                           usbduxsub->usbdev,
2017                           usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
2018                           usbduxsub->urbPwm->transfer_buffer,
2019                           usbduxsub->sizePwmBuf, usbduxsub_pwm_irq,
2020                           usbduxsub->comedidev);
2021
2022         errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
2023         if (errFlag) {
2024                 dev_err(&usbduxsub->interface->dev,
2025                         "comedi_: usbdux: pwm: usb_submit_urb error %d\n",
2026                         errFlag);
2027                 return errFlag;
2028         }
2029         return 0;
2030 }
2031
2032 static int usbdux_pwm_period(struct comedi_device *dev,
2033                              struct comedi_subdevice *s, unsigned int period)
2034 {
2035         struct usbduxsub *this_usbduxsub = dev->private;
2036         int fx2delay = 255;
2037
2038         if (period < MIN_PWM_PERIOD) {
2039                 dev_err(&this_usbduxsub->interface->dev,
2040                         "comedi%d: illegal period setting for pwm.\n",
2041                         dev->minor);
2042                 return -EAGAIN;
2043         } else {
2044                 fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
2045                 if (fx2delay > 255) {
2046                         dev_err(&this_usbduxsub->interface->dev,
2047                                 "comedi%d: period %d for pwm is too low.\n",
2048                                 dev->minor, period);
2049                         return -EAGAIN;
2050                 }
2051         }
2052         this_usbduxsub->pwmDelay = fx2delay;
2053         this_usbduxsub->pwmPeriod = period;
2054         dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
2055                 __func__, period, fx2delay);
2056         return 0;
2057 }
2058
2059 /* is called from insn so there's no need to do all the sanity checks */
2060 static int usbdux_pwm_start(struct comedi_device *dev,
2061                             struct comedi_subdevice *s)
2062 {
2063         int ret, i;
2064         struct usbduxsub *this_usbduxsub = dev->private;
2065
2066         dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
2067                 dev->minor, __func__);
2068
2069         if (this_usbduxsub->pwm_cmd_running) {
2070                 /* already running */
2071                 return 0;
2072         }
2073
2074         this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay);
2075         ret = send_dux_commands(this_usbduxsub, SENDPWMON);
2076         if (ret < 0)
2077                 return ret;
2078
2079         /* initialise the buffer */
2080         for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
2081                 ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
2082
2083         this_usbduxsub->pwm_cmd_running = 1;
2084         ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
2085         if (ret < 0) {
2086                 this_usbduxsub->pwm_cmd_running = 0;
2087                 return ret;
2088         }
2089         return 0;
2090 }
2091
2092 /* generates the bit pattern for PWM with the optional sign bit */
2093 static int usbdux_pwm_pattern(struct comedi_device *dev,
2094                               struct comedi_subdevice *s, int channel,
2095                               unsigned int value, unsigned int sign)
2096 {
2097         struct usbduxsub *this_usbduxsub = dev->private;
2098         int i, szbuf;
2099         char *pBuf;
2100         char pwm_mask;
2101         char sgn_mask;
2102         char c;
2103
2104         if (!this_usbduxsub)
2105                 return -EFAULT;
2106
2107         /* this is the DIO bit which carries the PWM data */
2108         pwm_mask = (1 << channel);
2109         /* this is the DIO bit which carries the optional direction bit */
2110         sgn_mask = (16 << channel);
2111         /* this is the buffer which will be filled with the with bit */
2112         /* pattern for one period */
2113         szbuf = this_usbduxsub->sizePwmBuf;
2114         pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
2115         for (i = 0; i < szbuf; i++) {
2116                 c = *pBuf;
2117                 /* reset bits */
2118                 c = c & (~pwm_mask);
2119                 /* set the bit as long as the index is lower than the value */
2120                 if (i < value)
2121                         c = c | pwm_mask;
2122                 /* set the optional sign bit for a relay */
2123                 if (!sign) {
2124                         /* positive value */
2125                         c = c & (~sgn_mask);
2126                 } else {
2127                         /* negative value */
2128                         c = c | sgn_mask;
2129                 }
2130                 *(pBuf++) = c;
2131         }
2132         return 1;
2133 }
2134
2135 static int usbdux_pwm_write(struct comedi_device *dev,
2136                             struct comedi_subdevice *s,
2137                             struct comedi_insn *insn, unsigned int *data)
2138 {
2139         struct usbduxsub *this_usbduxsub = dev->private;
2140
2141         if (!this_usbduxsub)
2142                 return -EFAULT;
2143
2144         if ((insn->n) != 1) {
2145                 /*
2146                  * doesn't make sense to have more than one value here because
2147                  * it would just overwrite the PWM buffer a couple of times
2148                  */
2149                 return -EINVAL;
2150         }
2151
2152         /*
2153          * the sign is set via a special INSN only, this gives us 8 bits for
2154          * normal operation
2155          * relay sign 0 by default
2156          */
2157         return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
2158 }
2159
2160 static int usbdux_pwm_read(struct comedi_device *x1,
2161                            struct comedi_subdevice *x2, struct comedi_insn *x3,
2162                            unsigned int *x4)
2163 {
2164         /* not needed */
2165         return -EINVAL;
2166 };
2167
2168 /* switches on/off PWM */
2169 static int usbdux_pwm_config(struct comedi_device *dev,
2170                              struct comedi_subdevice *s,
2171                              struct comedi_insn *insn, unsigned int *data)
2172 {
2173         struct usbduxsub *this_usbduxsub = dev->private;
2174         switch (data[0]) {
2175         case INSN_CONFIG_ARM:
2176                 /* switch it on */
2177                 dev_dbg(&this_usbduxsub->interface->dev,
2178                         "comedi%d: %s: pwm on\n", dev->minor, __func__);
2179                 /*
2180                  * if not zero the PWM is limited to a certain time which is
2181                  * not supported here
2182                  */
2183                 if (data[1] != 0)
2184                         return -EINVAL;
2185                 return usbdux_pwm_start(dev, s);
2186         case INSN_CONFIG_DISARM:
2187                 dev_dbg(&this_usbduxsub->interface->dev,
2188                         "comedi%d: %s: pwm off\n", dev->minor, __func__);
2189                 return usbdux_pwm_cancel(dev, s);
2190         case INSN_CONFIG_GET_PWM_STATUS:
2191                 /*
2192                  * to check if the USB transmission has failed or in case PWM
2193                  * was limited to n cycles to check if it has terminated
2194                  */
2195                 data[1] = this_usbduxsub->pwm_cmd_running;
2196                 return 0;
2197         case INSN_CONFIG_PWM_SET_PERIOD:
2198                 dev_dbg(&this_usbduxsub->interface->dev,
2199                         "comedi%d: %s: setting period\n", dev->minor, __func__);
2200                 return usbdux_pwm_period(dev, s, data[1]);
2201         case INSN_CONFIG_PWM_GET_PERIOD:
2202                 data[1] = this_usbduxsub->pwmPeriod;
2203                 return 0;
2204         case INSN_CONFIG_PWM_SET_H_BRIDGE:
2205                 /* value in the first byte and the sign in the second for a
2206                    relay */
2207                 return usbdux_pwm_pattern(dev, s,
2208                                           /* the channel number */
2209                                           CR_CHAN(insn->chanspec),
2210                                           /* actual PWM data */
2211                                           data[1],
2212                                           /* just a sign */
2213                                           (data[2] != 0));
2214         case INSN_CONFIG_PWM_GET_H_BRIDGE:
2215                 /* values are not kept in this driver, nothing to return here */
2216                 return -EINVAL;
2217         }
2218         return -EINVAL;
2219 }
2220
2221 /* end of PWM */
2222 /*****************************************************************/
2223
2224 static void tidy_up(struct usbduxsub *usbduxsub_tmp)
2225 {
2226         int i;
2227
2228         if (!usbduxsub_tmp)
2229                 return;
2230         dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
2231
2232         /* shows the usb subsystem that the driver is down */
2233         if (usbduxsub_tmp->interface)
2234                 usb_set_intfdata(usbduxsub_tmp->interface, NULL);
2235
2236         usbduxsub_tmp->probed = 0;
2237
2238         if (usbduxsub_tmp->urbIn) {
2239                 if (usbduxsub_tmp->ai_cmd_running) {
2240                         usbduxsub_tmp->ai_cmd_running = 0;
2241                         usbduxsub_unlink_InURBs(usbduxsub_tmp);
2242                 }
2243                 for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
2244                         kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
2245                         usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
2246                         usb_kill_urb(usbduxsub_tmp->urbIn[i]);
2247                         usb_free_urb(usbduxsub_tmp->urbIn[i]);
2248                         usbduxsub_tmp->urbIn[i] = NULL;
2249                 }
2250                 kfree(usbduxsub_tmp->urbIn);
2251                 usbduxsub_tmp->urbIn = NULL;
2252         }
2253         if (usbduxsub_tmp->urbOut) {
2254                 if (usbduxsub_tmp->ao_cmd_running) {
2255                         usbduxsub_tmp->ao_cmd_running = 0;
2256                         usbduxsub_unlink_OutURBs(usbduxsub_tmp);
2257                 }
2258                 for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
2259                         kfree(usbduxsub_tmp->urbOut[i]->transfer_buffer);
2260                         usbduxsub_tmp->urbOut[i]->transfer_buffer = NULL;
2261                         if (usbduxsub_tmp->urbOut[i]) {
2262                                 usb_kill_urb(usbduxsub_tmp->urbOut[i]);
2263                                 usb_free_urb(usbduxsub_tmp->urbOut[i]);
2264                                 usbduxsub_tmp->urbOut[i] = NULL;
2265                         }
2266                 }
2267                 kfree(usbduxsub_tmp->urbOut);
2268                 usbduxsub_tmp->urbOut = NULL;
2269         }
2270         if (usbduxsub_tmp->urbPwm) {
2271                 if (usbduxsub_tmp->pwm_cmd_running) {
2272                         usbduxsub_tmp->pwm_cmd_running = 0;
2273                         usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
2274                 }
2275                 kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
2276                 usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
2277                 usb_kill_urb(usbduxsub_tmp->urbPwm);
2278                 usb_free_urb(usbduxsub_tmp->urbPwm);
2279                 usbduxsub_tmp->urbPwm = NULL;
2280         }
2281         kfree(usbduxsub_tmp->inBuffer);
2282         usbduxsub_tmp->inBuffer = NULL;
2283         kfree(usbduxsub_tmp->insnBuffer);
2284         usbduxsub_tmp->insnBuffer = NULL;
2285         kfree(usbduxsub_tmp->outBuffer);
2286         usbduxsub_tmp->outBuffer = NULL;
2287         kfree(usbduxsub_tmp->dac_commands);
2288         usbduxsub_tmp->dac_commands = NULL;
2289         kfree(usbduxsub_tmp->dux_commands);
2290         usbduxsub_tmp->dux_commands = NULL;
2291         usbduxsub_tmp->ai_cmd_running = 0;
2292         usbduxsub_tmp->ao_cmd_running = 0;
2293         usbduxsub_tmp->pwm_cmd_running = 0;
2294 }
2295
2296 /* common part of attach and attach_usb */
2297 static int usbdux_attach_common(struct comedi_device *dev,
2298                                 struct usbduxsub *udev,
2299                                 void *aux_data, int aux_len)
2300 {
2301         int ret;
2302         struct comedi_subdevice *s = NULL;
2303         int n_subdevs;
2304
2305         down(&udev->sem);
2306         /* pointer back to the corresponding comedi device */
2307         udev->comedidev = dev;
2308
2309         /* trying to upload the firmware into the chip */
2310         if (aux_data)
2311                 firmwareUpload(udev, aux_data, aux_len);
2312
2313         dev->board_name = "usbdux";
2314
2315         /* set number of subdevices */
2316         if (udev->high_speed) {
2317                 /* with pwm */
2318                 n_subdevs = 5;
2319         } else {
2320                 /* without pwm */
2321                 n_subdevs = 4;
2322         }
2323
2324         ret = comedi_alloc_subdevices(dev, n_subdevs);
2325         if (ret) {
2326                 up(&udev->sem);
2327                 return ret;
2328         }
2329
2330         /* private structure is also simply the usb-structure */
2331         dev->private = udev;
2332
2333         /* the first subdevice is the A/D converter */
2334         s = dev->subdevices + SUBDEV_AD;
2335         /* the URBs get the comedi subdevice */
2336         /* which is responsible for reading */
2337         /* this is the subdevice which reads data */
2338         dev->read_subdev = s;
2339         /* the subdevice receives as private structure the */
2340         /* usb-structure */
2341         s->private = NULL;
2342         /* analog input */
2343         s->type = COMEDI_SUBD_AI;
2344         /* readable and ref is to ground */
2345         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
2346         /* 8 channels */
2347         s->n_chan = 8;
2348         /* length of the channellist */
2349         s->len_chanlist = 8;
2350         /* callback functions */
2351         s->insn_read = usbdux_ai_insn_read;
2352         s->do_cmdtest = usbdux_ai_cmdtest;
2353         s->do_cmd = usbdux_ai_cmd;
2354         s->cancel = usbdux_ai_cancel;
2355         /* max value from the A/D converter (12bit) */
2356         s->maxdata = 0xfff;
2357         /* range table to convert to physical units */
2358         s->range_table = (&range_usbdux_ai_range);
2359
2360         /* analog out */
2361         s = dev->subdevices + SUBDEV_DA;
2362         /* analog out */
2363         s->type = COMEDI_SUBD_AO;
2364         /* backward pointer */
2365         dev->write_subdev = s;
2366         /* the subdevice receives as private structure the */
2367         /* usb-structure */
2368         s->private = NULL;
2369         /* are writable */
2370         s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
2371         /* 4 channels */
2372         s->n_chan = 4;
2373         /* length of the channellist */
2374         s->len_chanlist = 4;
2375         /* 12 bit resolution */
2376         s->maxdata = 0x0fff;
2377         /* bipolar range */
2378         s->range_table = (&range_usbdux_ao_range);
2379         /* callback */
2380         s->do_cmdtest = usbdux_ao_cmdtest;
2381         s->do_cmd = usbdux_ao_cmd;
2382         s->cancel = usbdux_ao_cancel;
2383         s->insn_read = usbdux_ao_insn_read;
2384         s->insn_write = usbdux_ao_insn_write;
2385
2386         /* digital I/O */
2387         s = dev->subdevices + SUBDEV_DIO;
2388         s->type = COMEDI_SUBD_DIO;
2389         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2390         s->n_chan = 8;
2391         s->maxdata = 1;
2392         s->range_table = (&range_digital);
2393         s->insn_bits = usbdux_dio_insn_bits;
2394         s->insn_config = usbdux_dio_insn_config;
2395         /* we don't use it */
2396         s->private = NULL;
2397
2398         /* counter */
2399         s = dev->subdevices + SUBDEV_COUNTER;
2400         s->type = COMEDI_SUBD_COUNTER;
2401         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2402         s->n_chan = 4;
2403         s->maxdata = 0xFFFF;
2404         s->insn_read = usbdux_counter_read;
2405         s->insn_write = usbdux_counter_write;
2406         s->insn_config = usbdux_counter_config;
2407
2408         if (udev->high_speed) {
2409                 /* timer / pwm */
2410                 s = dev->subdevices + SUBDEV_PWM;
2411                 s->type = COMEDI_SUBD_PWM;
2412                 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
2413                 s->n_chan = 8;
2414                 /* this defines the max duty cycle resolution */
2415                 s->maxdata = udev->sizePwmBuf;
2416                 s->insn_write = usbdux_pwm_write;
2417                 s->insn_read = usbdux_pwm_read;
2418                 s->insn_config = usbdux_pwm_config;
2419                 usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
2420         }
2421         /* finally decide that it's attached */
2422         udev->attached = 1;
2423
2424         up(&udev->sem);
2425
2426         dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
2427                  dev->minor);
2428
2429         return 0;
2430 }
2431
2432 /* is called when comedi-config is called */
2433 static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2434 {
2435         int ret;
2436         int index;
2437         int i;
2438         void *aux_data;
2439         int aux_len;
2440
2441         dev->private = NULL;
2442
2443         aux_data = comedi_aux_data(it->options, 0);
2444         aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
2445         if (aux_data == NULL)
2446                 aux_len = 0;
2447         else if (aux_len == 0)
2448                 aux_data = NULL;
2449
2450         down(&start_stop_sem);
2451         /* find a valid device which has been detected by the probe function of
2452          * the usb */
2453         index = -1;
2454         for (i = 0; i < NUMUSBDUX; i++) {
2455                 if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
2456                         index = i;
2457                         break;
2458                 }
2459         }
2460
2461         if (index < 0) {
2462                 printk(KERN_ERR
2463                        "comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n",
2464                        dev->minor);
2465                 ret = -ENODEV;
2466         } else
2467                 ret = usbdux_attach_common(dev, &usbduxsub[index],
2468                                            aux_data, aux_len);
2469         up(&start_stop_sem);
2470         return ret;
2471 }
2472
2473 /* is called from comedi_usb_auto_config() */
2474 static int usbdux_attach_usb(struct comedi_device *dev,
2475                              struct usb_interface *uinterf)
2476 {
2477         int ret;
2478         struct usbduxsub *this_usbduxsub;
2479
2480         dev->private = NULL;
2481
2482         down(&start_stop_sem);
2483         this_usbduxsub = usb_get_intfdata(uinterf);
2484         if (!this_usbduxsub || !this_usbduxsub->probed) {
2485                 printk(KERN_ERR
2486                        "comedi%d: usbdux: error: attach_usb failed, not connected\n",
2487                        dev->minor);
2488                 ret = -ENODEV;
2489         } else if (this_usbduxsub->attached) {
2490                 printk(KERN_ERR
2491                        "comedi%d: usbdux: error: attach_usb failed, already attached\n",
2492                        dev->minor);
2493                 ret = -ENODEV;
2494         } else
2495                 ret = usbdux_attach_common(dev, this_usbduxsub, NULL, 0);
2496         up(&start_stop_sem);
2497         return ret;
2498 }
2499
2500 static void usbdux_detach(struct comedi_device *dev)
2501 {
2502         struct usbduxsub *usb = dev->private;
2503
2504         if (usb) {
2505                 down(&usb->sem);
2506                 dev->private = NULL;
2507                 usb->attached = 0;
2508                 usb->comedidev = NULL;
2509                 up(&usb->sem);
2510         }
2511 }
2512
2513 static struct comedi_driver usbdux_driver = {
2514         .driver_name    = "usbdux",
2515         .module         = THIS_MODULE,
2516         .attach         = usbdux_attach,
2517         .detach         = usbdux_detach,
2518         .attach_usb     = usbdux_attach_usb,
2519 };
2520
2521 static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
2522                                                      void *context)
2523 {
2524         struct usbduxsub *usbduxsub_tmp = context;
2525         struct usb_interface *uinterf = usbduxsub_tmp->interface;
2526         int ret;
2527
2528         if (fw == NULL) {
2529                 dev_err(&uinterf->dev,
2530                         "Firmware complete handler without firmware!\n");
2531                 return;
2532         }
2533
2534         /*
2535          * we need to upload the firmware here because fw will be
2536          * freed once we've left this function
2537          */
2538         ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
2539
2540         if (ret) {
2541                 dev_err(&uinterf->dev,
2542                         "Could not upload firmware (err=%d)\n", ret);
2543                 goto out;
2544         }
2545         comedi_usb_auto_config(uinterf, &usbdux_driver);
2546  out:
2547         release_firmware(fw);
2548 }
2549
2550 static int usbdux_usb_probe(struct usb_interface *uinterf,
2551                             const struct usb_device_id *id)
2552 {
2553         struct usb_device *udev = interface_to_usbdev(uinterf);
2554         struct device *dev = &uinterf->dev;
2555         int i;
2556         int index;
2557         int ret;
2558
2559         dev_dbg(dev, "comedi_: usbdux_: "
2560                 "finding a free structure for the usb-device\n");
2561
2562         down(&start_stop_sem);
2563         /* look for a free place in the usbdux array */
2564         index = -1;
2565         for (i = 0; i < NUMUSBDUX; i++) {
2566                 if (!(usbduxsub[i].probed)) {
2567                         index = i;
2568                         break;
2569                 }
2570         }
2571
2572         /* no more space */
2573         if (index == -1) {
2574                 dev_err(dev, "Too many usbdux-devices connected.\n");
2575                 up(&start_stop_sem);
2576                 return -EMFILE;
2577         }
2578         dev_dbg(dev, "comedi_: usbdux: "
2579                 "usbduxsub[%d] is ready to connect to comedi.\n", index);
2580
2581         sema_init(&(usbduxsub[index].sem), 1);
2582         /* save a pointer to the usb device */
2583         usbduxsub[index].usbdev = udev;
2584
2585         /* 2.6: save the interface itself */
2586         usbduxsub[index].interface = uinterf;
2587         /* get the interface number from the interface */
2588         usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
2589         /* hand the private data over to the usb subsystem */
2590         /* will be needed for disconnect */
2591         usb_set_intfdata(uinterf, &(usbduxsub[index]));
2592
2593         dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
2594
2595         /* test if it is high speed (USB 2.0) */
2596         usbduxsub[index].high_speed =
2597             (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
2598
2599         /* create space for the commands of the DA converter */
2600         usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
2601         if (!usbduxsub[index].dac_commands) {
2602                 dev_err(dev, "comedi_: usbdux: "
2603                         "error alloc space for dac commands\n");
2604                 tidy_up(&(usbduxsub[index]));
2605                 up(&start_stop_sem);
2606                 return -ENOMEM;
2607         }
2608         /* create space for the commands going to the usb device */
2609         usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
2610         if (!usbduxsub[index].dux_commands) {
2611                 dev_err(dev, "comedi_: usbdux: "
2612                         "error alloc space for dux commands\n");
2613                 tidy_up(&(usbduxsub[index]));
2614                 up(&start_stop_sem);
2615                 return -ENOMEM;
2616         }
2617         /* create space for the in buffer and set it to zero */
2618         usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
2619         if (!(usbduxsub[index].inBuffer)) {
2620                 dev_err(dev, "comedi_: usbdux: "
2621                         "could not alloc space for inBuffer\n");
2622                 tidy_up(&(usbduxsub[index]));
2623                 up(&start_stop_sem);
2624                 return -ENOMEM;
2625         }
2626         /* create space of the instruction buffer */
2627         usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
2628         if (!(usbduxsub[index].insnBuffer)) {
2629                 dev_err(dev, "comedi_: usbdux: "
2630                         "could not alloc space for insnBuffer\n");
2631                 tidy_up(&(usbduxsub[index]));
2632                 up(&start_stop_sem);
2633                 return -ENOMEM;
2634         }
2635         /* create space for the outbuffer */
2636         usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
2637         if (!(usbduxsub[index].outBuffer)) {
2638                 dev_err(dev, "comedi_: usbdux: "
2639                         "could not alloc space for outBuffer\n");
2640                 tidy_up(&(usbduxsub[index]));
2641                 up(&start_stop_sem);
2642                 return -ENOMEM;
2643         }
2644         /* setting to alternate setting 3: enabling iso ep and bulk ep. */
2645         i = usb_set_interface(usbduxsub[index].usbdev,
2646                               usbduxsub[index].ifnum, 3);
2647         if (i < 0) {
2648                 dev_err(dev, "comedi_: usbdux%d: "
2649                         "could not set alternate setting 3 in high speed.\n",
2650                         index);
2651                 tidy_up(&(usbduxsub[index]));
2652                 up(&start_stop_sem);
2653                 return -ENODEV;
2654         }
2655         if (usbduxsub[index].high_speed)
2656                 usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
2657         else
2658                 usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
2659
2660         usbduxsub[index].urbIn =
2661             kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
2662                     GFP_KERNEL);
2663         if (!(usbduxsub[index].urbIn)) {
2664                 dev_err(dev, "comedi_: usbdux: Could not alloc. urbIn array\n");
2665                 tidy_up(&(usbduxsub[index]));
2666                 up(&start_stop_sem);
2667                 return -ENOMEM;
2668         }
2669         for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
2670                 /* one frame: 1ms */
2671                 usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
2672                 if (usbduxsub[index].urbIn[i] == NULL) {
2673                         dev_err(dev, "comedi_: usbdux%d: "
2674                                 "Could not alloc. urb(%d)\n", index, i);
2675                         tidy_up(&(usbduxsub[index]));
2676                         up(&start_stop_sem);
2677                         return -ENOMEM;
2678                 }
2679                 usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
2680                 /* will be filled later with a pointer to the comedi-device */
2681                 /* and ONLY then the urb should be submitted */
2682                 usbduxsub[index].urbIn[i]->context = NULL;
2683                 usbduxsub[index].urbIn[i]->pipe =
2684                     usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
2685                 usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
2686                 usbduxsub[index].urbIn[i]->transfer_buffer =
2687                     kzalloc(SIZEINBUF, GFP_KERNEL);
2688                 if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
2689                         dev_err(dev, "comedi_: usbdux%d: "
2690                                 "could not alloc. transb.\n", index);
2691                         tidy_up(&(usbduxsub[index]));
2692                         up(&start_stop_sem);
2693                         return -ENOMEM;
2694                 }
2695                 usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
2696                 usbduxsub[index].urbIn[i]->number_of_packets = 1;
2697                 usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
2698                 usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
2699                 usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF;
2700         }
2701
2702         /* out */
2703         if (usbduxsub[index].high_speed)
2704                 usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
2705         else
2706                 usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
2707
2708         usbduxsub[index].urbOut =
2709             kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
2710                     GFP_KERNEL);
2711         if (!(usbduxsub[index].urbOut)) {
2712                 dev_err(dev, "comedi_: usbdux: "
2713                         "Could not alloc. urbOut array\n");
2714                 tidy_up(&(usbduxsub[index]));
2715                 up(&start_stop_sem);
2716                 return -ENOMEM;
2717         }
2718         for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
2719                 /* one frame: 1ms */
2720                 usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
2721                 if (usbduxsub[index].urbOut[i] == NULL) {
2722                         dev_err(dev, "comedi_: usbdux%d: "
2723                                 "Could not alloc. urb(%d)\n", index, i);
2724                         tidy_up(&(usbduxsub[index]));
2725                         up(&start_stop_sem);
2726                         return -ENOMEM;
2727                 }
2728                 usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
2729                 /* will be filled later with a pointer to the comedi-device */
2730                 /* and ONLY then the urb should be submitted */
2731                 usbduxsub[index].urbOut[i]->context = NULL;
2732                 usbduxsub[index].urbOut[i]->pipe =
2733                     usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
2734                 usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
2735                 usbduxsub[index].urbOut[i]->transfer_buffer =
2736                     kzalloc(SIZEOUTBUF, GFP_KERNEL);
2737                 if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
2738                         dev_err(dev, "comedi_: usbdux%d: "
2739                                 "could not alloc. transb.\n", index);
2740                         tidy_up(&(usbduxsub[index]));
2741                         up(&start_stop_sem);
2742                         return -ENOMEM;
2743                 }
2744                 usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
2745                 usbduxsub[index].urbOut[i]->number_of_packets = 1;
2746                 usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF;
2747                 usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
2748                 usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
2749                     SIZEOUTBUF;
2750                 if (usbduxsub[index].high_speed) {
2751                         /* uframes */
2752                         usbduxsub[index].urbOut[i]->interval = 8;
2753                 } else {
2754                         /* frames */
2755                         usbduxsub[index].urbOut[i]->interval = 1;
2756                 }
2757         }
2758
2759         /* pwm */
2760         if (usbduxsub[index].high_speed) {
2761                 /* max bulk ep size in high speed */
2762                 usbduxsub[index].sizePwmBuf = 512;
2763                 usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
2764                 if (usbduxsub[index].urbPwm == NULL) {
2765                         dev_err(dev, "comedi_: usbdux%d: "
2766                                 "Could not alloc. pwm urb\n", index);
2767                         tidy_up(&(usbduxsub[index]));
2768                         up(&start_stop_sem);
2769                         return -ENOMEM;
2770                 }
2771                 usbduxsub[index].urbPwm->transfer_buffer =
2772                     kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
2773                 if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
2774                         dev_err(dev, "comedi_: usbdux%d: "
2775                                 "could not alloc. transb. for pwm\n", index);
2776                         tidy_up(&(usbduxsub[index]));
2777                         up(&start_stop_sem);
2778                         return -ENOMEM;
2779                 }
2780         } else {
2781                 usbduxsub[index].urbPwm = NULL;
2782                 usbduxsub[index].sizePwmBuf = 0;
2783         }
2784
2785         usbduxsub[index].ai_cmd_running = 0;
2786         usbduxsub[index].ao_cmd_running = 0;
2787         usbduxsub[index].pwm_cmd_running = 0;
2788
2789         /* we've reached the bottom of the function */
2790         usbduxsub[index].probed = 1;
2791         up(&start_stop_sem);
2792
2793         ret = request_firmware_nowait(THIS_MODULE,
2794                                       FW_ACTION_HOTPLUG,
2795                                       FIRMWARE,
2796                                       &udev->dev,
2797                                       GFP_KERNEL,
2798                                       usbduxsub + index,
2799                                       usbdux_firmware_request_complete_handler);
2800
2801         if (ret) {
2802                 dev_err(dev, "Could not load firmware (err=%d)\n", ret);
2803                 return ret;
2804         }
2805
2806         dev_info(dev, "comedi_: usbdux%d "
2807                  "has been successfully initialised.\n", index);
2808         /* success */
2809         return 0;
2810 }
2811
2812 static void usbdux_usb_disconnect(struct usb_interface *intf)
2813 {
2814         struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
2815         struct usb_device *udev = interface_to_usbdev(intf);
2816
2817         if (!usbduxsub_tmp) {
2818                 dev_err(&intf->dev,
2819                         "comedi_: disconnect called with null pointer.\n");
2820                 return;
2821         }
2822         if (usbduxsub_tmp->usbdev != udev) {
2823                 dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n");
2824                 return;
2825         }
2826         comedi_usb_auto_unconfig(intf);
2827         down(&start_stop_sem);
2828         down(&usbduxsub_tmp->sem);
2829         tidy_up(usbduxsub_tmp);
2830         up(&usbduxsub_tmp->sem);
2831         up(&start_stop_sem);
2832         dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
2833 }
2834
2835 static const struct usb_device_id usbdux_usb_table[] = {
2836         { USB_DEVICE(0x13d8, 0x0001) },
2837         { USB_DEVICE(0x13d8, 0x0002) },
2838         { }
2839 };
2840
2841 MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
2842
2843 static struct usb_driver usbdux_usb_driver = {
2844         .name           = "usbdux",
2845         .probe          = usbdux_usb_probe,
2846         .disconnect     = usbdux_usb_disconnect,
2847         .id_table       = usbdux_usb_table,
2848 };
2849 module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
2850
2851 MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
2852 MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");
2853 MODULE_LICENSE("GPL");
2854 MODULE_FIRMWARE(FIRMWARE);