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