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