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