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