usbdux*: fix DMA buffers on stack
[comedi.git] / comedi / drivers / usbduxfast.c
1 #define DRIVER_VERSION "v1.0"
2 #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
3 #define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com"
4 /*
5    comedi/drivers/usbduxfast.c
6    Copyright (C) 2004 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: usbduxfast
25 Description: Driver for USB-DUX-FAST of INCITE Technology Limited
26 Devices: [ITL] USB-DUX-FAST (usbduxfast)
27 Author: Bernd Porr <tech@linux-usb-daq.co.uk>
28 Updated: 14 May 2012
29 Status: stable
30
31 The device has one subdevice for analogue input.
32   - subdevice: 0
33     number of channels: 16
34     max data value: 4096
35     ranges:
36       all channelss: 
37         range = 0 : [-0.75 V,0.75 V] 
38         range = 1 : [-0.5 V,0.5 V]
39     command:
40       The channel-list allows 1,2,3 and 16 channels.
41       start: now|ext|int (external trigger via pin at HD-D connector)
42       scan_begin: follow|timer|ext
43       convert: timer|ext (contains the sampling interval. Min interval
44                           for single channel acquisition is 33us 
45                           and for multiplexed acquisition 300us)
46       scan_end: count
47       stop: none|count
48
49 Configuration options:
50   The device requires firmware which is usually
51   uploaded automatically by udev/hotplug at the moment
52   the driver module is being loaded.
53   In case udev/hotplug is not enabled you need to upload 
54   the firmware with comedi_config -i usbduxfast_firmware.bin
55   The firmware is usually installed under /lib/firmware
56   or can be downloaded form http://www.linux-usb-daq.co.uk.
57 */
58
59 /*
60  * I must give credit here to Chris Baugher who
61  * wrote the driver for AT-MIO-16d. I used some parts of this
62  * driver. I also must give credits to David Brownell
63  * who supported me with the USB development.
64  *
65  * Bernd Porr
66  *
67  *
68  * Revision history:
69  * 0.9: Dropping the first data packet which seems to be from the last transfer.
70  *      Buffer overflows in the FX2 are handed over to comedi.
71  * 0.92: Dropping now 4 packets. The quad buffer has to be emptied.
72  *       Added insn command basically for testing. Sample rate is 1MHz/16ch=62.5kHz
73  * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
74  * 0.99a: added external trigger.
75  * 1.00: added firmware kernel request to the driver which fixed
76  *       udev coldplug problem
77  */
78
79 #include <linux/kernel.h>
80 #include <linux/firmware.h>
81 #include <linux/module.h>
82 #include <linux/init.h>
83 #include <linux/slab.h>
84 #include <linux/input.h>
85 #include <linux/usb.h>
86 #include <linux/fcntl.h>
87 #include <linux/compiler.h>
88 #include "comedi_fc.h"
89 #include <linux/comedidev.h>
90 #include <linux/usb.h>
91
92 // (un)comment this if you want to have debug info.
93 //#define CONFIG_COMEDI_DEBUG
94 #undef  CONFIG_COMEDI_DEBUG
95
96 #define BOARDNAME "usbduxfast"
97
98 // timeout for the USB-transfer
99 #define BULK_TIMEOUT 1000
100
101 // constants for "firmware" upload and download
102 #define USBDUXFASTSUB_FIRMWARE 0xA0
103 #define VENDOR_DIR_IN  0xC0
104 #define VENDOR_DIR_OUT 0x40
105
106 // internal adresses of the 8051 processor
107 #define USBDUXFASTSUB_CPUCS 0xE600
108
109 // max lenghth of the transfer-buffer for software upload
110 #define TB_LEN 0x2000
111
112 // Input endpoint number
113 #define BULKINEP           6
114
115 // Endpoint for the A/D channellist: bulk OUT
116 #define CHANNELLISTEP     4
117
118 // Number of channels
119 #define NUMCHANNELS       32
120
121 // size of the waveform descriptor
122 #define WAVESIZE          0x20
123
124 // Size of one A/D value
125 #define SIZEADIN          ((sizeof(int16_t)))
126
127 // Size of the input-buffer IN BYTES
128 #define SIZEINBUF         512
129
130 // 16 bytes.
131 #define SIZEINSNBUF       512
132
133 // Size of the buffer for the dux commands
134 #define SIZEOFDUXBUFFER    256  // bytes
135
136 // Number of in-URBs which receive the data: min=5
137 #define NUMOFINBUFFERSHIGH     10
138
139 // Total number of usbduxfast devices
140 #define NUMUSBDUXFAST             16
141
142 // Number of subdevices
143 #define N_SUBDEVICES          1
144
145 // Analogue in subdevice
146 #define SUBDEV_AD             0
147
148 // min delay steps for more than one channel
149 // basically when the mux gives up. ;-)
150 #define MIN_SAMPLING_PERIOD 9   // steps at 30MHz in the FX2
151
152 // Max number of 1/30MHz delay steps:
153 #define MAX_SAMPLING_PERIOD 500
154
155 // Number of received packets to ignore before we start handing data over to comedi.
156 // It's quad buffering and we have to ignore 4 packets.
157 #define PACKETS_TO_IGNORE 4
158
159 /////////////////////////////////////////////
160 // comedi constants
161 static const comedi_lrange range_usbduxfast_ai_range = { 2, {
162                         BIP_RANGE(0.75),
163                         BIP_RANGE(0.5),
164         }
165 };
166
167 /*
168  * private structure of one subdevice
169  */
170
171 // This is the structure which holds all the data of this driver
172 // one sub device just now: A/D
173 typedef struct {
174         // attached?
175         int attached;
176         // is it associated with a subdevice?
177         int probed;
178         // pointer to the usb-device
179         struct usb_device *usbdev;
180         // BULK-transfer handling: urb
181         struct urb *urbIn;
182         int8_t *transfer_buffer;
183         // input buffer for single insn
184         int16_t *insnBuffer;
185         // interface number
186         int ifnum;
187 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
188         // interface structure in 2.6
189         struct usb_interface *interface;
190 #endif
191         // comedi device for the interrupt context
192         comedi_device *comedidev;
193         // asynchronous command is running
194         short int ai_cmd_running;
195         // continous aquisition
196         short int ai_continous;
197         // number of samples to aquire
198         long int ai_sample_count;
199         // commands
200         uint8_t *dux_commands;
201         // counter which ignores the first buffers
202         int ignore;
203         struct mutex mutex;
204 } usbduxfastsub_t;
205
206 // The pointer to the private usb-data of the driver
207 // is also the private data for the comedi-device.
208 // This has to be global as the usb subsystem needs
209 // global variables. The other reason is that this
210 // structure must be there _before_ any comedi
211 // command is issued. The usb subsystem must be
212 // initialised before comedi can access it.
213 static usbduxfastsub_t usbduxfastsub[NUMUSBDUXFAST];
214
215 static DEFINE_MUTEX(start_stop_mutex);
216
217 // bulk transfers to usbduxfast
218
219 #define SENDADCOMMANDS            0
220 #define SENDINITEP6               1
221
222 static int send_dux_commands(usbduxfastsub_t * this_usbduxfastsub, int cmd_type)
223 {
224         int result, nsent;
225         this_usbduxfastsub->dux_commands[0] = cmd_type;
226 #ifdef CONFIG_COMEDI_DEBUG
227         int i;
228         printk("comedi%d: usbduxfast: dux_commands: ",
229                 this_usbduxfastsub->comedidev->minor);
230         for (i = 0; i < SIZEOFDUXBUFFER; i++) {
231                 printk(" %02x", this_usbduxfastsub->dux_commands[i]);
232         }
233         printk("\n");
234 #endif
235         result = USB_BULK_MSG(this_usbduxfastsub->usbdev,
236                 usb_sndbulkpipe(this_usbduxfastsub->usbdev,
237                         CHANNELLISTEP),
238                 this_usbduxfastsub->dux_commands,
239                 SIZEOFDUXBUFFER, &nsent, BULK_TIMEOUT);
240         if (result < 0) {
241                 printk("comedi%d: could not transmit dux_commands to the usb-device, err=%d\n", this_usbduxfastsub->comedidev->minor, result);
242         }
243         return result;
244 }
245
246 // Stops the data acquision
247 // It should be safe to call this function from any context
248 static int usbduxfastsub_unlink_InURBs(usbduxfastsub_t * usbduxfastsub_tmp)
249 {
250         int j = 0;
251         int err = 0;
252
253         if (usbduxfastsub_tmp && usbduxfastsub_tmp->urbIn) {
254                 usbduxfastsub_tmp->ai_cmd_running = 0;
255 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
256                 j = usb_unlink_urb(usbduxfastsub_tmp->urbIn);
257                 if (j < 0) {
258                         err = j;
259                 }
260 #else
261                 // waits until a running transfer is over
262                 usb_kill_urb(usbduxfastsub_tmp->urbIn);
263                 j = 0;
264 #endif
265         }
266 #ifdef CONFIG_COMEDI_DEBUG
267         printk("comedi: usbduxfast: unlinked InURB: res=%d\n", j);
268 #endif
269         return err;
270 }
271
272 /* This will stop a running acquisition operation */
273 // Is called from within this driver from both the
274 // interrupt context and from comedi
275 static int usbduxfast_ai_stop(usbduxfastsub_t * this_usbduxfastsub,
276         int do_unlink)
277 {
278         int ret = 0;
279
280         if (!this_usbduxfastsub) {
281                 printk("comedi?: usbduxfast_ai_stop: this_usbduxfastsub=NULL!\n");
282                 return -EFAULT;
283         }
284 #ifdef CONFIG_COMEDI_DEBUG
285         printk("comedi: usbduxfast_ai_stop\n");
286 #endif
287
288         this_usbduxfastsub->ai_cmd_running = 0;
289
290         if (do_unlink) {
291                 // stop aquistion
292                 ret = usbduxfastsub_unlink_InURBs(this_usbduxfastsub);
293         }
294
295         return ret;
296 }
297
298 // This will cancel a running acquisition operation.
299 // This is called by comedi but never from inside the
300 // driver.
301 static int usbduxfast_ai_cancel(comedi_device * dev, comedi_subdevice * s)
302 {
303         usbduxfastsub_t *this_usbduxfastsub;
304         int res = 0;
305
306         // force unlink of all urbs
307 #ifdef CONFIG_COMEDI_DEBUG
308         printk("comedi: usbduxfast_ai_cancel\n");
309 #endif
310         this_usbduxfastsub = dev->private;
311         if (!this_usbduxfastsub) {
312                 printk("comedi: usbduxfast_ai_cancel: this_usbduxfastsub=NULL\n");
313                 return -EFAULT;
314         }
315         mutex_lock(&this_usbduxfastsub->mutex);
316         if (!(this_usbduxfastsub->probed)) {
317                 mutex_unlock(&this_usbduxfastsub->mutex);
318                 return -ENODEV;
319         }
320         // unlink
321         res = usbduxfast_ai_stop(this_usbduxfastsub, 1);
322         mutex_unlock(&this_usbduxfastsub->mutex);
323
324         return res;
325 }
326
327 // analogue IN
328 // interrupt service routine
329 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
330 static void usbduxfastsub_ai_Irq(struct urb *urb)
331 #else
332 static void usbduxfastsub_ai_Irq(struct urb *urb PT_REGS_ARG)
333 #endif
334 {
335         int n, err;
336         usbduxfastsub_t *this_usbduxfastsub;
337         comedi_device *this_comedidev;
338         comedi_subdevice *s;
339         uint16_t *p;
340
341         // sanity checks
342         // is the urb there?
343         if (!urb) {
344                 printk("comedi_: usbduxfast_: ao int-handler called with urb=NULL!\n");
345                 return;
346         }
347         // the context variable points to the subdevice
348         this_comedidev = urb->context;
349         if (!this_comedidev) {
350                 printk("comedi_: usbduxfast_: urb context is a NULL pointer!\n");
351                 return;
352         }
353         // the private structure of the subdevice is usbduxfastsub_t
354         this_usbduxfastsub = this_comedidev->private;
355         if (!this_usbduxfastsub) {
356                 printk("comedi_: usbduxfast_: private of comedi subdev is a NULL pointer!\n");
357                 return;
358         }
359         // are we running a command?
360         if (unlikely(!(this_usbduxfastsub->ai_cmd_running))) {
361                 // not running a command
362                 // do not continue execution if no asynchronous command is running
363                 // in particular not resubmit
364                 return;
365         }
366
367         if (unlikely(!(this_usbduxfastsub->attached))) {
368                 // no comedi device there
369                 return;
370         }
371         // subdevice which is the AD converter
372         s = this_comedidev->subdevices + SUBDEV_AD;
373
374         // first we test if something unusual has just happened
375         switch (urb->status) {
376         case 0:
377                 break;
378
379                 // happens after an unlink command or when the device is plugged out
380         case -ECONNRESET:
381         case -ENOENT:
382         case -ESHUTDOWN:
383         case -ECONNABORTED:
384                 // tell this comedi
385                 s->async->events |= COMEDI_CB_EOA;
386                 s->async->events |= COMEDI_CB_ERROR;
387                 comedi_event(this_usbduxfastsub->comedidev, s);
388                 // stop the transfer w/o unlink
389                 usbduxfast_ai_stop(this_usbduxfastsub, 0);
390                 return;
391
392         default:
393                 printk("comedi%d: usbduxfast: non-zero urb status received in ai intr context: %d\n", this_usbduxfastsub->comedidev->minor, urb->status);
394                 s->async->events |= COMEDI_CB_EOA;
395                 s->async->events |= COMEDI_CB_ERROR;
396                 comedi_event(this_usbduxfastsub->comedidev, s);
397                 usbduxfast_ai_stop(this_usbduxfastsub, 0);
398                 return;
399         }
400
401         p = urb->transfer_buffer;
402         if (!this_usbduxfastsub->ignore) {
403                 if (!(this_usbduxfastsub->ai_continous)) {
404                         // not continous, fixed number of samples
405                         n = urb->actual_length / sizeof(uint16_t);
406                         if (unlikely(this_usbduxfastsub->ai_sample_count < n)) {
407                                 // we have send only a fraction of the bytes received
408                                 cfc_write_array_to_buffer(s,
409                                         urb->transfer_buffer,
410                                         this_usbduxfastsub->ai_sample_count *
411                                         sizeof(uint16_t));
412                                 usbduxfast_ai_stop(this_usbduxfastsub, 0);
413                                 // say comedi that the acquistion is over
414                                 s->async->events |= COMEDI_CB_EOA;
415                                 comedi_event(this_usbduxfastsub->comedidev, s);
416                                 return;
417                         }
418                         this_usbduxfastsub->ai_sample_count -= n;
419                 }
420                 // write the full buffer to comedi
421                 err = cfc_write_array_to_buffer(s,
422                                                 urb->transfer_buffer, urb->actual_length);
423
424                 if (unlikely(err == 0)) {
425                         /* buffer overflow */
426                         usbduxfast_ai_stop(this_usbduxfastsub, 0);
427                         return;
428                 }
429
430                 // tell comedi that data is there
431                 comedi_event(this_usbduxfastsub->comedidev, s);
432
433         } else {
434                 // ignore this packet
435                 this_usbduxfastsub->ignore--;
436         }
437
438         // command is still running
439         // resubmit urb for BULK transfer
440         urb->dev = this_usbduxfastsub->usbdev;
441         urb->status = 0;
442         if ((err = USB_SUBMIT_URB(urb)) < 0) {
443                 printk("comedi%d: usbduxfast: urb resubm failed: %d",
444                         this_usbduxfastsub->comedidev->minor, err);
445                 s->async->events |= COMEDI_CB_EOA;
446                 s->async->events |= COMEDI_CB_ERROR;
447                 comedi_event(this_usbduxfastsub->comedidev, s);
448                 usbduxfast_ai_stop(this_usbduxfastsub, 0);
449         }
450 }
451
452 static int usbduxfastsub_start(usbduxfastsub_t * usbduxfastsub)
453 {
454         int errcode = 0;
455         unsigned char *local_transfer_buffer;
456
457         local_transfer_buffer = kmalloc(16, GFP_KERNEL);
458         if (!local_transfer_buffer)
459                 return -ENOMEM;
460
461         // 7f92 to zero
462         local_transfer_buffer[0] = 0;
463         errcode = USB_CONTROL_MSG(usbduxfastsub->usbdev,
464                                   // create a pipe for a control transfer
465                                   usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
466                                   // bRequest, "Firmware"
467                                   USBDUXFASTSUB_FIRMWARE,
468                                   // bmRequestType
469                                   VENDOR_DIR_OUT,
470                                   // Value
471                                   USBDUXFASTSUB_CPUCS,
472                                   // Index
473                                   0x0000,
474                                   // address of the transfer buffer
475                                   local_transfer_buffer,
476                                   // Length
477                                   1,
478                                   // Timeout
479                                   BULK_TIMEOUT);
480         if (errcode < 0)
481                 printk("comedi_: usbduxfast_: control msg failed (start)\n");
482
483         kfree(local_transfer_buffer);
484         return errcode;
485 }
486
487 static int usbduxfastsub_stop(usbduxfastsub_t * usbduxfastsub)
488 {
489         int errcode = 0;
490         unsigned char *local_transfer_buffer;
491
492         local_transfer_buffer = kmalloc(16, GFP_KERNEL);
493         if (!local_transfer_buffer)
494                 return -ENOMEM;
495
496         // 7f92 to one
497         local_transfer_buffer[0] = 1;
498         errcode = USB_CONTROL_MSG
499                 (usbduxfastsub->usbdev,
500                  usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
501                  // bRequest, "Firmware"
502                  USBDUXFASTSUB_FIRMWARE,
503                  // bmRequestType
504                  VENDOR_DIR_OUT,
505                  // Value
506                  USBDUXFASTSUB_CPUCS,
507                  // Index
508                  0x0000, local_transfer_buffer,
509                  // Length
510                  1,
511                  // Timeout
512                  BULK_TIMEOUT);
513         if (errcode < 0)
514                 printk("comedi_: usbduxfast: control msg failed (stop)\n");
515
516         kfree(local_transfer_buffer);
517         return errcode;
518 }
519
520 static int usbduxfastsub_upload(usbduxfastsub_t * usbduxfastsub,
521         unsigned char *local_transfer_buffer,
522         unsigned int startAddr, unsigned int len)
523 {
524         int errcode;
525
526         errcode = USB_CONTROL_MSG
527                 (usbduxfastsub->usbdev,
528                  usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
529                  // brequest, firmware
530                  USBDUXFASTSUB_FIRMWARE,
531                  // bmRequestType
532                  VENDOR_DIR_OUT,
533                  // value
534                  startAddr,
535                  // index
536                  0x0000,
537                  // our local safe buffer
538                  local_transfer_buffer,
539                  // length
540                  len,
541                  // timeout
542                  BULK_TIMEOUT);
543         if (errcode < 0) {
544                 printk("comedi_: usbduxfast: uppload failed\n");
545                 return errcode;
546         }
547         return 0;
548 }
549
550 int firmwareUpload(usbduxfastsub_t * usbduxfastsub,
551         unsigned char *firmwareBinary, int sizeFirmware)
552 {
553         int ret;
554
555         if (!firmwareBinary) {
556                 return 0;
557         }
558         ret = usbduxfastsub_stop(usbduxfastsub);
559         if (ret < 0) {
560                 printk("comedi_: usbduxfast: can not stop firmware\n");
561                 return ret;
562         }
563         ret = usbduxfastsub_upload(usbduxfastsub,
564                 firmwareBinary, 0, sizeFirmware);
565         if (ret < 0) {
566                 printk("comedi_: usbduxfast: firmware upload failed\n");
567                 return ret;
568         }
569         ret = usbduxfastsub_start(usbduxfastsub);
570         if (ret < 0) {
571                 printk("comedi_: usbduxfast: can not start firmware\n");
572                 return ret;
573         }
574         return 0;
575 }
576
577 int usbduxfastsub_submit_InURBs(usbduxfastsub_t * usbduxfastsub)
578 {
579         int errFlag;
580
581         if (!usbduxfastsub) {
582                 return -EFAULT;
583         }
584         usb_fill_bulk_urb(usbduxfastsub->urbIn,
585                 usbduxfastsub->usbdev,
586                 usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
587                 usbduxfastsub->transfer_buffer,
588                 SIZEINBUF, usbduxfastsub_ai_Irq, usbduxfastsub->comedidev);
589
590 #ifdef CONFIG_COMEDI_DEBUG
591         printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n",
592                 usbduxfastsub->comedidev->minor,
593                 (int)(usbduxfastsub->urbIn->context),
594                 (int)(usbduxfastsub->urbIn->dev));
595 #endif
596         errFlag = USB_SUBMIT_URB(usbduxfastsub->urbIn);
597         if (errFlag) {
598                 printk("comedi_: usbduxfast: ai: ");
599                 printk("USB_SUBMIT_URB");
600                 printk(" error %d\n", errFlag);
601                 return errFlag;
602         }
603         return 0;
604 }
605
606 static int usbduxfast_ai_cmdtest(comedi_device * dev,
607         comedi_subdevice * s, comedi_cmd * cmd)
608 {
609         int err = 0, stop_mask = 0;
610         long int steps, tmp = 0;
611         int minSamplPer;
612         usbduxfastsub_t *this_usbduxfastsub = dev->private;
613         if (!(this_usbduxfastsub->probed)) {
614                 return -ENODEV;
615         }
616 #ifdef CONFIG_COMEDI_DEBUG
617         printk("comedi%d: usbduxfast_ai_cmdtest\n", dev->minor);
618         printk("comedi%d: usbduxfast: convert_arg=%u scan_begin_arg=%u\n",
619                 dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
620 #endif
621         /* step 1: make sure trigger sources are trivially valid */
622
623         tmp = cmd->start_src;
624         cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
625         if (!cmd->start_src || tmp != cmd->start_src)
626                 err++;
627
628         tmp = cmd->scan_begin_src;
629         cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
630         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
631                 err++;
632
633         tmp = cmd->convert_src;
634         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
635         if (!cmd->convert_src || tmp != cmd->convert_src)
636                 err++;
637
638         tmp = cmd->scan_end_src;
639         cmd->scan_end_src &= TRIG_COUNT;
640         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
641                 err++;
642
643         tmp = cmd->stop_src;
644         stop_mask = TRIG_COUNT | TRIG_NONE;
645         cmd->stop_src &= stop_mask;
646         if (!cmd->stop_src || tmp != cmd->stop_src)
647                 err++;
648
649         if (err)
650                 return 1;
651
652         /* step 2: make sure trigger sources are unique and mutually compatible */
653
654         if (cmd->start_src != TRIG_NOW &&
655                 cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT)
656                 err++;
657         if (cmd->scan_begin_src != TRIG_TIMER &&
658                 cmd->scan_begin_src != TRIG_FOLLOW &&
659                 cmd->scan_begin_src != TRIG_EXT)
660                 err++;
661         if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
662                 err++;
663         if (cmd->stop_src != TRIG_COUNT &&
664                 cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
665                 err++;
666
667         // can't have external stop and start triggers at once
668         if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
669                 err++;
670
671         if (err)
672                 return 2;
673
674         /* step 3: make sure arguments are trivially compatible */
675
676         if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) {
677                 cmd->start_arg = 0;
678                 err++;
679         }
680
681         if (!cmd->chanlist_len) {
682                 err++;
683         }
684         if (cmd->scan_end_arg != cmd->chanlist_len) {
685                 cmd->scan_end_arg = cmd->chanlist_len;
686                 err++;
687         }
688
689         if (cmd->chanlist_len == 1) {
690                 minSamplPer = 1;
691         } else {
692                 minSamplPer = MIN_SAMPLING_PERIOD;
693         }
694
695         if (cmd->convert_src == TRIG_TIMER) {
696                 steps = cmd->convert_arg * 30;
697                 if (steps < (minSamplPer * 1000)) {
698                         steps = minSamplPer * 1000;
699                 }
700                 if (steps > (MAX_SAMPLING_PERIOD * 1000)) {
701                         steps = MAX_SAMPLING_PERIOD * 1000;
702                 }
703                 // calc arg again
704                 tmp = steps / 30;
705                 if (cmd->convert_arg != tmp) {
706                         cmd->convert_arg = tmp;
707                         err++;
708                 }
709         }
710
711         if (cmd->scan_begin_src == TRIG_TIMER) {
712                 err++;
713         }
714         // stop source
715         switch (cmd->stop_src) {
716         case TRIG_COUNT:
717                 if (!cmd->stop_arg) {
718                         cmd->stop_arg = 1;
719                         err++;
720                 }
721                 break;
722         case TRIG_NONE:
723                 if (cmd->stop_arg != 0) {
724                         cmd->stop_arg = 0;
725                         err++;
726                 }
727                 break;
728                 // TRIG_EXT doesn't care since it doesn't trigger off a numbered channel
729         default:
730                 break;
731         }
732
733         if (err)
734                 return 3;
735
736         /* step 4: fix up any arguments */
737
738         return 0;
739
740 }
741
742 static int usbduxfast_ai_inttrig(comedi_device * dev,
743         comedi_subdevice * s, unsigned int trignum)
744 {
745         int ret;
746         usbduxfastsub_t *this_usbduxfastsub = dev->private;
747         if (!this_usbduxfastsub) {
748                 return -EFAULT;
749         }
750         mutex_lock(&this_usbduxfastsub->mutex);
751         if (!(this_usbduxfastsub->probed)) {
752                 mutex_unlock(&this_usbduxfastsub->mutex);
753                 return -ENODEV;
754         }
755 #ifdef CONFIG_COMEDI_DEBUG
756         printk("comedi%d: usbduxfast_ai_inttrig\n", dev->minor);
757 #endif
758
759         if (trignum != 0) {
760                 printk("comedi%d: usbduxfast_ai_inttrig: invalid trignum\n",
761                         dev->minor);
762                 mutex_unlock(&this_usbduxfastsub->mutex);
763                 return -EINVAL;
764         }
765         if (!(this_usbduxfastsub->ai_cmd_running)) {
766                 this_usbduxfastsub->ai_cmd_running = 1;
767                 ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub);
768                 if (ret < 0) {
769                         printk("comedi%d: usbduxfast_ai_inttrig: urbSubmit: err=%d\n", dev->minor, ret);
770                         this_usbduxfastsub->ai_cmd_running = 0;
771                         mutex_unlock(&this_usbduxfastsub->mutex);
772                         return ret;
773                 }
774                 s->async->inttrig = NULL;
775         } else {
776                 printk("comedi%d: ai_inttrig but acqu is already running\n",
777                         dev->minor);
778         }
779         mutex_unlock(&this_usbduxfastsub->mutex);
780         return 1;
781 }
782
783 // offsets for the GPIF bytes
784 // the first byte is the command byte
785 #define LENBASE 1+0x00
786 #define OPBASE  1+0x08
787 #define OUTBASE 1+0x10
788 #define LOGBASE 1+0x18
789
790 static int usbduxfast_ai_cmd(comedi_device * dev, comedi_subdevice * s)
791 {
792         comedi_cmd *cmd = &s->async->cmd;
793         unsigned int chan, gain, rngmask = 0xff;
794         int i, j, ret;
795         usbduxfastsub_t *this_usbduxfastsub = dev->private;
796         int result;
797         long steps, steps_tmp;
798
799 #ifdef CONFIG_COMEDI_DEBUG
800         printk("comedi%d: usbduxfast_ai_cmd\n", dev->minor);
801 #endif
802         if (!this_usbduxfastsub) {
803                 return -EFAULT;
804         }
805         mutex_lock(&this_usbduxfastsub->mutex);
806         if (!(this_usbduxfastsub->probed)) {
807                 mutex_unlock(&this_usbduxfastsub->mutex);
808                 return -ENODEV;
809         }
810         if (this_usbduxfastsub->ai_cmd_running) {
811                 printk("comedi%d: ai_cmd not possible. Another ai_cmd is running.\n", dev->minor);
812                 mutex_unlock(&this_usbduxfastsub->mutex);
813                 return -EBUSY;
814         }
815         // set current channel of the running aquisition to zero
816         s->async->cur_chan = 0;
817
818         // ignore the first buffers from the device if there is an error condition
819         this_usbduxfastsub->ignore = PACKETS_TO_IGNORE;
820
821         if (cmd->chanlist_len > 0) {
822                 gain = CR_RANGE(cmd->chanlist[0]);
823                 for (i = 0; i < cmd->chanlist_len; ++i) {
824                         chan = CR_CHAN(cmd->chanlist[i]);
825                         if (chan != i) {
826                                 printk("comedi%d: cmd is accepting only consecutive channels.\n", dev->minor);
827                                 mutex_unlock(&this_usbduxfastsub->mutex);
828                                 return -EINVAL;
829                         }
830                         if ((gain != CR_RANGE(cmd->chanlist[i]))
831                                 && (cmd->chanlist_len > 3)) {
832                                 printk("comedi%d: the gain must be the same for all channels.\n", dev->minor);
833                                 mutex_unlock(&this_usbduxfastsub->mutex);
834                                 return -EINVAL;
835                         }
836                         if (i >= NUMCHANNELS) {
837                                 printk("comedi%d: channel list too long\n",
838                                         dev->minor);
839                                 break;
840                         }
841                 }
842         }
843         steps = 0;
844         if (cmd->scan_begin_src == TRIG_TIMER) {
845                 printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
846                 mutex_unlock(&this_usbduxfastsub->mutex);
847                 return -EINVAL;
848         }
849         if (cmd->convert_src == TRIG_TIMER) {
850                 steps = (cmd->convert_arg * 30) / 1000;
851         }
852         if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
853                 printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, steps, cmd->scan_begin_arg);
854                 mutex_unlock(&this_usbduxfastsub->mutex);
855                 return -EINVAL;
856         }
857         if (steps > MAX_SAMPLING_PERIOD) {
858                 printk("comedi%d: usbduxfast: ai_cmd: sampling rate too low.\n",
859                         dev->minor);
860                 mutex_unlock(&this_usbduxfastsub->mutex);
861                 return -EINVAL;
862         }
863         if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
864                 && (cmd->chanlist_len != 16)) {
865                 printk("comedi%d: usbduxfast: ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n", dev->minor);
866                 mutex_unlock(&this_usbduxfastsub->mutex);
867                 return -EINVAL;
868         }
869 #ifdef CONFIG_COMEDI_DEBUG
870         printk("comedi%d: usbduxfast: steps=%ld, convert_arg=%u, ai_timer=%u\n",
871                 dev->minor,
872                 steps, cmd->convert_arg, this_usbduxfastsub->ai_timer);
873 #endif
874
875         switch (cmd->chanlist_len) {
876                 // one channel
877         case 1:
878                 if (CR_RANGE(cmd->chanlist[0]) > 0)
879                         rngmask = 0xff - 0x04;
880                 else
881                         rngmask = 0xff;
882
883                 // for external trigger: looping in this state until the RDY0 pin
884                 // becomes zero
885                 if (cmd->start_src == TRIG_EXT) {       // we loop here until ready has been set
886                         this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01;   // branch back to state 0
887                         this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01;    // deceision state w/o data
888                         this_usbduxfastsub->dux_commands[OUTBASE + 0] =
889                                 0xFF & rngmask;
890                         this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00;   // RDY0 = 0
891                 } else {        // we just proceed to state 1
892                         this_usbduxfastsub->dux_commands[LENBASE + 0] = 1;
893                         this_usbduxfastsub->dux_commands[OPBASE + 0] = 0;
894                         this_usbduxfastsub->dux_commands[OUTBASE + 0] =
895                                 0xFF & rngmask;
896                         this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
897                 }
898
899                 if (steps < MIN_SAMPLING_PERIOD) {
900                         // for fast single channel aqu without mux
901                         if (steps <= 1) {
902                                 // we just stay here at state 1 and rexecute the same state
903                                 // this gives us 30MHz sampling rate
904                                 this_usbduxfastsub->dux_commands[LENBASE + 1] = 0x89;   // branch back to state 1
905                                 this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x03;    // deceision state with data
906                                 this_usbduxfastsub->dux_commands[OUTBASE + 1] =
907                                         0xFF & rngmask;
908                                 this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0xFF;   // doesn't matter
909                         } else {
910                                 // we loop through two states: data and delay: max rate is 15Mhz
911                                 this_usbduxfastsub->dux_commands[LENBASE + 1] =
912                                         steps - 1;
913                                 this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02;    // data
914                                 this_usbduxfastsub->dux_commands[OUTBASE + 1] =
915                                         0xFF & rngmask;
916                                 this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;      // doesn't matter
917
918                                 this_usbduxfastsub->dux_commands[LENBASE + 2] = 0x09;   // branch back to state 1
919                                 this_usbduxfastsub->dux_commands[OPBASE + 2] = 0x01;    // deceision state w/o data
920                                 this_usbduxfastsub->dux_commands[OUTBASE + 2] =
921                                         0xFF & rngmask;
922                                 this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0xFF;   // doesn't matter
923                         }
924                 } else {
925                         // we loop through 3 states: 2x delay and 1x data. This gives a min
926                         // sampling rate of 60kHz.
927
928                         // we have 1 state with duration 1
929                         steps = steps - 1;
930
931                         // do the first part of the delay
932                         this_usbduxfastsub->dux_commands[LENBASE + 1] =
933                                 steps / 2;
934                         this_usbduxfastsub->dux_commands[OPBASE + 1] = 0;
935                         this_usbduxfastsub->dux_commands[OUTBASE + 1] =
936                                 0xFF & rngmask;
937                         this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
938
939                         // and the second part
940                         this_usbduxfastsub->dux_commands[LENBASE + 2] =
941                                 steps - steps / 2;
942                         this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
943                         this_usbduxfastsub->dux_commands[OUTBASE + 2] =
944                                 0xFF & rngmask;
945                         this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
946
947                         // get the data and branch back
948                         this_usbduxfastsub->dux_commands[LENBASE + 3] = 0x09;   // branch back to state 1
949                         this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x03;    // deceision state w data
950                         this_usbduxfastsub->dux_commands[OUTBASE + 3] =
951                                 0xFF & rngmask;
952                         this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0xFF;   // doesn't matter
953                 }
954                 break;
955
956         case 2:
957                 // two channels
958                 // commit data to the FIFO
959                 if (CR_RANGE(cmd->chanlist[0]) > 0)
960                         rngmask = 0xff - 0x04;
961                 else
962                         rngmask = 0xff;
963                 this_usbduxfastsub->dux_commands[LENBASE + 0] = 1;
964                 this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x02;    // data
965                 this_usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
966                 this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
967
968                 // we have 1 state with duration 1: state 0
969                 steps_tmp = steps - 1;
970
971                 if (CR_RANGE(cmd->chanlist[1]) > 0)
972                         rngmask = 0xff - 0x04;
973                 else
974                         rngmask = 0xff;
975                 // do the first part of the delay
976                 this_usbduxfastsub->dux_commands[LENBASE + 1] = steps_tmp / 2;
977                 this_usbduxfastsub->dux_commands[OPBASE + 1] = 0;
978                 this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask; //count
979                 this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
980
981                 // and the second part
982                 this_usbduxfastsub->dux_commands[LENBASE + 2] =
983                         steps_tmp - steps_tmp / 2;
984                 this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
985                 this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
986                 this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
987
988                 this_usbduxfastsub->dux_commands[LENBASE + 3] = 1;
989                 this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x02;    // data
990                 this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
991                 this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
992
993                 // we have 2 states with duration 1: step 6 and the IDLE state
994                 steps_tmp = steps - 2;
995
996                 if (CR_RANGE(cmd->chanlist[0]) > 0)
997                         rngmask = 0xff - 0x04;
998                 else
999                         rngmask = 0xff;
1000                 // do the first part of the delay
1001                 this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2;
1002                 this_usbduxfastsub->dux_commands[OPBASE + 4] = 0;
1003                 this_usbduxfastsub->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask;        //reset
1004                 this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
1005
1006                 // and the second part
1007                 this_usbduxfastsub->dux_commands[LENBASE + 5] =
1008                         steps_tmp - steps_tmp / 2;
1009                 this_usbduxfastsub->dux_commands[OPBASE + 5] = 0;
1010                 this_usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
1011                 this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
1012
1013                 this_usbduxfastsub->dux_commands[LENBASE + 6] = 1;
1014                 this_usbduxfastsub->dux_commands[OPBASE + 6] = 0;
1015                 this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1016                 this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0;
1017                 break;
1018
1019         case 3:
1020                 // three channels
1021                 for (j = 0; j < 1; j++) {
1022                         if (CR_RANGE(cmd->chanlist[j]) > 0)
1023                                 rngmask = 0xff - 0x04;
1024                         else
1025                                 rngmask = 0xff;
1026                         // commit data to the FIFO and do the first part of the delay
1027                         this_usbduxfastsub->dux_commands[LENBASE + j * 2] =
1028                                 steps / 2;
1029                         this_usbduxfastsub->dux_commands[OPBASE + j * 2] = 0x02;        // data
1030                         this_usbduxfastsub->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask;     // no change
1031                         this_usbduxfastsub->dux_commands[LOGBASE + j * 2] = 0;
1032
1033                         if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
1034                                 rngmask = 0xff - 0x04;
1035                         else
1036                                 rngmask = 0xff;
1037                         // do the second part of the delay
1038                         this_usbduxfastsub->dux_commands[LENBASE + j * 2 + 1] =
1039                                 steps - steps / 2;
1040                         this_usbduxfastsub->dux_commands[OPBASE + j * 2 + 1] = 0;       // no data
1041                         this_usbduxfastsub->dux_commands[OUTBASE + j * 2 + 1] = 0xFE & rngmask; //count
1042                         this_usbduxfastsub->dux_commands[LOGBASE + j * 2 + 1] =
1043                                 0;
1044                 }
1045
1046                 // 2 steps with duration 1: the idele step and step 6:
1047                 steps_tmp = steps - 2;
1048                 // commit data to the FIFO and do the first part of the delay
1049                 this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2;
1050                 this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x02;    // data
1051                 this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask; // no change
1052                 this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
1053
1054                 if (CR_RANGE(cmd->chanlist[0]) > 0)
1055                         rngmask = 0xff - 0x04;
1056                 else
1057                         rngmask = 0xff;
1058                 // do the second part of the delay
1059                 this_usbduxfastsub->dux_commands[LENBASE + 5] =
1060                         steps_tmp - steps_tmp / 2;
1061                 this_usbduxfastsub->dux_commands[OPBASE + 5] = 0;       // no data
1062                 this_usbduxfastsub->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask;        // reset
1063                 this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
1064
1065                 this_usbduxfastsub->dux_commands[LENBASE + 6] = 1;
1066                 this_usbduxfastsub->dux_commands[OPBASE + 6] = 0;
1067                 this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1068                 this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0;
1069
1070         case 16:
1071                 if (CR_RANGE(cmd->chanlist[0]) > 0)
1072                         rngmask = 0xff - 0x04;
1073                 else
1074                         rngmask = 0xff;
1075                 if (cmd->start_src == TRIG_EXT) {       // we loop here until ready has been set
1076                         this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01;   // branch back to state 0
1077                         this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01;    // deceision state w/o data
1078                         this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask;        // reset
1079                         this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00;   // RDY0 = 0
1080                 } else {        // we just proceed to state 1
1081                         this_usbduxfastsub->dux_commands[LENBASE + 0] = 255;    // 30us reset pulse
1082                         this_usbduxfastsub->dux_commands[OPBASE + 0] = 0;
1083                         this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask;        // reset
1084                         this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
1085                 }
1086
1087                 // commit data to the FIFO
1088                 this_usbduxfastsub->dux_commands[LENBASE + 1] = 1;
1089                 this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02;    // data
1090                 this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
1091                 this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
1092
1093                 // we have 2 states with duration 1
1094                 steps = steps - 2;
1095
1096                 // do the first part of the delay
1097                 this_usbduxfastsub->dux_commands[LENBASE + 2] = steps / 2;
1098                 this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
1099                 this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
1100                 this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
1101
1102                 // and the second part
1103                 this_usbduxfastsub->dux_commands[LENBASE + 3] =
1104                         steps - steps / 2;
1105                 this_usbduxfastsub->dux_commands[OPBASE + 3] = 0;
1106                 this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
1107                 this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
1108
1109                 this_usbduxfastsub->dux_commands[LENBASE + 4] = 0x09;   // branch back to state 1
1110                 this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x01;    // deceision state w/o data
1111                 this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
1112                 this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0xFF;   // doesn't matter
1113
1114                 break;
1115
1116         default:
1117                 printk("comedi %d: unsupported combination of channels\n",
1118                         dev->minor);
1119                 mutex_unlock(&this_usbduxfastsub->mutex);
1120                 return -EFAULT;
1121         }
1122
1123 #ifdef CONFIG_COMEDI_DEBUG
1124         printk("comedi %d: sending commands to the usb device\n", dev->minor);
1125 #endif
1126         // 0 means that the AD commands are sent
1127         result = send_dux_commands(this_usbduxfastsub, SENDADCOMMANDS);
1128         if (result < 0) {
1129                 printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
1130                 mutex_unlock(&this_usbduxfastsub->mutex);
1131                 return result;
1132         }
1133         if (cmd->stop_src == TRIG_COUNT) {
1134                 this_usbduxfastsub->ai_sample_count =
1135                         (cmd->stop_arg) * (cmd->scan_end_arg);
1136                 if (usbduxfastsub->ai_sample_count < 1) {
1137                         printk("comedi%d: (cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n", dev->minor);
1138                         mutex_unlock(&this_usbduxfastsub->mutex);
1139                         return -EFAULT;
1140                 }
1141                 this_usbduxfastsub->ai_continous = 0;
1142         } else {
1143                 // continous aquisition
1144                 this_usbduxfastsub->ai_continous = 1;
1145                 this_usbduxfastsub->ai_sample_count = 0;
1146         }
1147
1148         if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
1149                 // enable this acquisition operation
1150                 this_usbduxfastsub->ai_cmd_running = 1;
1151                 ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub);
1152                 if (ret < 0) {
1153                         this_usbduxfastsub->ai_cmd_running = 0;
1154                         // fixme: unlink here??
1155                         mutex_unlock(&this_usbduxfastsub->mutex);
1156                         return ret;
1157                 }
1158                 s->async->inttrig = NULL;
1159         } else {
1160                 /* TRIG_INT */
1161                 // don't enable the acquision operation
1162                 // wait for an internal signal
1163                 s->async->inttrig = usbduxfast_ai_inttrig;
1164         }
1165         mutex_unlock(&this_usbduxfastsub->mutex);
1166
1167         return 0;
1168 }
1169
1170 /* Mode 0 is used to get a single conversion on demand */
1171 static int usbduxfast_ai_insn_read(comedi_device * dev,
1172         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
1173 {
1174         int i, j, n, actual_length;
1175         int chan, range, rngmask;
1176         int err;
1177         usbduxfastsub_t *usbduxfastsub = dev->private;
1178
1179         if (!usbduxfastsub) {
1180                 printk("comedi%d: ai_insn_read: no usb dev.\n", dev->minor);
1181                 return -ENODEV;
1182         }
1183 #ifdef CONFIG_COMEDI_DEBUG
1184         printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1185                 dev->minor, insn->n, insn->subdev);
1186 #endif
1187         mutex_lock(&usbduxfastsub->mutex);
1188         if (!(usbduxfastsub->probed)) {
1189                 mutex_unlock(&usbduxfastsub->mutex);
1190                 return -ENODEV;
1191         }
1192         if (usbduxfastsub->ai_cmd_running) {
1193                 printk("comedi%d: ai_insn_read not possible. Async Command is running.\n", dev->minor);
1194                 mutex_unlock(&usbduxfastsub->mutex);
1195                 return -EBUSY;
1196         }
1197         // sample one channel
1198         chan = CR_CHAN(insn->chanspec);
1199         range = CR_RANGE(insn->chanspec);
1200         // set command for the first channel
1201
1202         if (range > 0)
1203                 rngmask = 0xff - 0x04;
1204         else
1205                 rngmask = 0xff;
1206         // commit data to the FIFO
1207         usbduxfastsub->dux_commands[LENBASE + 0] = 1;
1208         usbduxfastsub->dux_commands[OPBASE + 0] = 0x02; // data
1209         usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
1210         usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
1211
1212         // do the first part of the delay
1213         usbduxfastsub->dux_commands[LENBASE + 1] = 12;
1214         usbduxfastsub->dux_commands[OPBASE + 1] = 0;
1215         usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
1216         usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
1217
1218         usbduxfastsub->dux_commands[LENBASE + 2] = 1;
1219         usbduxfastsub->dux_commands[OPBASE + 2] = 0;
1220         usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
1221         usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
1222
1223         usbduxfastsub->dux_commands[LENBASE + 3] = 1;
1224         usbduxfastsub->dux_commands[OPBASE + 3] = 0;
1225         usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFE & rngmask;
1226         usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
1227
1228         usbduxfastsub->dux_commands[LENBASE + 4] = 1;
1229         usbduxfastsub->dux_commands[OPBASE + 4] = 0;
1230         usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFE & rngmask;
1231         usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
1232
1233         // second part
1234         usbduxfastsub->dux_commands[LENBASE + 5] = 12;
1235         usbduxfastsub->dux_commands[OPBASE + 5] = 0;
1236         usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
1237         usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
1238
1239         usbduxfastsub->dux_commands[LENBASE + 6] = 1;
1240         usbduxfastsub->dux_commands[OPBASE + 6] = 0;
1241         usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
1242         usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
1243
1244 #ifdef CONFIG_COMEDI_DEBUG
1245         printk("comedi %d: sending commands to the usb device\n", dev->minor);
1246 #endif
1247         // 0 means that the AD commands are sent
1248         err = send_dux_commands(usbduxfastsub, SENDADCOMMANDS);
1249         if (err < 0) {
1250                 printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
1251                 mutex_unlock(&usbduxfastsub->mutex);
1252                 return err;
1253         }
1254 #ifdef CONFIG_COMEDI_DEBUG
1255         printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n",
1256                 usbduxfastsub->comedidev->minor,
1257                 (int)(usbduxfastsub->urbIn->context),
1258                 (int)(usbduxfastsub->urbIn->dev));
1259 #endif
1260         for (i = 0; i < PACKETS_TO_IGNORE; i++) {
1261                 err = USB_BULK_MSG(usbduxfastsub->usbdev,
1262                         usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
1263                         usbduxfastsub->transfer_buffer,
1264                         SIZEINBUF, &actual_length, BULK_TIMEOUT);
1265                 if (err < 0) {
1266                         printk("comedi%d: insn timeout. No data.\n",
1267                                 dev->minor);
1268                         mutex_unlock(&usbduxfastsub->mutex);
1269                         return err;
1270                 }
1271         }
1272         // data points
1273         for (i = 0; i < insn->n;) {
1274                 err = USB_BULK_MSG(usbduxfastsub->usbdev,
1275                         usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
1276                         usbduxfastsub->transfer_buffer,
1277                         SIZEINBUF, &actual_length, BULK_TIMEOUT);
1278                 if (err < 0) {
1279                         printk("comedi%d: insn data error: %d\n",
1280                                 dev->minor, err);
1281                         mutex_unlock(&usbduxfastsub->mutex);
1282                         return err;
1283                 }
1284                 n = actual_length / sizeof(uint16_t);
1285                 if ((n % 16) != 0) {
1286                         printk("comedi%d: insn data packet corrupted.\n",
1287                                 dev->minor);
1288                         mutex_unlock(&usbduxfastsub->mutex);
1289                         return -EINVAL;
1290                 }
1291                 for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
1292                         data[i] =
1293                                 ((uint16_t *) (usbduxfastsub->
1294                                         transfer_buffer))[j];
1295                         i++;
1296                 }
1297         }
1298         mutex_unlock(&usbduxfastsub->mutex);
1299         return i;
1300 }
1301
1302 static unsigned hex2unsigned(char *h)
1303 {
1304         unsigned hi, lo;
1305         if (h[0] > '9') {
1306                 hi = h[0] - 'A' + 0x0a;
1307         } else {
1308                 hi = h[0] - '0';
1309         }
1310         if (h[1] > '9') {
1311                 lo = h[1] - 'A' + 0x0a;
1312         } else {
1313                 lo = h[1] - '0';
1314         }
1315         return hi * 0x10 + lo;
1316 }
1317
1318 // for FX2
1319 #define FIRMWARE_MAX_LEN 0x2000
1320
1321 // taken from David Brownell's fxload and adjusted for this driver
1322 static int read_firmware(usbduxfastsub_t * usbduxfastsub,
1323                          const void *firmwarePtr,
1324                          long size)
1325 {
1326         int i = 0;
1327         unsigned char *fp = (char *)firmwarePtr;
1328         unsigned char *firmwareBinary = NULL;
1329         int res = 0;
1330         int maxAddr = 0;
1331
1332         firmwareBinary = kmalloc(FIRMWARE_MAX_LEN, GFP_KERNEL);
1333         if (!firmwareBinary) {
1334                 printk("comedi_: usbduxfast: mem alloc for firmware failed\n");
1335                 return -ENOMEM;
1336         }
1337
1338         for (;;) {
1339                 char buf[256], *cp;
1340                 char type;
1341                 int len;
1342                 int idx, off;
1343                 int j = 0;
1344
1345                 // get one line
1346                 while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) {
1347                         buf[j] = fp[i];
1348                         i++;
1349                         j++;
1350                         if (j >= sizeof(buf)) {
1351                                 printk("comedi_: usbduxfast: bogus firmware file!\n");
1352                                 return -1;
1353                         }
1354                 }
1355                 // get rid of LF/CR/...
1356                 while ((i < size) && ((fp[i] == 13) || (fp[i] == 10)
1357                                 || (fp[i] == 0))) {
1358                         i++;
1359                 }
1360
1361                 buf[j] = 0;
1362                 //printk("comedi_: buf=%s\n",buf);
1363
1364                 /* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
1365                 if (buf[0] == '#')
1366                         continue;
1367
1368                 if (buf[0] != ':') {
1369                         printk("comedi_: usbduxfast: upload: not an ihex record: %s", buf);
1370                         return -EFAULT;
1371                 }
1372
1373                 /* Read the length field (up to 16 bytes) */
1374                 len = hex2unsigned(buf + 1);
1375
1376                 /* Read the target offset */
1377                 off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5);
1378
1379                 if ((off + len) > maxAddr) {
1380                         maxAddr = off + len;
1381                 }
1382
1383                 if (maxAddr >= FIRMWARE_MAX_LEN) {
1384                         printk("comedi_: usbduxfast: firmware upload goes beyond FX2 RAM boundaries.");
1385                         return -EFAULT;
1386                 }
1387                 //printk("comedi_: usbduxfast: off=%x, len=%x:",off,len);
1388
1389                 /* Read the record type */
1390                 type = hex2unsigned(buf + 7);
1391
1392                 /* If this is an EOF record, then make it so. */
1393                 if (type == 1) {
1394                         break;
1395                 }
1396
1397                 if (type != 0) {
1398                         printk("comedi_: usbduxfast: unsupported record type: %u\n", type);
1399                         return -EFAULT;
1400                 }
1401
1402                 for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) {
1403                         firmwareBinary[idx + off] = hex2unsigned(cp);
1404                         //printk("%02x ",firmwareBinary[idx+off]);
1405                 }
1406                 //printk("\n");
1407
1408                 if (i >= size) {
1409                         printk("comedi_: usbduxfast: unexpected end of hex file\n");
1410                         break;
1411                 }
1412
1413         }
1414         res = firmwareUpload(usbduxfastsub, firmwareBinary, maxAddr + 1);
1415         kfree(firmwareBinary);
1416         return res;
1417 }
1418
1419 static void tidy_up(usbduxfastsub_t * usbduxfastsub_tmp)
1420 {
1421 #ifdef CONFIG_COMEDI_DEBUG
1422         printk("comedi_: usbduxfast: tiding up\n");
1423 #endif
1424         if (!usbduxfastsub_tmp) {
1425                 return;
1426         }
1427 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1428         // shows the usb subsystem that the driver is down
1429         if (usbduxfastsub_tmp->interface) {
1430                 usb_set_intfdata(usbduxfastsub_tmp->interface, NULL);
1431         }
1432 #endif
1433
1434         usbduxfastsub_tmp->probed = 0;
1435
1436         if (usbduxfastsub_tmp->urbIn) {
1437 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
1438                 // waits until a running transfer is over
1439                 // thus, under 2.4 hotplugging while a command
1440                 // is running is not safe
1441                 usb_kill_urb(usbduxfastsub_tmp->urbIn);
1442 #endif
1443                 if (usbduxfastsub_tmp->transfer_buffer) {
1444                         kfree(usbduxfastsub_tmp->transfer_buffer);
1445                         usbduxfastsub_tmp->transfer_buffer = NULL;
1446                 }
1447                 usb_free_urb(usbduxfastsub_tmp->urbIn);
1448                 usbduxfastsub_tmp->urbIn = NULL;
1449         }
1450         if (usbduxfastsub_tmp->insnBuffer) {
1451                 kfree(usbduxfastsub_tmp->insnBuffer);
1452                 usbduxfastsub_tmp->insnBuffer = NULL;
1453         }
1454         if (usbduxfastsub_tmp->dux_commands) {
1455                 kfree(usbduxfastsub_tmp->dux_commands);
1456                 usbduxfastsub_tmp->dux_commands = NULL;
1457         }
1458         usbduxfastsub_tmp->ai_cmd_running = 0;
1459 }
1460
1461 static void usbduxfast_firmware_request_complete_handler(
1462         const struct firmware *fw,
1463         void *context)
1464 {
1465         usbduxfastsub_t * usbduxfastsub_tmp = (usbduxfastsub_t *)context;
1466         struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
1467         int ret;
1468
1469         if(fw == NULL) {
1470                 return;
1471         }
1472
1473         // we need to upload the firmware here because fw will be
1474         // freed one we've left this function
1475         ret=read_firmware(usbduxfastsub_tmp,
1476                           fw->data,
1477                           fw->size);
1478
1479         if (ret) {
1480                 dev_err(&usbdev->dev,
1481                         "Could not upload firmware (err=%d)\n",
1482                         ret);
1483                 goto out;
1484         }
1485
1486         comedi_usb_auto_config(usbdev, BOARDNAME);
1487 out:
1488         /*
1489          * in more recent versions the completion handler
1490          * had to release the firmware whereas in older
1491          * versions this has been done by the caller
1492          */
1493         COMEDI_RELEASE_FIRMWARE_NOWAIT(fw);
1494 }
1495
1496 // allocate memory for the urbs and initialise them
1497 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1498 static void *usbduxfastsub_probe(struct usb_device *udev,
1499                                  unsigned int interfnum,
1500                                  const struct usb_device_id *id)
1501 {
1502 #else
1503 static int usbduxfastsub_probe(struct usb_interface *uinterf,
1504         const struct usb_device_id *id)
1505 {
1506         struct usb_device *udev = interface_to_usbdev(uinterf);
1507 #endif
1508         int i;
1509         int index;
1510         int ret;
1511
1512         if (udev->speed != USB_SPEED_HIGH) {
1513                 printk("comedi_: usbduxfast_: This driver needs USB 2.0 to operate. Aborting...\n");
1514                 return PROBE_ERR_RETURN(-ENODEV);
1515         }
1516 #ifdef CONFIG_COMEDI_DEBUG
1517         printk("comedi_: usbduxfast_: finding a free structure for the usb-device\n");
1518 #endif
1519         mutex_lock(&start_stop_mutex);
1520         // look for a free place in the usbduxfast array
1521         index = -1;
1522         for (i = 0; i < NUMUSBDUXFAST; i++) {
1523                 if (!(usbduxfastsub[i].probed)) {
1524                         index = i;
1525                         break;
1526                 }
1527         }
1528
1529         // no more space
1530         if (index == -1) {
1531                 printk("Too many usbduxfast-devices connected.\n");
1532                 mutex_unlock(&start_stop_mutex);
1533                 return PROBE_ERR_RETURN(-EMFILE);
1534         }
1535 #ifdef CONFIG_COMEDI_DEBUG
1536         printk("comedi_: usbduxfast: usbduxfastsub[%d] is ready to connect to comedi.\n", index);
1537 #endif
1538
1539         mutex_init(&(usbduxfastsub[index].mutex));
1540         // save a pointer to the usb device
1541         usbduxfastsub[index].usbdev = udev;
1542
1543 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1544         // save the interface number
1545         usbduxfastsub[index].ifnum = interfnum;
1546 #else
1547         // 2.6: save the interface itself
1548         usbduxfastsub[index].interface = uinterf;
1549         // get the interface number from the interface
1550         usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
1551         // hand the private data over to the usb subsystem
1552         // will be needed for disconnect
1553         usb_set_intfdata(uinterf, &(usbduxfastsub[index]));
1554 #endif
1555
1556 #ifdef CONFIG_COMEDI_DEBUG
1557         printk("comedi_: usbduxfast: ifnum=%d\n", usbduxfastsub[index].ifnum);
1558 #endif
1559         // create space for the commands going to the usb device
1560         usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
1561                 GFP_KERNEL);
1562         if (!usbduxfastsub[index].dux_commands) {
1563                 printk("comedi_: usbduxfast: error alloc space for dac commands\n");
1564                 tidy_up(&(usbduxfastsub[index]));
1565                 mutex_unlock(&start_stop_mutex);
1566                 return PROBE_ERR_RETURN(-ENOMEM);
1567         }
1568         // create space of the instruction buffer
1569         usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
1570         if (!(usbduxfastsub[index].insnBuffer)) {
1571                 printk("comedi_: usbduxfast: could not alloc space for insnBuffer\n");
1572                 tidy_up(&(usbduxfastsub[index]));
1573                 mutex_unlock(&start_stop_mutex);
1574                 return PROBE_ERR_RETURN(-ENOMEM);
1575         }
1576         // setting to alternate setting 1: enabling bulk ep
1577         i = usb_set_interface(usbduxfastsub[index].usbdev,
1578                 usbduxfastsub[index].ifnum, 1);
1579         if (i < 0) {
1580                 printk("comedi_: usbduxfast%d: could not switch to alternate setting 1.\n", index);
1581                 tidy_up(&(usbduxfastsub[index]));
1582                 mutex_unlock(&start_stop_mutex);
1583                 return PROBE_ERR_RETURN(-ENODEV);
1584         }
1585         usbduxfastsub[index].urbIn = USB_ALLOC_URB(0);
1586         if (usbduxfastsub[index].urbIn == NULL) {
1587                 printk("comedi_: usbduxfast%d: Could not alloc. urb\n", index);
1588                 tidy_up(&(usbduxfastsub[index]));
1589                 mutex_unlock(&start_stop_mutex);
1590                 return PROBE_ERR_RETURN(-ENOMEM);
1591         }
1592         usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
1593         if (!(usbduxfastsub[index].transfer_buffer)) {
1594                 printk("comedi_: usbduxfast%d: could not alloc. transb.\n",
1595                         index);
1596                 tidy_up(&(usbduxfastsub[index]));
1597                 mutex_unlock(&start_stop_mutex);
1598                 return PROBE_ERR_RETURN(-ENOMEM);
1599         }
1600         // we've reached the bottom of the function
1601         usbduxfastsub[index].probed = 1;
1602         mutex_unlock(&start_stop_mutex);
1603
1604         ret = request_firmware_nowait(THIS_MODULE,
1605                                       FW_ACTION_HOTPLUG,
1606                                       "usbduxfast_firmware.hex",
1607                                       &udev->dev,
1608                                       GFP_KERNEL,
1609                                       usbduxfastsub + index,
1610                                       usbduxfast_firmware_request_complete_handler);
1611
1612         if (ret) {
1613                 dev_err(&udev->dev,
1614                         "could not load firmware (err=%d)\n",
1615                         ret);
1616                 return ret;
1617         }
1618
1619         printk("comedi_: usbduxfast%d has been successfully initialized.\n",
1620                index);
1621
1622 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1623         return (void *)(&usbduxfastsub[index]);
1624 #else
1625         // success
1626         return 0;
1627 #endif
1628 }
1629
1630 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
1631 static void usbduxfastsub_disconnect(struct usb_device *udev, void *ptr)
1632 {
1633         usbduxfastsub_t *usbduxfastsub_tmp = (usbduxfastsub_t *) ptr;
1634 #else
1635 static void usbduxfastsub_disconnect(struct usb_interface *intf)
1636 {
1637         usbduxfastsub_t *usbduxfastsub_tmp = usb_get_intfdata(intf);
1638         struct usb_device *udev = interface_to_usbdev(intf);
1639 #endif
1640         if (!usbduxfastsub_tmp) {
1641                 printk("comedi_: usbduxfast: disconnect called with null pointer.\n");
1642                 return;
1643         }
1644         if (usbduxfastsub_tmp->usbdev != udev) {
1645                 printk("comedi_: usbduxfast: BUG! called with wrong ptr!!!\n");
1646                 return;
1647         }
1648
1649         comedi_usb_auto_unconfig(udev);
1650
1651         mutex_lock(&start_stop_mutex);
1652         mutex_lock(&usbduxfastsub_tmp->mutex);
1653         tidy_up(usbduxfastsub_tmp);
1654         mutex_unlock(&usbduxfastsub_tmp->mutex);
1655         mutex_unlock(&start_stop_mutex);
1656 #ifdef CONFIG_COMEDI_DEBUG
1657         printk("comedi_: usbduxfast: disconnected from the usb\n");
1658 #endif
1659 }
1660
1661 // is called when comedi-config is called
1662 static int usbduxfast_attach(comedi_device * dev, comedi_devconfig * it)
1663 {
1664         int ret;
1665         int index;
1666         int i;
1667         comedi_subdevice *s = NULL;
1668         dev->private = NULL;
1669
1670         mutex_lock(&start_stop_mutex);
1671         // find a valid device which has been detected by the probe function of the usb
1672         index = -1;
1673         for (i = 0; i < NUMUSBDUXFAST; i++) {
1674                 if ((usbduxfastsub[i].probed) && (!usbduxfastsub[i].attached)) {
1675                         index = i;
1676                         break;
1677                 }
1678         }
1679
1680         if (index < 0) {
1681                 printk("comedi%d: usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n", dev->minor);
1682                 mutex_unlock(&start_stop_mutex);
1683                 return -ENODEV;
1684         }
1685
1686         mutex_lock(&(usbduxfastsub[index].mutex));
1687         // pointer back to the corresponding comedi device
1688         usbduxfastsub[index].comedidev = dev;
1689
1690         // trying to upload the firmware into the chip
1691         if (comedi_aux_data(it->options, 0) &&
1692             it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
1693                 read_firmware(&usbduxfastsub[index],
1694                               comedi_aux_data(it->options, 0),
1695                               it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
1696         }
1697
1698         dev->board_name = BOARDNAME;
1699
1700         /* set number of subdevices */
1701         dev->n_subdevices = N_SUBDEVICES;
1702
1703         // allocate space for the subdevices
1704         if ((ret = alloc_subdevices(dev, N_SUBDEVICES)) < 0) {
1705                 printk("comedi%d: usbduxfast: error alloc space for subdev\n",
1706                         dev->minor);
1707                 mutex_unlock(&start_stop_mutex);
1708                 return ret;
1709         }
1710
1711         printk("comedi%d: usbduxfast: usb-device %d is attached to comedi.\n",
1712                 dev->minor, index);
1713         // private structure is also simply the usb-structure
1714         dev->private = usbduxfastsub + index;
1715         // the first subdevice is the A/D converter
1716         s = dev->subdevices + SUBDEV_AD;
1717         // the URBs get the comedi subdevice
1718         // which is responsible for reading
1719         // this is the subdevice which reads data
1720         dev->read_subdev = s;
1721         // the subdevice receives as private structure the
1722         // usb-structure
1723         s->private = NULL;
1724         // analog input
1725         s->type = COMEDI_SUBD_AI;
1726         // readable and ref is to ground
1727         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
1728         // 16 channels
1729         s->n_chan = 16;
1730         // length of the channellist
1731         s->len_chanlist = 16;
1732         // callback functions
1733         s->insn_read = usbduxfast_ai_insn_read;
1734         s->do_cmdtest = usbduxfast_ai_cmdtest;
1735         s->do_cmd = usbduxfast_ai_cmd;
1736         s->cancel = usbduxfast_ai_cancel;
1737         // max value from the A/D converter (12bit+1 bit for overflow)
1738         s->maxdata = 0x1000;
1739         // range table to convert to physical units
1740         s->range_table = &range_usbduxfast_ai_range;
1741
1742         // finally decide that it's attached
1743         usbduxfastsub[index].attached = 1;
1744
1745         mutex_unlock(&(usbduxfastsub[index].mutex));
1746
1747         mutex_unlock(&start_stop_mutex);
1748
1749         printk("comedi%d: successfully attached to usbduxfast.\n", dev->minor);
1750
1751         return 0;
1752 }
1753
1754 static int usbduxfast_detach(comedi_device * dev)
1755 {
1756         usbduxfastsub_t *usbduxfastsub_tmp;
1757
1758 #ifdef CONFIG_COMEDI_DEBUG
1759         printk("comedi%d: usbduxfast: detach usb device\n", dev->minor);
1760 #endif
1761
1762         if (!dev) {
1763                 printk("comedi?: usbduxfast: detach without dev variable...\n");
1764                 return -EFAULT;
1765         }
1766
1767         usbduxfastsub_tmp = dev->private;
1768         if (!usbduxfastsub_tmp) {
1769                 printk("comedi?: usbduxfast: detach without ptr to usbduxfastsub[]\n");
1770                 return -EFAULT;
1771         }
1772
1773         mutex_lock(&usbduxfastsub_tmp->mutex);
1774         mutex_lock(&start_stop_mutex);
1775         // Don't allow detach to free the private structure
1776         // It's one entry of of usbduxfastsub[]
1777         dev->private = NULL;
1778         usbduxfastsub_tmp->attached = 0;
1779         usbduxfastsub_tmp->comedidev = NULL;
1780 #ifdef CONFIG_COMEDI_DEBUG
1781         printk("comedi%d: usbduxfast: detach: successfully removed\n",
1782                 dev->minor);
1783 #endif
1784         mutex_unlock(&start_stop_mutex);
1785         mutex_unlock(&usbduxfastsub_tmp->mutex);
1786         return 0;
1787 }
1788
1789 /* main driver struct */
1790 static comedi_driver driver_usbduxfast = {
1791       driver_name:"usbduxfast",
1792       module:THIS_MODULE,
1793       attach:usbduxfast_attach,
1794       detach:usbduxfast_detach,
1795 };
1796
1797 static void init_usb_devices(void)
1798 {
1799         int index;
1800 #ifdef CONFIG_COMEDI_DEBUG
1801         printk("comedi_: usbduxfast: setting all possible devs to invalid\n");
1802 #endif
1803         // all devices entries are invalid to begin with
1804         // they will become valid by the probe function
1805         // and then finally by the attach-function
1806         for (index = 0; index < NUMUSBDUXFAST; index++) {
1807                 memset(&(usbduxfastsub[index]), 0x00,
1808                         sizeof(usbduxfastsub[index]));
1809                 mutex_init(&(usbduxfastsub[index].mutex));
1810         }
1811 }
1812
1813 static void uninit_usb_devices(void)
1814 {
1815         int index;
1816
1817         for (index = 0; index < NUMUSBDUXFAST; index++) {
1818                 mutex_destroy(&(usbduxfastsub[index].mutex));
1819         }
1820 }
1821
1822 // Table with the USB-devices: just now only testing IDs
1823 static struct usb_device_id usbduxfastsub_table[] = {
1824         //        { USB_DEVICE(0x4b4, 0x8613), //testing
1825         //        },
1826         {USB_DEVICE(0x13d8, 0x0010)     //real ID
1827                 },
1828         {USB_DEVICE(0x13d8, 0x0011)     //real ID
1829                 },
1830         {}                      /* Terminating entry */
1831 };
1832
1833 MODULE_DEVICE_TABLE(usb, usbduxfastsub_table);
1834
1835 // The usbduxfastsub-driver
1836 static struct usb_driver usbduxfastsub_driver = {
1837 #ifdef COMEDI_HAVE_USB_DRIVER_OWNER
1838       owner:THIS_MODULE,
1839 #endif
1840       name:BOARDNAME,
1841       probe:usbduxfastsub_probe,
1842       disconnect:usbduxfastsub_disconnect,
1843       id_table:usbduxfastsub_table,
1844 };
1845
1846 // Can't use the nice macro as I have also to initialise the USB
1847 // subsystem:
1848 // registering the usb-system _and_ the comedi-driver
1849 static int init_usbduxfast(void)
1850 {
1851         printk(KERN_INFO KBUILD_MODNAME ": "
1852                DRIVER_VERSION ":" DRIVER_DESC "\n");
1853         init_usb_devices();
1854         usb_register(&usbduxfastsub_driver);
1855         comedi_driver_register(&driver_usbduxfast);
1856         return 0;
1857 }
1858
1859 // deregistering the comedi driver and the usb-subsystem
1860 static void exit_usbduxfast(void)
1861 {
1862         comedi_driver_unregister(&driver_usbduxfast);
1863         usb_deregister(&usbduxfastsub_driver);
1864         uninit_usb_devices();
1865 }
1866
1867 module_init(init_usbduxfast);
1868 module_exit(exit_usbduxfast);
1869
1870 MODULE_AUTHOR(DRIVER_AUTHOR);
1871 MODULE_DESCRIPTION(DRIVER_DESC);
1872 MODULE_LICENSE("GPL");