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