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