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