usbduxfast.c revision e57795a1a7ebf8ac91cfb82070cf19bf01ee4ac0
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: usbduxfast: uploading %d bytes", len);
502	printk(KERN_DEBUG " to addr %d, first byte=%d.\n",
503		startAddr, local_transfer_buffer[0]);
504#endif
505	ret = usb_control_msg(udfs->usbdev,
506		usb_sndctrlpipe(udfs->usbdev, 0),
507		USBDUXFASTSUB_FIRMWARE, /* brequest, firmware */
508		VENDOR_DIR_OUT,		/* bmRequestType */
509		startAddr,		/* value */
510		0x0000,			/* index */
511		local_transfer_buffer,	/* our local safe buffer */
512		len,			/* length */
513		EZTIMEOUT);		/* timeout */
514
515#ifdef CONFIG_COMEDI_DEBUG
516	printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret);
517#endif
518
519	if (ret < 0) {
520		printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n");
521		return ret;
522	}
523
524	return 0;
525}
526
527int firmwareUpload(struct usbduxfastsub_s *udfs, unsigned char *firmwareBinary,
528		   int sizeFirmware)
529{
530	int ret;
531
532	if (!firmwareBinary)
533		return 0;
534
535	ret = usbduxfastsub_stop(udfs);
536	if (ret < 0) {
537		printk(KERN_ERR "comedi_: usbduxfast: can not stop firmware\n");
538		return ret;
539	}
540	ret = usbduxfastsub_upload(udfs, firmwareBinary, 0, sizeFirmware);
541	if (ret < 0) {
542		printk(KERN_ERR "comedi_: usbduxfast: firmware upload failed\n");
543		return ret;
544	}
545	ret = usbduxfastsub_start(udfs);
546	if (ret < 0) {
547		printk(KERN_ERR "comedi_: usbduxfast: can not start firmware\n");
548		return ret;
549	}
550
551	return 0;
552}
553
554int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs)
555{
556	int ret;
557
558	if (!udfs)
559		return -EFAULT;
560
561	usb_fill_bulk_urb(udfs->urbIn, udfs->usbdev,
562			  usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
563			  udfs->transfer_buffer,
564			  SIZEINBUF, usbduxfastsub_ai_Irq, udfs->comedidev);
565
566#ifdef CONFIG_COMEDI_DEBUG
567	printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
568	       "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
569		udfs->urbIn->dev);
570#endif
571	ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC);
572	if (ret) {
573		printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error"
574		       " %d\n", ret);
575		return ret;
576	}
577	return 0;
578}
579
580static int usbduxfast_ai_cmdtest(comedi_device *dev,
581	comedi_subdevice *s, comedi_cmd *cmd)
582{
583	int err = 0, stop_mask = 0;
584	long int steps, tmp;
585	int minSamplPer;
586	struct usbduxfastsub_s *udfs = dev->private;
587
588	if (!udfs->probed)
589		return -ENODEV;
590
591#ifdef CONFIG_COMEDI_DEBUG
592	printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmdtest\n", dev->minor);
593	printk(KERN_DEBUG "comedi%d: usbduxfast: convert_arg=%u "
594	       "scan_begin_arg=%u\n",
595	       dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
596#endif
597	/* step 1: make sure trigger sources are trivially valid */
598
599	tmp = cmd->start_src;
600	cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
601	if (!cmd->start_src || tmp != cmd->start_src)
602		err++;
603
604	tmp = cmd->scan_begin_src;
605	cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
606	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
607		err++;
608
609	tmp = cmd->convert_src;
610	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
611	if (!cmd->convert_src || tmp != cmd->convert_src)
612		err++;
613
614	tmp = cmd->scan_end_src;
615	cmd->scan_end_src &= TRIG_COUNT;
616	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
617		err++;
618
619	tmp = cmd->stop_src;
620	stop_mask = TRIG_COUNT | TRIG_NONE;
621	cmd->stop_src &= stop_mask;
622	if (!cmd->stop_src || tmp != cmd->stop_src)
623		err++;
624
625	if (err)
626		return 1;
627
628	/*
629	 * step 2: make sure trigger sources are unique and mutually compatible
630	 */
631
632	if (cmd->start_src != TRIG_NOW &&
633		cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT)
634		err++;
635	if (cmd->scan_begin_src != TRIG_TIMER &&
636		cmd->scan_begin_src != TRIG_FOLLOW &&
637		cmd->scan_begin_src != TRIG_EXT)
638		err++;
639	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
640		err++;
641	if (cmd->stop_src != TRIG_COUNT &&
642		cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
643		err++;
644
645	/* can't have external stop and start triggers at once */
646	if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
647		err++;
648
649	if (err)
650		return 2;
651
652	/* step 3: make sure arguments are trivially compatible */
653
654	if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) {
655		cmd->start_arg = 0;
656		err++;
657	}
658
659	if (!cmd->chanlist_len)
660		err++;
661
662	if (cmd->scan_end_arg != cmd->chanlist_len) {
663		cmd->scan_end_arg = cmd->chanlist_len;
664		err++;
665	}
666
667	if (cmd->chanlist_len == 1)
668		minSamplPer = 1;
669	else
670		minSamplPer = MIN_SAMPLING_PERIOD;
671
672	if (cmd->convert_src == TRIG_TIMER) {
673		steps = cmd->convert_arg * 30;
674		if (steps < (minSamplPer * 1000))
675			steps = minSamplPer * 1000;
676
677		if (steps > (MAX_SAMPLING_PERIOD * 1000))
678			steps = MAX_SAMPLING_PERIOD * 1000;
679
680		/* calc arg again */
681		tmp = steps / 30;
682		if (cmd->convert_arg != tmp) {
683			cmd->convert_arg = tmp;
684			err++;
685		}
686	}
687
688	if (cmd->scan_begin_src == TRIG_TIMER)
689		err++;
690
691	/* stop source */
692	switch (cmd->stop_src) {
693	case TRIG_COUNT:
694		if (!cmd->stop_arg) {
695			cmd->stop_arg = 1;
696			err++;
697		}
698		break;
699	case TRIG_NONE:
700		if (cmd->stop_arg != 0) {
701			cmd->stop_arg = 0;
702			err++;
703		}
704		break;
705		/*
706		 * TRIG_EXT doesn't care since it doesn't trigger
707		 * off a numbered channel
708		 */
709	default:
710		break;
711	}
712
713	if (err)
714		return 3;
715
716	/* step 4: fix up any arguments */
717
718	return 0;
719
720}
721
722static int usbduxfast_ai_inttrig(comedi_device *dev,
723	comedi_subdevice *s, unsigned int trignum)
724{
725	int ret;
726	struct usbduxfastsub_s *udfs = dev->private;
727
728	if (!udfs)
729		return -EFAULT;
730
731	down(&udfs->sem);
732	if (!udfs->probed) {
733		up(&udfs->sem);
734		return -ENODEV;
735	}
736#ifdef CONFIG_COMEDI_DEBUG
737	printk(KERN_DEBUG "comedi%d: usbduxfast_ai_inttrig\n", dev->minor);
738#endif
739
740	if (trignum != 0) {
741		printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid"
742		       " trignum\n", dev->minor);
743		up(&udfs->sem);
744		return -EINVAL;
745	}
746	if (!udfs->ai_cmd_running) {
747		udfs->ai_cmd_running = 1;
748		ret = usbduxfastsub_submit_InURBs(udfs);
749		if (ret < 0) {
750			printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: "
751			       "urbSubmit: err=%d\n", dev->minor, ret);
752			udfs->ai_cmd_running = 0;
753			up(&udfs->sem);
754			return ret;
755		}
756		s->async->inttrig = NULL;
757	} else {
758		printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already"
759		       " running\n", dev->minor);
760	}
761	up(&udfs->sem);
762	return 1;
763}
764
765/*
766 * offsets for the GPIF bytes
767 * the first byte is the command byte
768 */
769#define LENBASE	(1+0x00)
770#define OPBASE	(1+0x08)
771#define OUTBASE	(1+0x10)
772#define LOGBASE	(1+0x18)
773
774static int usbduxfast_ai_cmd(comedi_device *dev, comedi_subdevice *s)
775{
776	comedi_cmd *cmd = &s->async->cmd;
777	unsigned int chan, gain, rngmask = 0xff;
778	int i, j, ret;
779	struct usbduxfastsub_s *udfs;
780	int result;
781	long steps, steps_tmp;
782
783#ifdef CONFIG_COMEDI_DEBUG
784	printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmd\n", dev->minor);
785#endif
786	udfs = dev->private;
787	if (!udfs)
788		return -EFAULT;
789
790	down(&udfs->sem);
791	if (!udfs->probed) {
792		up(&udfs->sem);
793		return -ENODEV;
794	}
795	if (udfs->ai_cmd_running) {
796		printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd"
797		       " is running.\n", dev->minor);
798		up(&udfs->sem);
799		return -EBUSY;
800	}
801	/* set current channel of the running aquisition to zero */
802	s->async->cur_chan = 0;
803
804	/*
805	 * ignore the first buffers from the device if there
806	 * is an error condition
807	 */
808	udfs->ignore = PACKETS_TO_IGNORE;
809
810	if (cmd->chanlist_len > 0) {
811		gain = CR_RANGE(cmd->chanlist[0]);
812		for (i = 0; i < cmd->chanlist_len; ++i) {
813			chan = CR_CHAN(cmd->chanlist[i]);
814			if (chan != i) {
815				printk(KERN_ERR "comedi%d: cmd is accepting "
816				       "only consecutive channels.\n",
817				       dev->minor);
818				up(&udfs->sem);
819				return -EINVAL;
820			}
821			if ((gain != CR_RANGE(cmd->chanlist[i]))
822				&& (cmd->chanlist_len > 3)) {
823				printk(KERN_ERR "comedi%d: the gain must be"
824				       " the same for all channels.\n",
825				       dev->minor);
826				up(&udfs->sem);
827				return -EINVAL;
828			}
829			if (i >= NUMCHANNELS) {
830				printk(KERN_ERR "comedi%d: channel list too"
831				       " long\n", dev->minor);
832				break;
833			}
834		}
835	}
836	steps = 0;
837	if (cmd->scan_begin_src == TRIG_TIMER) {
838		printk(KERN_ERR "comedi%d: usbduxfast: "
839		       "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
840		up(&udfs->sem);
841		return -EINVAL;
842	}
843	if (cmd->convert_src == TRIG_TIMER)
844		steps = (cmd->convert_arg * 30) / 1000;
845
846	if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
847		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, "
848		       "scan_begin_arg=%d. Not properly tested by cmdtest?\n",
849		       dev->minor, steps, cmd->scan_begin_arg);
850		up(&udfs->sem);
851		return -EINVAL;
852	}
853	if (steps > MAX_SAMPLING_PERIOD) {
854		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate "
855		       "too low.\n", dev->minor);
856		up(&udfs->sem);
857		return -EINVAL;
858	}
859	if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
860		&& (cmd->chanlist_len != 16)) {
861		printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only"
862		       " with 1 or 16 channels possible.\n", dev->minor);
863		up(&udfs->sem);
864		return -EINVAL;
865	}
866#ifdef CONFIG_COMEDI_DEBUG
867	printk(KERN_DEBUG "comedi%d: usbduxfast: steps=%ld, convert_arg=%u\n",
868	       dev->minor, steps, cmd->convert_arg);
869#endif
870
871	switch (cmd->chanlist_len) {
872	case 1:
873		/*
874		 * one channel
875		 */
876
877		if (CR_RANGE(cmd->chanlist[0]) > 0)
878			rngmask = 0xff - 0x04;
879		else
880			rngmask = 0xff;
881
882		/*
883		 * for external trigger: looping in this state until
884		 * the RDY0 pin becomes zero
885		 */
886
887		/* we loop here until ready has been set */
888		if (cmd->start_src == TRIG_EXT) {
889			/* branch back to state 0 */
890			udfs->dux_commands[LENBASE+0] = 0x01;
891			/* deceision state w/o data */
892			udfs->dux_commands[OPBASE+0] = 0x01;
893			udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask;
894			/* RDY0 = 0 */
895			udfs->dux_commands[LOGBASE+0] = 0x00;
896		} else {	/* we just proceed to state 1 */
897			udfs->dux_commands[LENBASE+0] = 1;
898			udfs->dux_commands[OPBASE+0] = 0;
899			udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask;
900			udfs->dux_commands[LOGBASE+0] = 0;
901		}
902
903		if (steps < MIN_SAMPLING_PERIOD) {
904			/* for fast single channel aqu without mux */
905			if (steps <= 1) {
906				/*
907				 * we just stay here at state 1 and rexecute
908				 * the same state this gives us 30MHz sampling
909				 * rate
910				 */
911
912				/* branch back to state 1 */
913				udfs->dux_commands[LENBASE+1] = 0x89;
914				/* deceision state with data */
915				udfs->dux_commands[OPBASE+1] = 0x03;
916				udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask;
917				/* doesn't matter */
918				udfs->dux_commands[LOGBASE+1] = 0xFF;
919			} else {
920				/*
921				 * we loop through two states: data and delay
922				 * max rate is 15MHz
923				 */
924				udfs->dux_commands[LENBASE+1] = steps - 1;
925				/* data */
926				udfs->dux_commands[OPBASE+1] = 0x02;
927				udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask;
928				/* doesn't matter */
929				udfs->dux_commands[LOGBASE+1] = 0;
930				/* branch back to state 1 */
931				udfs->dux_commands[LENBASE+2] = 0x09;
932				/* deceision state w/o data */
933				udfs->dux_commands[OPBASE+2] = 0x01;
934				udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask;
935				/* doesn't matter */
936				udfs->dux_commands[LOGBASE+2] = 0xFF;
937			}
938		} else {
939			/*
940			 * we loop through 3 states: 2x delay and 1x data
941			 * this gives a min sampling rate of 60kHz
942			 */
943
944			/* we have 1 state with duration 1 */
945			steps = steps - 1;
946
947			/* do the first part of the delay */
948			udfs->dux_commands[LENBASE+1] = steps / 2;
949			udfs->dux_commands[OPBASE+1] = 0;
950			udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask;
951			udfs->dux_commands[LOGBASE+1] = 0;
952
953			/* and the second part */
954			udfs->dux_commands[LENBASE+2] = steps - steps / 2;
955			udfs->dux_commands[OPBASE+2] = 0;
956			udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask;
957			udfs->dux_commands[LOGBASE+2] = 0;
958
959			/* get the data and branch back */
960
961			/* branch back to state 1 */
962			udfs->dux_commands[LENBASE+3] = 0x09;
963			/* deceision state w data */
964			udfs->dux_commands[OPBASE+3] = 0x03;
965			udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask;
966			/* doesn't matter */
967			udfs->dux_commands[LOGBASE+3] = 0xFF;
968		}
969		break;
970
971	case 2:
972		/*
973		 * two channels
974		 * commit data to the FIFO
975		 */
976
977		if (CR_RANGE(cmd->chanlist[0]) > 0)
978			rngmask = 0xff - 0x04;
979		else
980			rngmask = 0xff;
981
982		udfs->dux_commands[LENBASE+0] = 1;
983		/* data */
984		udfs->dux_commands[OPBASE+0] = 0x02;
985		udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask;
986		udfs->dux_commands[LOGBASE+0] = 0;
987
988		/* we have 1 state with duration 1: state 0 */
989		steps_tmp = steps - 1;
990
991		if (CR_RANGE(cmd->chanlist[1]) > 0)
992			rngmask = 0xff - 0x04;
993		else
994			rngmask = 0xff;
995
996		/* do the first part of the delay */
997		udfs->dux_commands[LENBASE+1] = steps_tmp / 2;
998		udfs->dux_commands[OPBASE+1] = 0;
999		/* count */
1000		udfs->dux_commands[OUTBASE+1] = 0xFE & rngmask;
1001		udfs->dux_commands[LOGBASE+1] = 0;
1002
1003		/* and the second part */
1004		udfs->dux_commands[LENBASE+2] = steps_tmp - steps_tmp / 2;
1005		udfs->dux_commands[OPBASE+2] = 0;
1006		udfs->dux_commands[OUTBASE+2] = 0xFF & rngmask;
1007		udfs->dux_commands[LOGBASE+2] = 0;
1008
1009		udfs->dux_commands[LENBASE+3] = 1;
1010		/* data */
1011		udfs->dux_commands[OPBASE+3] = 0x02;
1012		udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask;
1013		udfs->dux_commands[LOGBASE+3] = 0;
1014
1015		/*
1016		 * we have 2 states with duration 1: step 6 and
1017		 * the IDLE state
1018		 */
1019		steps_tmp = steps - 2;
1020
1021		if (CR_RANGE(cmd->chanlist[0]) > 0)
1022			rngmask = 0xff - 0x04;
1023		else
1024			rngmask = 0xff;
1025
1026		/* do the first part of the delay */
1027		udfs->dux_commands[LENBASE+4] = steps_tmp / 2;
1028		udfs->dux_commands[OPBASE+4] = 0;
1029		/* reset */
1030		udfs->dux_commands[OUTBASE+4] = (0xFF - 0x02) & rngmask;
1031		udfs->dux_commands[LOGBASE+4] = 0;
1032
1033		/* and the second part */
1034		udfs->dux_commands[LENBASE+5] = steps_tmp - steps_tmp / 2;
1035		udfs->dux_commands[OPBASE+5] = 0;
1036		udfs->dux_commands[OUTBASE+5] = 0xFF & rngmask;
1037		udfs->dux_commands[LOGBASE+5] = 0;
1038
1039		udfs->dux_commands[LENBASE+6] = 1;
1040		udfs->dux_commands[OPBASE+6] = 0;
1041		udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask;
1042		udfs->dux_commands[LOGBASE+6] = 0;
1043		break;
1044
1045	case 3:
1046		/*
1047		 * three channels
1048		 */
1049		for (j = 0; j < 1; j++) {
1050			if (CR_RANGE(cmd->chanlist[j]) > 0)
1051				rngmask = 0xff - 0x04;
1052			else
1053				rngmask = 0xff;
1054			/*
1055			 * commit data to the FIFO and do the first part
1056			 * of the delay
1057			 */
1058			udfs->dux_commands[LENBASE+j*2] = steps / 2;
1059			/* data */
1060			udfs->dux_commands[OPBASE+j*2] = 0x02;
1061			/* no change */
1062			udfs->dux_commands[OUTBASE+j*2] = 0xFF & rngmask;
1063			udfs->dux_commands[LOGBASE+j*2] = 0;
1064
1065			if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
1066				rngmask = 0xff - 0x04;
1067			else
1068				rngmask = 0xff;
1069
1070			/* do the second part of the delay */
1071			udfs->dux_commands[LENBASE+j*2+1] = steps - steps / 2;
1072			/* no data */
1073			udfs->dux_commands[OPBASE+j*2+1] = 0;
1074			/* count */
1075			udfs->dux_commands[OUTBASE+j*2+1] = 0xFE & rngmask;
1076			udfs->dux_commands[LOGBASE+j*2+1] = 0;
1077		}
1078
1079		/* 2 steps with duration 1: the idele step and step 6: */
1080		steps_tmp = steps - 2;
1081
1082		/* commit data to the FIFO and do the first part of the delay */
1083		udfs->dux_commands[LENBASE+4] = steps_tmp / 2;
1084		/* data */
1085		udfs->dux_commands[OPBASE+4] = 0x02;
1086		udfs->dux_commands[OUTBASE+4] = 0xFF & rngmask;
1087		udfs->dux_commands[LOGBASE+4] = 0;
1088
1089		if (CR_RANGE(cmd->chanlist[0]) > 0)
1090			rngmask = 0xff - 0x04;
1091		else
1092			rngmask = 0xff;
1093
1094		/* do the second part of the delay */
1095		udfs->dux_commands[LENBASE+5] = steps_tmp - steps_tmp / 2;
1096		/* no data */
1097		udfs->dux_commands[OPBASE+5] = 0;
1098		/* reset */
1099		udfs->dux_commands[OUTBASE+5] = (0xFF - 0x02) & rngmask;
1100		udfs->dux_commands[LOGBASE+5] = 0;
1101
1102		udfs->dux_commands[LENBASE+6] = 1;
1103		udfs->dux_commands[OPBASE+6] = 0;
1104		udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask;
1105		udfs->dux_commands[LOGBASE+6] = 0;
1106
1107	case 16:
1108		if (CR_RANGE(cmd->chanlist[0]) > 0)
1109			rngmask = 0xff - 0x04;
1110		else
1111			rngmask = 0xff;
1112
1113		if (cmd->start_src == TRIG_EXT) {
1114			/*
1115			 * we loop here until ready has been set
1116			 */
1117
1118			/* branch back to state 0 */
1119			udfs->dux_commands[LENBASE+0] = 0x01;
1120			/* deceision state w/o data */
1121			udfs->dux_commands[OPBASE+0] = 0x01;
1122			/* reset */
1123			udfs->dux_commands[OUTBASE+0] = (0xFF-0x02) & rngmask;
1124			/* RDY0 = 0 */
1125			udfs->dux_commands[LOGBASE+0] = 0x00;
1126		} else {
1127			/*
1128			 * we just proceed to state 1
1129			 */
1130
1131			/* 30us reset pulse */
1132			udfs->dux_commands[LENBASE+0] = 255;
1133			udfs->dux_commands[OPBASE+0] = 0;
1134			/* reset */
1135			udfs->dux_commands[OUTBASE+0] = (0xFF-0x02) & rngmask;
1136			udfs->dux_commands[LOGBASE+0] = 0;
1137		}
1138
1139		/* commit data to the FIFO */
1140		udfs->dux_commands[LENBASE+1] = 1;
1141		/* data */
1142		udfs->dux_commands[OPBASE+1] = 0x02;
1143		udfs->dux_commands[OUTBASE+1] = 0xFF & rngmask;
1144		udfs->dux_commands[LOGBASE+1] = 0;
1145
1146		/* we have 2 states with duration 1 */
1147		steps = steps - 2;
1148
1149		/* do the first part of the delay */
1150		udfs->dux_commands[LENBASE+2] = steps / 2;
1151		udfs->dux_commands[OPBASE+2] = 0;
1152		udfs->dux_commands[OUTBASE+2] = 0xFE & rngmask;
1153		udfs->dux_commands[LOGBASE+2] = 0;
1154
1155		/* and the second part */
1156		udfs->dux_commands[LENBASE+3] = steps - steps / 2;
1157		udfs->dux_commands[OPBASE+3] = 0;
1158		udfs->dux_commands[OUTBASE+3] = 0xFF & rngmask;
1159		udfs->dux_commands[LOGBASE+3] = 0;
1160
1161		/* branch back to state 1 */
1162		udfs->dux_commands[LENBASE+4] = 0x09;
1163		/* deceision state w/o data */
1164		udfs->dux_commands[OPBASE+4] = 0x01;
1165		udfs->dux_commands[OUTBASE+4] = 0xFF & rngmask;
1166		/* doesn't matter */
1167		udfs->dux_commands[LOGBASE+4] = 0xFF;
1168
1169		break;
1170
1171	default:
1172		printk(KERN_ERR "comedi %d: unsupported combination of "
1173		       "channels\n", dev->minor);
1174		up(&udfs->sem);
1175		return -EFAULT;
1176	}
1177
1178#ifdef CONFIG_COMEDI_DEBUG
1179	printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
1180	       dev->minor);
1181#endif
1182	/* 0 means that the AD commands are sent */
1183	result = send_dux_commands(udfs, SENDADCOMMANDS);
1184	if (result < 0) {
1185		printk(KERN_ERR "comedi%d: adc command could not be submitted."
1186		       "Aborting...\n", dev->minor);
1187		up(&udfs->sem);
1188		return result;
1189	}
1190	if (cmd->stop_src == TRIG_COUNT) {
1191		udfs->ai_sample_count =	cmd->stop_arg * cmd->scan_end_arg;
1192		if (udfs->ai_sample_count < 1) {
1193			printk(KERN_ERR "comedi%d: "
1194			       "(cmd->stop_arg)*(cmd->scan_end_arg)<1, "
1195			       "aborting.\n", dev->minor);
1196			up(&udfs->sem);
1197			return -EFAULT;
1198		}
1199		udfs->ai_continous = 0;
1200	} else {
1201		/* continous aquisition */
1202		udfs->ai_continous = 1;
1203		udfs->ai_sample_count = 0;
1204	}
1205
1206	if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
1207		/* enable this acquisition operation */
1208		udfs->ai_cmd_running = 1;
1209		ret = usbduxfastsub_submit_InURBs(udfs);
1210		if (ret < 0) {
1211			udfs->ai_cmd_running = 0;
1212			/* fixme: unlink here?? */
1213			up(&udfs->sem);
1214			return ret;
1215		}
1216		s->async->inttrig = NULL;
1217	} else {
1218		/*
1219		 * TRIG_INT
1220		 * don't enable the acquision operation
1221		 * wait for an internal signal
1222		 */
1223		s->async->inttrig = usbduxfast_ai_inttrig;
1224	}
1225	up(&udfs->sem);
1226
1227	return 0;
1228}
1229
1230/*
1231 * Mode 0 is used to get a single conversion on demand.
1232 */
1233static int usbduxfast_ai_insn_read(comedi_device *dev,
1234	comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
1235{
1236	int i, j, n, actual_length;
1237	int chan, range, rngmask;
1238	int err;
1239	struct usbduxfastsub_s *udfs;
1240
1241	udfs = dev->private;
1242	if (!udfs) {
1243		printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n",
1244		       dev->minor);
1245		return -ENODEV;
1246	}
1247#ifdef CONFIG_COMEDI_DEBUG
1248	printk(KERN_DEBUG "comedi%d: ai_insn_read, insn->n=%d, "
1249	       "insn->subdev=%d\n", dev->minor, insn->n, insn->subdev);
1250#endif
1251	down(&udfs->sem);
1252	if (!udfs->probed) {
1253		up(&udfs->sem);
1254		return -ENODEV;
1255	}
1256	if (udfs->ai_cmd_running) {
1257		printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async "
1258		       "Command is running.\n", dev->minor);
1259		up(&udfs->sem);
1260		return -EBUSY;
1261	}
1262	/* sample one channel */
1263	chan = CR_CHAN(insn->chanspec);
1264	range = CR_RANGE(insn->chanspec);
1265	/* set command for the first channel */
1266
1267	if (range > 0)
1268		rngmask = 0xff - 0x04;
1269	else
1270		rngmask = 0xff;
1271
1272	/* commit data to the FIFO */
1273	udfs->dux_commands[LENBASE+0] = 1;
1274	/* data */
1275	udfs->dux_commands[OPBASE+0] = 0x02;
1276	udfs->dux_commands[OUTBASE+0] = 0xFF & rngmask;
1277	udfs->dux_commands[LOGBASE+0] = 0;
1278
1279	/* do the first part of the delay */
1280	udfs->dux_commands[LENBASE+1] = 12;
1281	udfs->dux_commands[OPBASE+1] = 0;
1282	udfs->dux_commands[OUTBASE+1] = 0xFE & rngmask;
1283	udfs->dux_commands[LOGBASE+1] = 0;
1284
1285	udfs->dux_commands[LENBASE+2] = 1;
1286	udfs->dux_commands[OPBASE+2] = 0;
1287	udfs->dux_commands[OUTBASE+2] = 0xFE & rngmask;
1288	udfs->dux_commands[LOGBASE+2] = 0;
1289
1290	udfs->dux_commands[LENBASE+3] = 1;
1291	udfs->dux_commands[OPBASE+3] = 0;
1292	udfs->dux_commands[OUTBASE+3] = 0xFE & rngmask;
1293	udfs->dux_commands[LOGBASE+3] = 0;
1294
1295	udfs->dux_commands[LENBASE+4] = 1;
1296	udfs->dux_commands[OPBASE+4] = 0;
1297	udfs->dux_commands[OUTBASE+4] = 0xFE & rngmask;
1298	udfs->dux_commands[LOGBASE+4] = 0;
1299
1300	/* second part */
1301	udfs->dux_commands[LENBASE+5] = 12;
1302	udfs->dux_commands[OPBASE+5] = 0;
1303	udfs->dux_commands[OUTBASE+5] = 0xFF & rngmask;
1304	udfs->dux_commands[LOGBASE+5] = 0;
1305
1306	udfs->dux_commands[LENBASE+6] = 1;
1307	udfs->dux_commands[OPBASE+6] = 0;
1308	udfs->dux_commands[OUTBASE+6] = 0xFF & rngmask;
1309	udfs->dux_commands[LOGBASE+0] = 0;
1310
1311#ifdef CONFIG_COMEDI_DEBUG
1312	printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n",
1313	       dev->minor);
1314#endif
1315	/* 0 means that the AD commands are sent */
1316	err = send_dux_commands(udfs, SENDADCOMMANDS);
1317	if (err < 0) {
1318		printk(KERN_ERR "comedi%d: adc command could not be submitted."
1319		       "Aborting...\n", dev->minor);
1320		up(&udfs->sem);
1321		return err;
1322	}
1323#ifdef CONFIG_COMEDI_DEBUG
1324	printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: "
1325	       "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context,
1326	       udfs->urbIn->dev);
1327#endif
1328	for (i = 0; i < PACKETS_TO_IGNORE; i++) {
1329		err = usb_bulk_msg(udfs->usbdev,
1330				   usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
1331				   udfs->transfer_buffer, SIZEINBUF,
1332				   &actual_length, 10000);
1333		if (err < 0) {
1334			printk(KERN_ERR "comedi%d: insn timeout. No data.\n",
1335				dev->minor);
1336			up(&udfs->sem);
1337			return err;
1338		}
1339	}
1340	/* data points */
1341	for (i = 0; i < insn->n;) {
1342		err = usb_bulk_msg(udfs->usbdev,
1343				   usb_rcvbulkpipe(udfs->usbdev, BULKINEP),
1344				   udfs->transfer_buffer, SIZEINBUF,
1345				   &actual_length, 10000);
1346		if (err < 0) {
1347			printk(KERN_ERR "comedi%d: insn data error: %d\n",
1348				dev->minor, err);
1349			up(&udfs->sem);
1350			return err;
1351		}
1352		n = actual_length / sizeof(uint16_t);
1353		if ((n % 16) != 0) {
1354			printk(KERN_ERR "comedi%d: insn data packet "
1355			       "corrupted.\n", dev->minor);
1356			up(&udfs->sem);
1357			return -EINVAL;
1358		}
1359		for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
1360			data[i] = ((uint16_t *) (udfs->transfer_buffer))[j];
1361			i++;
1362		}
1363	}
1364	up(&udfs->sem);
1365	return i;
1366}
1367
1368static unsigned hex2unsigned(char *h)
1369{
1370	unsigned hi, lo;
1371
1372	if (h[0] > '9')
1373		hi = h[0] - 'A' + 0x0a;
1374	else
1375		hi = h[0] - '0';
1376
1377	if (h[1] > '9')
1378		lo = h[1] - 'A' + 0x0a;
1379	else
1380		lo = h[1] - '0';
1381
1382	return hi * 0x10 + lo;
1383}
1384
1385/* for FX2 */
1386#define FIRMWARE_MAX_LEN 0x2000
1387
1388/*
1389 * taken from David Brownell's fxload and adjusted for this driver
1390 */
1391static int read_firmware(struct usbduxfastsub_s *udfs, const void *firmwarePtr,
1392			 long size)
1393{
1394	int i = 0;
1395	unsigned char *fp = (char *)firmwarePtr;
1396	unsigned char *firmwareBinary;
1397	int res = 0;
1398	int maxAddr = 0;
1399
1400	firmwareBinary = kmalloc(FIRMWARE_MAX_LEN, GFP_KERNEL);
1401	if (!firmwareBinary) {
1402		printk(KERN_ERR "comedi_: usbduxfast: mem alloc for firmware "
1403		       " failed\n");
1404		return -ENOMEM;
1405	}
1406
1407	for (;;) {
1408		char buf[256], *cp;
1409		char type;
1410		int len;
1411		int idx, off;
1412		int j = 0;
1413
1414		/* get one line */
1415		while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) {
1416			buf[j] = fp[i];
1417			i++;
1418			j++;
1419			if (j >= sizeof(buf)) {
1420				printk(KERN_ERR "comedi_: usbduxfast: bogus "
1421				       "firmware file!\n");
1422				kfree(firmwareBinary);
1423				return -1;
1424			}
1425		}
1426		/* get rid of LF/CR/... */
1427		while ((i < size) && ((fp[i] == 13) || (fp[i] == 10)
1428					|| (fp[i] == 0)))
1429			i++;
1430
1431		buf[j] = 0;
1432		/* printk("comedi_: buf=%s\n",buf); */
1433
1434		/*
1435		 * EXTENSION: "# comment-till-end-of-line",
1436		 * for copyrights etc
1437		 */
1438		if (buf[0] == '#')
1439			continue;
1440
1441		if (buf[0] != ':') {
1442			printk(KERN_ERR "comedi_: usbduxfast: upload: not an "
1443			       "ihex record: %s", buf);
1444			kfree(firmwareBinary);
1445			return -EFAULT;
1446		}
1447
1448		/* Read the length field (up to 16 bytes) */
1449		len = hex2unsigned(buf + 1);
1450
1451		/* Read the target offset */
1452		off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5);
1453
1454		if ((off + len) > maxAddr)
1455			maxAddr = off + len;
1456
1457		if (maxAddr >= FIRMWARE_MAX_LEN) {
1458			printk(KERN_ERR "comedi_: usbduxfast: firmware upload "
1459			       "goes beyond FX2 RAM boundaries.");
1460			kfree(firmwareBinary);
1461			return -EFAULT;
1462		}
1463		/* printk("comedi_: usbduxfast: off=%x, len=%x:",off,len); */
1464
1465		/* Read the record type */
1466		type = hex2unsigned(buf + 7);
1467
1468		/* If this is an EOF record, then make it so. */
1469		if (type == 1)
1470			break;
1471
1472		if (type != 0) {
1473			printk(KERN_ERR "comedi_: usbduxfast: unsupported "
1474			       "record type: %u\n", type);
1475			kfree(firmwareBinary);
1476			return -EFAULT;
1477		}
1478
1479		for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) {
1480			firmwareBinary[idx + off] = hex2unsigned(cp);
1481			/* printk("%02x ",firmwareBinary[idx+off]); */
1482		}
1483
1484		/* printk("\n"); */
1485
1486		if (i >= size) {
1487			printk(KERN_ERR "comedi_: usbduxfast: unexpected end "
1488			       "of hex file\n");
1489			break;
1490		}
1491
1492	}
1493	res = firmwareUpload(udfs, firmwareBinary, maxAddr + 1);
1494	kfree(firmwareBinary);
1495	return res;
1496}
1497
1498static void tidy_up(struct usbduxfastsub_s *udfs)
1499{
1500#ifdef CONFIG_COMEDI_DEBUG
1501	printk(KERN_DEBUG "comedi_: usbduxfast: tiding up\n");
1502#endif
1503
1504	if (!udfs)
1505		return;
1506
1507	/* shows the usb subsystem that the driver is down */
1508	if (udfs->interface)
1509		usb_set_intfdata(udfs->interface, NULL);
1510
1511	udfs->probed = 0;
1512
1513	if (udfs->urbIn) {
1514		/* waits until a running transfer is over */
1515		usb_kill_urb(udfs->urbIn);
1516
1517		kfree(udfs->transfer_buffer);
1518		udfs->transfer_buffer = NULL;
1519
1520		usb_free_urb(udfs->urbIn);
1521		udfs->urbIn = NULL;
1522	}
1523
1524	kfree(udfs->insnBuffer);
1525	udfs->insnBuffer = NULL;
1526
1527	kfree(udfs->dux_commands);
1528	udfs->dux_commands = NULL;
1529
1530	udfs->ai_cmd_running = 0;
1531}
1532
1533static void usbduxfast_firmware_request_complete_handler(const struct firmware *fw,
1534							 void *context)
1535{
1536	struct usbduxfastsub_s *usbduxfastsub_tmp = context;
1537	struct usb_device *usbdev = usbduxfastsub_tmp->usbdev;
1538	int ret;
1539
1540	if (fw == NULL)
1541		return;
1542
1543	/*
1544	 * we need to upload the firmware here because fw will be
1545	 * freed once we've left this function
1546	 */
1547	ret = read_firmware(usbduxfastsub_tmp, fw->data, fw->size);
1548
1549	if (ret) {
1550		dev_err(&usbdev->dev,
1551			"Could not upload firmware (err=%d)\n",
1552			ret);
1553		return;
1554	}
1555
1556	comedi_usb_auto_config(usbdev, BOARDNAME);
1557}
1558
1559/*
1560 * allocate memory for the urbs and initialise them
1561 */
1562static int usbduxfastsub_probe(struct usb_interface *uinterf,
1563	const struct usb_device_id *id)
1564{
1565	struct usb_device *udev = interface_to_usbdev(uinterf);
1566	int i;
1567	int index;
1568	int ret;
1569
1570	if (udev->speed != USB_SPEED_HIGH) {
1571		printk(KERN_ERR "comedi_: usbduxfast_: This driver needs"
1572		       "USB 2.0 to operate. Aborting...\n");
1573		return -ENODEV;
1574	}
1575#ifdef CONFIG_COMEDI_DEBUG
1576	printk(KERN_DEBUG "comedi_: usbduxfast_: finding a free structure for "
1577	       "the usb-device\n");
1578#endif
1579	down(&start_stop_sem);
1580	/* look for a free place in the usbduxfast array */
1581	index = -1;
1582	for (i = 0; i < NUMUSBDUXFAST; i++) {
1583		if (!usbduxfastsub[i].probed) {
1584			index = i;
1585			break;
1586		}
1587	}
1588
1589	/* no more space */
1590	if (index == -1) {
1591		printk(KERN_ERR "Too many usbduxfast-devices connected.\n");
1592		up(&start_stop_sem);
1593		return -EMFILE;
1594	}
1595#ifdef CONFIG_COMEDI_DEBUG
1596	printk(KERN_DEBUG "comedi_: usbduxfast: usbduxfastsub[%d] is ready to "
1597	       "connect to comedi.\n", index);
1598#endif
1599
1600	init_MUTEX(&(usbduxfastsub[index].sem));
1601	/* save a pointer to the usb device */
1602	usbduxfastsub[index].usbdev = udev;
1603
1604	/* save the interface itself */
1605	usbduxfastsub[index].interface = uinterf;
1606	/* get the interface number from the interface */
1607	usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
1608	/*
1609	 * hand the private data over to the usb subsystem
1610	 * will be needed for disconnect
1611	 */
1612	usb_set_intfdata(uinterf, &(usbduxfastsub[index]));
1613
1614#ifdef CONFIG_COMEDI_DEBUG
1615	printk(KERN_DEBUG "comedi_: usbduxfast: ifnum=%d\n",
1616	       usbduxfastsub[index].ifnum);
1617#endif
1618	/* create space for the commands going to the usb device */
1619	usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
1620						    GFP_KERNEL);
1621	if (!usbduxfastsub[index].dux_commands) {
1622		printk(KERN_ERR "comedi_: usbduxfast: error alloc space for "
1623		       "dac commands\n");
1624		tidy_up(&(usbduxfastsub[index]));
1625		up(&start_stop_sem);
1626		return -ENOMEM;
1627	}
1628	/* create space of the instruction buffer */
1629	usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
1630	if (!usbduxfastsub[index].insnBuffer) {
1631		printk(KERN_ERR "comedi_: usbduxfast: could not alloc space "
1632		       "for insnBuffer\n");
1633		tidy_up(&(usbduxfastsub[index]));
1634		up(&start_stop_sem);
1635		return -ENOMEM;
1636	}
1637	/* setting to alternate setting 1: enabling bulk ep */
1638	i = usb_set_interface(usbduxfastsub[index].usbdev,
1639		usbduxfastsub[index].ifnum, 1);
1640	if (i < 0) {
1641		printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to "
1642		       "alternate setting 1.\n", index);
1643		tidy_up(&(usbduxfastsub[index]));
1644		up(&start_stop_sem);
1645		return -ENODEV;
1646	}
1647	usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
1648	if (!usbduxfastsub[index].urbIn) {
1649		printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc."
1650		       "urb\n", index);
1651		tidy_up(&(usbduxfastsub[index]));
1652		up(&start_stop_sem);
1653		return -ENOMEM;
1654	}
1655	usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
1656	if (!usbduxfastsub[index].transfer_buffer) {
1657		printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. "
1658		       "transb.\n", index);
1659		tidy_up(&(usbduxfastsub[index]));
1660		up(&start_stop_sem);
1661		return -ENOMEM;
1662	}
1663	/* we've reached the bottom of the function */
1664	usbduxfastsub[index].probed = 1;
1665	up(&start_stop_sem);
1666
1667	ret = request_firmware_nowait(THIS_MODULE,
1668				      FW_ACTION_HOTPLUG,
1669				      "usbduxfast_firmware.hex",
1670				      &udev->dev,
1671				      usbduxfastsub + index,
1672				      usbduxfast_firmware_request_complete_handler);
1673
1674	if (ret) {
1675		dev_err(&udev->dev, "could not load firmware (err=%d)\n",
1676			ret);
1677		return ret;
1678	}
1679
1680	printk(KERN_INFO "comedi_: usbduxfast%d has been successfully "
1681	       "initialized.\n", index);
1682	/* success */
1683	return 0;
1684}
1685
1686static void usbduxfastsub_disconnect(struct usb_interface *intf)
1687{
1688	struct usbduxfastsub_s *udfs = usb_get_intfdata(intf);
1689	struct usb_device *udev = interface_to_usbdev(intf);
1690
1691	if (!udfs) {
1692		printk(KERN_ERR "comedi_: usbduxfast: disconnect called with "
1693		       "null pointer.\n");
1694		return;
1695	}
1696	if (udfs->usbdev != udev) {
1697		printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong "
1698		       "ptr!!!\n");
1699		return;
1700	}
1701
1702	comedi_usb_auto_unconfig(udev);
1703
1704	down(&start_stop_sem);
1705	down(&udfs->sem);
1706	tidy_up(udfs);
1707	up(&udfs->sem);
1708	up(&start_stop_sem);
1709
1710#ifdef CONFIG_COMEDI_DEBUG
1711	printk(KERN_DEBUG "comedi_: usbduxfast: disconnected from the usb\n");
1712#endif
1713}
1714
1715/*
1716 * is called when comedi-config is called
1717 */
1718static int usbduxfast_attach(comedi_device *dev, comedi_devconfig *it)
1719{
1720	int ret;
1721	int index;
1722	int i;
1723	comedi_subdevice *s = NULL;
1724	dev->private = NULL;
1725
1726	down(&start_stop_sem);
1727	/*
1728	 * find a valid device which has been detected by the
1729	 * probe function of the usb
1730	 */
1731	index = -1;
1732	for (i = 0; i < NUMUSBDUXFAST; i++) {
1733		if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) {
1734			index = i;
1735			break;
1736		}
1737	}
1738
1739	if (index < 0) {
1740		printk(KERN_ERR "comedi%d: usbduxfast: error: attach failed, "
1741		       "no usbduxfast devs connected to the usb bus.\n",
1742		       dev->minor);
1743		up(&start_stop_sem);
1744		return -ENODEV;
1745	}
1746
1747	down(&(usbduxfastsub[index].sem));
1748	/* pointer back to the corresponding comedi device */
1749	usbduxfastsub[index].comedidev = dev;
1750
1751	/* trying to upload the firmware into the chip */
1752	if (comedi_aux_data(it->options, 0) &&
1753	    it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
1754		read_firmware(&usbduxfastsub[index],
1755			      comedi_aux_data(it->options, 0),
1756			      it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
1757	}
1758
1759	dev->board_name = BOARDNAME;
1760
1761	/* set number of subdevices */
1762	dev->n_subdevices = N_SUBDEVICES;
1763
1764	/* allocate space for the subdevices */
1765	ret = alloc_subdevices(dev, N_SUBDEVICES);
1766	if (ret < 0) {
1767		printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for "
1768		       "subdev\n", dev->minor);
1769		up(&(usbduxfastsub[index].sem));
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
1866/*
1867 * Table with the USB-devices: just now only testing IDs
1868 */
1869static struct usb_device_id usbduxfastsub_table[] = {
1870	/* { USB_DEVICE(0x4b4, 0x8613) }, testing */
1871	{ USB_DEVICE(0x13d8, 0x0010) },	/* real ID */
1872	{ USB_DEVICE(0x13d8, 0x0011) },	/* real ID */
1873	{ }			/* Terminating entry */
1874};
1875
1876MODULE_DEVICE_TABLE(usb, usbduxfastsub_table);
1877
1878/*
1879 * The usbduxfastsub-driver
1880 */
1881static struct usb_driver usbduxfastsub_driver = {
1882#ifdef COMEDI_HAVE_USB_DRIVER_OWNER
1883	.owner		= THIS_MODULE,
1884#endif
1885	.name		= BOARDNAME,
1886	.probe		= usbduxfastsub_probe,
1887	.disconnect	= usbduxfastsub_disconnect,
1888	.id_table	= usbduxfastsub_table
1889};
1890
1891/*
1892 * Can't use the nice macro as I have also to initialise the USB subsystem:
1893 * registering the usb-system _and_ the comedi-driver
1894 */
1895static int __init init_usbduxfast(void)
1896{
1897	printk(KERN_INFO
1898	       KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n");
1899	usb_register(&usbduxfastsub_driver);
1900	comedi_driver_register(&driver_usbduxfast);
1901	return 0;
1902}
1903
1904/*
1905 * deregistering the comedi driver and the usb-subsystem
1906 */
1907static void __exit exit_usbduxfast(void)
1908{
1909	comedi_driver_unregister(&driver_usbduxfast);
1910	usb_deregister(&usbduxfastsub_driver);
1911}
1912
1913module_init(init_usbduxfast);
1914module_exit(exit_usbduxfast);
1915
1916MODULE_AUTHOR(DRIVER_AUTHOR);
1917MODULE_DESCRIPTION(DRIVER_DESC);
1918MODULE_LICENSE("GPL");
1919