usbdux.c revision e54fb9c184a250fc80c48110ae42068bb0237a13
1#define DRIVER_VERSION "v2.1"
2#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
3#define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
4/*
5   comedi/drivers/usbdux.c
6   Copyright (C) 2003-2007 Bernd Porr, Bernd.Porr@f2s.com
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23/*
24Driver: usbdux
25Description: University of Stirling USB DAQ & INCITE Technology Limited
26Devices: [ITL] USB-DUX (usbdux.o)
27Author: Bernd Porr <BerndPorr@f2s.com>
28Updated: 25 Nov 2007
29Status: Testing
30Configuration options:
31  You have to upload firmware with the -i option. The
32  firmware is usually installed under /usr/share/usb or
33  /usr/local/share/usb or /lib/firmware.
34
35Connection scheme for the counter at the digital port:
36  0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
37  The sampling rate of the counter is approximately 500Hz.
38
39Please note that under USB2.0 the length of the channel list determines
40the max sampling rate. If you sample only one channel you get 8kHz
41sampling rate. If you sample two channels you get 4kHz and so on.
42*/
43/*
44 * I must give credit here to Chris Baugher who
45 * wrote the driver for AT-MIO-16d. I used some parts of this
46 * driver. I also must give credits to David Brownell
47 * who supported me with the USB development.
48 *
49 * Bernd Porr
50 *
51 *
52 * Revision history:
53 * 0.94: D/A output should work now with any channel list combinations
54 * 0.95: .owner commented out for kernel vers below 2.4.19
55 *       sanity checks in ai/ao_cmd
56 * 0.96: trying to get it working with 2.6, moved all memory alloc to comedi's attach final USB IDs
57 *       moved memory allocation completely to the corresponding comedi functions
58 *       firmware upload is by fxload and no longer by comedi (due to enumeration)
59 * 0.97: USB IDs received, adjusted table
60 * 0.98: SMP, locking, memroy alloc: moved all usb memory alloc
61 *       to the usb subsystem and moved all comedi related memory
62 *       alloc to comedi.
63 *       | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
64 * 0.99: USB 2.0: changed protocol to isochronous transfer
65 *                IRQ transfer is too buggy and too risky in 2.0
66 *                for the high speed ISO transfer is now a working version available
67 * 0.99b: Increased the iso transfer buffer for high sp.to 10 buffers. Some VIA
68 *        chipsets miss out IRQs. Deeper buffering is needed.
69 * 1.00: full USB 2.0 support for the A/D converter. Now: max 8kHz sampling rate.
70 *       Firmware vers 1.00 is needed for this.
71 *       Two 16 bit up/down/reset counter with a sampling rate of 1kHz
72 *       And loads of cleaning up, in particular streamlining the
73 *       bulk transfers.
74 * 1.1:  moved EP4 transfers to EP1 to make space for a PWM output on EP4
75 * 1.2:  added PWM suport via EP4
76 * 2.0:  PWM seems to be stable and is not interfering with the other functions
77 * 2.1:  changed PWM API
78 *
79 */
80
81/* generates loads of debug info */
82/* #define NOISY_DUX_DEBUGBUG */
83
84#include <linux/kernel.h>
85#include <linux/module.h>
86#include <linux/init.h>
87#include <linux/slab.h>
88#include <linux/input.h>
89#include <linux/usb.h>
90#include <linux/smp_lock.h>
91#include <linux/fcntl.h>
92#include <linux/compiler.h>
93
94#include "../comedidev.h"
95#include "../usb.h"
96
97#define BOARDNAME "usbdux"
98
99/* timeout for the USB-transfer */
100#define EZTIMEOUT 30
101
102/* constants for "firmware" upload and download */
103#define USBDUXSUB_FIRMWARE 0xA0
104#define VENDOR_DIR_IN  0xC0
105#define VENDOR_DIR_OUT 0x40
106
107/* internal adresses of the 8051 processor */
108#define USBDUXSUB_CPUCS 0xE600
109
110/*
111 * the minor device number, major is 180 only for debugging purposes and to
112 * upload special firmware (programming the eeprom etc) which is not compatible
113 * with the comedi framwork
114 */
115#define USBDUXSUB_MINOR 32
116
117/* max lenghth of the transfer-buffer for software upload */
118#define TB_LEN 0x2000
119
120/* Input endpoint number: ISO/IRQ */
121#define ISOINEP           6
122
123/* Output endpoint number: ISO/IRQ */
124#define ISOOUTEP          2
125
126/* This EP sends DUX commands to USBDUX */
127#define COMMAND_OUT_EP     1
128
129/* This EP receives the DUX commands from USBDUX */
130#define COMMAND_IN_EP        8
131
132/* Output endpoint for PWM */
133#define PWM_EP         4
134
135/* 300Hz max frequ under PWM */
136#define MIN_PWM_PERIOD  ((long)(1E9/300))
137
138/* Default PWM frequency */
139#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
140
141/* Number of channels */
142#define NUMCHANNELS       8
143
144/* Size of one A/D value */
145#define SIZEADIN          ((sizeof(int16_t)))
146
147/* Size of the input-buffer IN BYTES */
148/* Always multiple of 8 for 8 microframes which is needed in the highspeed mode */
149#define SIZEINBUF         ((8*SIZEADIN))
150
151/* 16 bytes. */
152#define SIZEINSNBUF       16
153
154/* Number of DA channels */
155#define NUMOUTCHANNELS    8
156
157/* size of one value for the D/A converter: channel and value */
158#define SIZEDAOUT          ((sizeof(int8_t)+sizeof(int16_t)))
159
160/*
161 * Size of the output-buffer in bytes
162 * Actually only the first 4 triplets are used but for the
163 * high speed mode we need to pad it to 8 (microframes).
164 */
165#define SIZEOUTBUF         ((8*SIZEDAOUT))
166
167/*
168 * Size of the buffer for the dux commands: just now max size is determined
169 * by the analogue out + command byte + panic bytes...
170 */
171#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
172
173/* Number of in-URBs which receive the data: min=2 */
174#define NUMOFINBUFFERSFULL     5
175
176/* Number of out-URBs which send the data: min=2 */
177#define NUMOFOUTBUFFERSFULL    5
178
179/* Number of in-URBs which receive the data: min=5 */
180/* must have more buffers due to buggy USB ctr */
181#define NUMOFINBUFFERSHIGH     10
182
183/* Number of out-URBs which send the data: min=5 */
184/* must have more buffers due to buggy USB ctr */
185#define NUMOFOUTBUFFERSHIGH    10
186
187/* Total number of usbdux devices */
188#define NUMUSBDUX             16
189
190/* Analogue in subdevice */
191#define SUBDEV_AD             0
192
193/* Analogue out subdevice */
194#define SUBDEV_DA             1
195
196/* Digital I/O */
197#define SUBDEV_DIO            2
198
199/* counter */
200#define SUBDEV_COUNTER        3
201
202/* timer aka pwm output */
203#define SUBDEV_PWM            4
204
205/* number of retries to get the right dux command */
206#define RETRIES 10
207
208/**************************************************/
209/* comedi constants */
210static const comedi_lrange range_usbdux_ai_range = { 4, {
211			BIP_RANGE(4.096),
212			BIP_RANGE(4.096 / 2),
213			UNI_RANGE(4.096),
214			UNI_RANGE(4.096 / 2)
215	}
216};
217
218static const comedi_lrange range_usbdux_ao_range = { 2, {
219			BIP_RANGE(4.096),
220			UNI_RANGE(4.096),
221	}
222};
223
224/*
225 * private structure of one subdevice
226 */
227
228/*
229 * This is the structure which holds all the data of
230 * this driver one sub device just now: A/D
231 */
232typedef struct {
233	/* attached? */
234	int attached;
235	/* is it associated with a subdevice? */
236	int probed;
237	/* pointer to the usb-device */
238	struct usb_device *usbdev;
239	/* actual number of in-buffers */
240	int numOfInBuffers;
241	/* actual number of out-buffers */
242	int numOfOutBuffers;
243	/* ISO-transfer handling: buffers */
244	struct urb **urbIn;
245	struct urb **urbOut;
246	/* pwm-transfer handling */
247	struct urb *urbPwm;
248	/* PWM period */
249	lsampl_t pwmPeriod;
250	/* PWM internal delay for the GPIF in the FX2 */
251	int8_t pwmDelay;
252	/* size of the PWM buffer which holds the bit pattern */
253	int sizePwmBuf;
254	/* input buffer for the ISO-transfer */
255	int16_t *inBuffer;
256	/* input buffer for single insn */
257	int16_t *insnBuffer;
258	/* output buffer for single DA outputs */
259	int16_t *outBuffer;
260	/* interface number */
261	int ifnum;
262	/* interface structure in 2.6 */
263	struct usb_interface *interface;
264	/* comedi device for the interrupt context */
265	comedi_device *comedidev;
266	/* is it USB_SPEED_HIGH or not? */
267	short int high_speed;
268	/* asynchronous command is running */
269	short int ai_cmd_running;
270	short int ao_cmd_running;
271	/* pwm is running */
272	short int pwm_cmd_running;
273	/* continous aquisition */
274	short int ai_continous;
275	short int ao_continous;
276	/* number of samples to aquire */
277	int ai_sample_count;
278	int ao_sample_count;
279	/* time between samples in units of the timer */
280	unsigned int ai_timer;
281	unsigned int ao_timer;
282	/* counter between aquisitions */
283	unsigned int ai_counter;
284	unsigned int ao_counter;
285	/* interval in frames/uframes */
286	unsigned int ai_interval;
287	/* D/A commands */
288	int8_t *dac_commands;
289	/* commands */
290	int8_t *dux_commands;
291	struct semaphore sem;
292} usbduxsub_t;
293
294/*
295 * The pointer to the private usb-data of the driver is also the private data
296 * for the comedi-device.  This has to be global as the usb subsystem needs
297 * global variables. The other reason is that this structure must be there
298 * _before_ any comedi command is issued. The usb subsystem must be initialised
299 * before comedi can access it.
300 */
301static usbduxsub_t usbduxsub[NUMUSBDUX];
302
303static DECLARE_MUTEX(start_stop_sem);
304
305/*
306 * Stops the data acquision
307 * It should be safe to call this function from any context
308 */
309static int usbduxsub_unlink_InURBs(usbduxsub_t *usbduxsub_tmp)
310{
311	int i = 0;
312	int err = 0;
313
314	if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
315		for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
316			if (usbduxsub_tmp->urbIn[i]) {
317				/* We wait here until all transfers have been
318				 * cancelled. */
319				usb_kill_urb(usbduxsub_tmp->urbIn[i]);
320			}
321#ifdef NOISY_DUX_DEBUGBUG
322			printk("comedi: usbdux: unlinked InURB %d, err=%d\n",
323				i, err);
324#endif
325		}
326	}
327	return err;
328}
329
330/*
331 * This will stop a running acquisition operation
332 * Is called from within this driver from both the
333 * interrupt context and from comedi
334 */
335static int usbdux_ai_stop(usbduxsub_t *this_usbduxsub, int do_unlink)
336{
337	int ret = 0;
338
339	if (!this_usbduxsub) {
340		printk("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
341		return -EFAULT;
342	}
343#ifdef NOISY_DUX_DEBUGBUG
344	printk("comedi: usbdux_ai_stop\n");
345#endif
346
347	if (do_unlink) {
348		/* stop aquistion */
349		ret = usbduxsub_unlink_InURBs(this_usbduxsub);
350	}
351
352	this_usbduxsub->ai_cmd_running = 0;
353
354	return ret;
355}
356
357/*
358 * This will cancel a running acquisition operation.
359 * This is called by comedi but never from inside the driver.
360 */
361static int usbdux_ai_cancel(comedi_device * dev, comedi_subdevice * s)
362{
363	usbduxsub_t *this_usbduxsub;
364	int res = 0;
365
366	/* force unlink of all urbs */
367#ifdef NOISY_DUX_DEBUGBUG
368	printk("comedi: usbdux_ai_cancel\n");
369#endif
370	this_usbduxsub = dev->private;
371	if (!this_usbduxsub) {
372		printk("comedi: usbdux_ai_cancel: this_usbduxsub=NULL\n");
373		return -EFAULT;
374	}
375	/* prevent other CPUs from submitting new commands just now */
376	down(&this_usbduxsub->sem);
377	if (!(this_usbduxsub->probed)) {
378		up(&this_usbduxsub->sem);
379		return -ENODEV;
380	}
381	/* unlink only if the urb really has been submitted */
382	res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
383	up(&this_usbduxsub->sem);
384	return res;
385}
386
387/* analogue IN - interrupt service routine */
388static void usbduxsub_ai_IsocIrq(struct urb *urb)
389{
390	int i, err, n;
391	usbduxsub_t *this_usbduxsub;
392	comedi_device *this_comedidev;
393	comedi_subdevice *s;
394
395	/* sanity checks */
396	/* is the urb there? */
397	if (!urb) {
398		printk("comedi_: usbdux_: ao int-handler called with urb=NULL!\n");
399		return;
400	}
401	/* the context variable points to the subdevice */
402	this_comedidev = urb->context;
403	if (unlikely(!this_comedidev)) {
404		printk("comedi_: usbdux_: BUG! urb context is a NULL pointer!\n");
405		return;
406	}
407	/* the private structure of the subdevice is usbduxsub_t */
408	this_usbduxsub = this_comedidev->private;
409	if (unlikely(!this_usbduxsub)) {
410		printk("comedi_: usbdux_: BUG! private of comedi subdev is a NULL pointer!\n");
411		return;
412	}
413	/* subdevice which is the AD converter */
414	s = this_comedidev->subdevices + SUBDEV_AD;
415
416	/* first we test if something unusual has just happened */
417	switch (urb->status) {
418	case 0:
419		/* copy the result in the transfer buffer */
420		memcpy(this_usbduxsub->inBuffer,
421			urb->transfer_buffer, SIZEINBUF);
422		break;
423	case -EILSEQ:
424		/* error in the ISOchronous data */
425		/* we don't copy the data into the transfer buffer */
426		/* and recycle the last data byte */
427#ifdef CONFIG_COMEDI_DEBUG
428		printk("comedi%d: usbdux: CRC error in ISO IN stream.\n",
429			this_usbduxsub->comedidev->minor);
430#endif
431
432		break;
433
434	case -ECONNRESET:
435	case -ENOENT:
436	case -ESHUTDOWN:
437	case -ECONNABORTED:
438		/* happens after an unlink command */
439		if (this_usbduxsub->ai_cmd_running) {
440			/* we are still running a command */
441			/* tell this comedi */
442			s->async->events |= COMEDI_CB_EOA;
443			s->async->events |= COMEDI_CB_ERROR;
444			comedi_event(this_usbduxsub->comedidev, s);
445			/* stop the transfer w/o unlink */
446			usbdux_ai_stop(this_usbduxsub, 0);
447		}
448		return;
449
450	default:
451		/* a real error on the bus */
452		/* pass error to comedi if we are really running a command */
453		if (this_usbduxsub->ai_cmd_running) {
454			printk("Non-zero urb status received in ai intr context: %d\n", urb->status);
455			s->async->events |= COMEDI_CB_EOA;
456			s->async->events |= COMEDI_CB_ERROR;
457			comedi_event(this_usbduxsub->comedidev, s);
458			/* don't do an unlink here */
459			usbdux_ai_stop(this_usbduxsub, 0);
460		}
461		return;
462	}
463
464	/* at this point we are reasonably sure that nothing dodgy has happened */
465	/* are we running a command? */
466	if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
467		/*
468		 * not running a command, do not continue execution if no
469		 * asynchronous command is running in particular not resubmit
470		 */
471		return;
472	}
473
474	urb->dev = this_usbduxsub->usbdev;
475
476	/* resubmit the urb */
477	err = USB_SUBMIT_URB(urb);
478	if (unlikely(err < 0)) {
479		printk("comedi_: usbdux_: urb resubmit failed in int-context! err=%d ", err);
480		if (err == -EL2NSYNC)
481			printk("--> buggy USB host controller or bug in IRQ handler!\n");
482		else
483			printk("\n");
484		s->async->events |= COMEDI_CB_EOA;
485		s->async->events |= COMEDI_CB_ERROR;
486		comedi_event(this_usbduxsub->comedidev, s);
487		/* don't do an unlink here */
488		usbdux_ai_stop(this_usbduxsub, 0);
489		return;
490	}
491
492	this_usbduxsub->ai_counter--;
493	if (likely(this_usbduxsub->ai_counter > 0))
494		return;
495
496	/* timer zero, transfer measurements to comedi */
497	this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
498
499	/* test, if we transmit only a fixed number of samples */
500	if (!(this_usbduxsub->ai_continous)) {
501		/* not continous, fixed number of samples */
502		this_usbduxsub->ai_sample_count--;
503		/* all samples received? */
504		if (this_usbduxsub->ai_sample_count < 0) {
505			/* prevent a resubmit next time */
506			usbdux_ai_stop(this_usbduxsub, 0);
507			/* say comedi that the acquistion is over */
508			s->async->events |= COMEDI_CB_EOA;
509			comedi_event(this_usbduxsub->comedidev, s);
510			return;
511		}
512	}
513	/* get the data from the USB bus and hand it over to comedi */
514	n = s->async->cmd.chanlist_len;
515	for (i = 0; i < n; i++) {
516		/* transfer data */
517		if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
518			comedi_buf_put
519				(s->async,
520				le16_to_cpu(this_usbduxsub->
521					inBuffer[i]) ^ 0x800);
522		} else {
523			comedi_buf_put
524				(s->async,
525				le16_to_cpu(this_usbduxsub->inBuffer[i]));
526		}
527	}
528	/* tell comedi that data is there */
529	comedi_event(this_usbduxsub->comedidev, s);
530}
531
532static int usbduxsub_unlink_OutURBs(usbduxsub_t *usbduxsub_tmp)
533{
534	int i = 0;
535	int err = 0;
536
537	if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
538		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
539			if (usbduxsub_tmp->urbOut[i])
540				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
541
542#ifdef NOISY_DUX_DEBUGBUG
543			printk("comedi: usbdux: unlinked OutURB %d: res=%d\n",
544				i, err);
545#endif
546		}
547	}
548	return err;
549}
550
551/* This will cancel a running acquisition operation
552 * in any context.
553 */
554static int usbdux_ao_stop(usbduxsub_t *this_usbduxsub, int do_unlink)
555{
556	int ret = 0;
557
558	if (!this_usbduxsub) {
559#ifdef NOISY_DUX_DEBUGBUG
560		printk("comedi?: usbdux_ao_stop: this_usbduxsub=NULL!\n");
561#endif
562		return -EFAULT;
563	}
564#ifdef NOISY_DUX_DEBUGBUG
565	printk("comedi: usbdux_ao_cancel\n");
566#endif
567	if (do_unlink)
568		ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
569
570	this_usbduxsub->ao_cmd_running = 0;
571
572	return ret;
573}
574
575/* force unlink, is called by comedi */
576static int usbdux_ao_cancel(comedi_device *dev, comedi_subdevice *s)
577{
578	usbduxsub_t *this_usbduxsub = dev->private;
579	int res = 0;
580
581	if (!this_usbduxsub) {
582		printk("comedi: usbdux_ao_cancel: this_usbduxsub=NULL\n");
583		return -EFAULT;
584	}
585	/* prevent other CPUs from submitting a command just now */
586	down(&this_usbduxsub->sem);
587	if (!(this_usbduxsub->probed)) {
588		up(&this_usbduxsub->sem);
589		return -ENODEV;
590	}
591	/* unlink only if it is really running */
592	res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
593	up(&this_usbduxsub->sem);
594	return res;
595}
596
597static void usbduxsub_ao_IsocIrq(struct urb *urb)
598{
599	int i, ret;
600	int8_t *datap;
601	usbduxsub_t *this_usbduxsub;
602	comedi_device *this_comedidev;
603	comedi_subdevice *s;
604
605	if (!urb) {
606		printk("comedi_: usbdux_: ao urb handler called with NULL ptr.\n");
607		return;
608	}
609	/* the context variable points to the subdevice */
610	this_comedidev = urb->context;
611	if (!this_comedidev) {
612		printk("comedi_: usbdux_: ao urb int-context is a NULL pointer.\n");
613		return;
614	}
615	/* the private structure of the subdevice is usbduxsub_t */
616	this_usbduxsub = this_comedidev->private;
617	if (!this_usbduxsub) {
618		printk("comedi_: usbdux_: private data structure of ao subdev is NULL p.\n");
619		return;
620	}
621
622	s = this_comedidev->subdevices + SUBDEV_DA;
623
624	switch (urb->status) {
625	case 0:
626		/* success */
627		break;
628
629	case -ECONNRESET:
630	case -ENOENT:
631	case -ESHUTDOWN:
632	case -ECONNABORTED:
633		/* after an unlink command, unplug, ... etc */
634		/* no unlink needed here. Already shutting down. */
635		if (this_usbduxsub->ao_cmd_running) {
636			s->async->events |= COMEDI_CB_EOA;
637			comedi_event(this_usbduxsub->comedidev, s);
638			usbdux_ao_stop(this_usbduxsub, 0);
639		}
640		return;
641
642	default:
643		/* a real error */
644		if (this_usbduxsub->ao_cmd_running) {
645			printk("comedi_: usbdux_: Non-zero urb status received in ao intr context: %d\n", urb->status);
646			s->async->events |= COMEDI_CB_ERROR;
647			s->async->events |= COMEDI_CB_EOA;
648			comedi_event(this_usbduxsub->comedidev, s);
649			/* we do an unlink if we are in the high speed mode */
650			usbdux_ao_stop(this_usbduxsub, 0);
651		}
652		return;
653	}
654
655	/* are we actually running? */
656	if (!(this_usbduxsub->ao_cmd_running))
657		return;
658
659	/* normal operation: executing a command in this subdevice */
660	this_usbduxsub->ao_counter--;
661	if (this_usbduxsub->ao_counter <= 0) {
662		/* timer zero */
663		this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
664
665		/* handle non continous aquisition */
666		if (!(this_usbduxsub->ao_continous)) {
667			/* fixed number of samples */
668			this_usbduxsub->ao_sample_count--;
669			if (this_usbduxsub->ao_sample_count < 0) {
670				/* all samples transmitted */
671				usbdux_ao_stop(this_usbduxsub, 0);
672				s->async->events |= COMEDI_CB_EOA;
673				comedi_event(this_usbduxsub->comedidev, s);
674				/* no resubmit of the urb */
675				return;
676			}
677		}
678		/* transmit data to the USB bus */
679		((uint8_t *) (urb->transfer_buffer))[0] =
680			s->async->cmd.chanlist_len;
681		for (i = 0; i < s->async->cmd.chanlist_len; i++) {
682			sampl_t temp;
683			if (i >= NUMOUTCHANNELS)
684				break;
685
686			/* pointer to the DA */
687			datap = (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1]));
688			/* get the data from comedi */
689			ret = comedi_buf_get(s->async, &temp);
690			datap[0] = temp;
691			datap[1] = temp >> 8;
692			datap[2] = this_usbduxsub->dac_commands[i];
693			/* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
694			/* datap[0],datap[1],datap[2]); */
695			if (ret < 0) {
696				printk("comedi: usbdux: buffer underflow\n");
697				s->async->events |= COMEDI_CB_EOA;
698				s->async->events |= COMEDI_CB_OVERFLOW;
699			}
700			/* transmit data to comedi */
701			s->async->events |= COMEDI_CB_BLOCK;
702			comedi_event(this_usbduxsub->comedidev, s);
703		}
704	}
705	urb->transfer_buffer_length = SIZEOUTBUF;
706	urb->dev = this_usbduxsub->usbdev;
707	urb->status = 0;
708	if (this_usbduxsub->ao_cmd_running) {
709		if (this_usbduxsub->high_speed) {
710			/* uframes */
711			urb->interval = 8;
712		} else {
713			/* frames */
714			urb->interval = 1;
715		}
716		urb->number_of_packets = 1;
717		urb->iso_frame_desc[0].offset = 0;
718		urb->iso_frame_desc[0].length = SIZEOUTBUF;
719		urb->iso_frame_desc[0].status = 0;
720		if ((ret = USB_SUBMIT_URB(urb)) < 0) {
721			printk("comedi_: usbdux_: ao urb resubm failed in int-cont.");
722			printk("ret=%d", ret);
723			if (ret == EL2NSYNC)
724				printk("--> buggy USB host controller or bug in IRQ handling!\n");
725			else
726				printk("\n");
727
728			s->async->events |= COMEDI_CB_EOA;
729			s->async->events |= COMEDI_CB_ERROR;
730			comedi_event(this_usbduxsub->comedidev, s);
731			/* don't do an unlink here */
732			usbdux_ao_stop(this_usbduxsub, 0);
733		}
734	}
735}
736
737static int usbduxsub_start(usbduxsub_t *usbduxsub)
738{
739	int errcode = 0;
740	uint8_t local_transfer_buffer[16];
741
742	if (usbduxsub->probed) {
743		/* 7f92 to zero */
744		local_transfer_buffer[0] = 0;
745		errcode = USB_CONTROL_MSG(usbduxsub->usbdev,
746			/* create a pipe for a control transfer */
747			usb_sndctrlpipe(usbduxsub->usbdev, 0),
748			/* bRequest, "Firmware" */
749			USBDUXSUB_FIRMWARE,
750			/* bmRequestType */
751			VENDOR_DIR_OUT,
752			/* Value */
753			USBDUXSUB_CPUCS,
754			/* Index */
755			0x0000,
756			/* address of the transfer buffer */
757			local_transfer_buffer,
758			/* Length */
759			1,
760			/* Timeout */
761			EZTIMEOUT);
762		if (errcode < 0) {
763			printk("comedi_: usbdux_: control msg failed (start)\n");
764			return errcode;
765		}
766	}
767	return 0;
768}
769
770static int usbduxsub_stop(usbduxsub_t *usbduxsub)
771{
772	int errcode = 0;
773
774	uint8_t local_transfer_buffer[16];
775	if (usbduxsub->probed) {
776		/* 7f92 to one */
777		local_transfer_buffer[0] = 1;
778		errcode = USB_CONTROL_MSG
779			(usbduxsub->usbdev,
780			usb_sndctrlpipe(usbduxsub->usbdev, 0),
781			/* bRequest, "Firmware" */
782			USBDUXSUB_FIRMWARE,
783			/* bmRequestType */
784			VENDOR_DIR_OUT,
785			/* Value */
786			USBDUXSUB_CPUCS,
787			/* Index */
788			0x0000, local_transfer_buffer,
789			/* Length */
790			1,
791			/* Timeout */
792			EZTIMEOUT);
793		if (errcode < 0) {
794			printk("comedi_: usbdux: control msg failed (stop)\n");
795			return errcode;
796		}
797	}
798	return 0;
799}
800
801static int usbduxsub_upload(usbduxsub_t *usbduxsub,
802			    uint8_t *local_transfer_buffer,
803			    unsigned int startAddr, unsigned int len)
804{
805	int errcode;
806
807	if (usbduxsub->probed) {
808#ifdef CONFIG_COMEDI_DEBUG
809		printk("comedi%d: usbdux: uploading %d bytes",
810			usbduxsub->comedidev->minor, len);
811		printk(" to addr %d, first byte=%d.\n",
812			startAddr, local_transfer_buffer[0]);
813#endif
814		errcode = USB_CONTROL_MSG
815			(usbduxsub->usbdev,
816			usb_sndctrlpipe(usbduxsub->usbdev, 0),
817			/* brequest, firmware */
818			USBDUXSUB_FIRMWARE,
819			/* bmRequestType */
820			VENDOR_DIR_OUT,
821			/* value */
822			startAddr,
823			/* index */
824			0x0000,
825			/* our local safe buffer */
826			local_transfer_buffer,
827			/* length */
828			len,
829			/* timeout */
830			EZTIMEOUT);
831#ifdef NOISY_DUX_DEBUGBUG
832		printk("comedi_: usbdux: result=%d\n", errcode);
833#endif
834		if (errcode < 0) {
835			printk("comedi_: usbdux: uppload failed\n");
836			return errcode;
837		}
838	} else {
839		/* no device on the bus for this index */
840		return -EFAULT;
841	}
842	return 0;
843}
844
845static int firmwareUpload(usbduxsub_t *usbduxsub, uint8_t *firmwareBinary,
846			  int sizeFirmware)
847{
848	int ret;
849
850	if (!firmwareBinary) {
851		return 0;
852	}
853	ret = usbduxsub_stop(usbduxsub);
854	if (ret < 0) {
855		printk("comedi_: usbdux: can not stop firmware\n");
856		return ret;
857	}
858	ret = usbduxsub_upload(usbduxsub, firmwareBinary, 0, sizeFirmware);
859	if (ret < 0) {
860		printk("comedi_: usbdux: firmware upload failed\n");
861		return ret;
862	}
863	ret = usbduxsub_start(usbduxsub);
864	if (ret < 0) {
865		printk("comedi_: usbdux: can not start firmware\n");
866		return ret;
867	}
868	return 0;
869}
870
871static int usbduxsub_submit_InURBs(usbduxsub_t *usbduxsub)
872{
873	int i, errFlag;
874
875	if (!usbduxsub)
876		return -EFAULT;
877
878	/* Submit all URBs and start the transfer on the bus */
879	for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
880		/* in case of a resubmission after an unlink... */
881		usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
882		usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
883		usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
884		usbduxsub->urbIn[i]->status = 0;
885		usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
886#ifdef NOISY_DUX_DEBUGBUG
887		printk("comedi%d: usbdux: submitting in-urb[%d]: %p,%p intv=%d\n", usbduxsub->comedidev->minor, i, (usbduxsub->urbIn[i]->context), (usbduxsub->urbIn[i]->dev), (usbduxsub->urbIn[i]->interval));
888#endif
889		errFlag = USB_SUBMIT_URB(usbduxsub->urbIn[i]);
890		if (errFlag) {
891			printk("comedi_: usbdux: ai: ");
892			printk("USB_SUBMIT_URB(%d)", i);
893			printk(" error %d\n", errFlag);
894			return errFlag;
895		}
896	}
897	return 0;
898}
899
900static int usbduxsub_submit_OutURBs(usbduxsub_t *usbduxsub)
901{
902	int i, errFlag;
903
904	if (!usbduxsub) {
905		return -EFAULT;
906	}
907	for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
908#ifdef NOISY_DUX_DEBUGBUG
909		printk("comedi_: usbdux: submitting out-urb[%d]\n", i);
910#endif
911		/* in case of a resubmission after an unlink... */
912		usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
913		usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
914		usbduxsub->urbOut[i]->status = 0;
915		usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
916		errFlag = USB_SUBMIT_URB(usbduxsub->urbOut[i]);
917		if (errFlag) {
918			printk("comedi_: usbdux: ao: ");
919			printk("USB_SUBMIT_URB(%d)", i);
920			printk(" error %d\n", errFlag);
921			return errFlag;
922		}
923	}
924	return 0;
925}
926
927static int usbdux_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
928			     comedi_cmd *cmd)
929{
930	int err = 0, tmp, i;
931	unsigned int tmpTimer;
932	usbduxsub_t *this_usbduxsub = dev->private;
933	if (!(this_usbduxsub->probed)) {
934		return -ENODEV;
935	}
936#ifdef NOISY_DUX_DEBUGBUG
937	printk("comedi%d: usbdux_ai_cmdtest\n", dev->minor);
938#endif
939	/* make sure triggers are valid */
940	/* Only immediate triggers are allowed */
941	tmp = cmd->start_src;
942	cmd->start_src &= TRIG_NOW | TRIG_INT;
943	if (!cmd->start_src || tmp != cmd->start_src)
944		err++;
945
946	/* trigger should happen timed */
947	tmp = cmd->scan_begin_src;
948	/* start a new _scan_ with a timer */
949	cmd->scan_begin_src &= TRIG_TIMER;
950	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
951		err++;
952
953	/* scanning is continous */
954	tmp = cmd->convert_src;
955	cmd->convert_src &= TRIG_NOW;
956	if (!cmd->convert_src || tmp != cmd->convert_src)
957		err++;
958
959	/* issue a trigger when scan is finished and start a new scan */
960	tmp = cmd->scan_end_src;
961	cmd->scan_end_src &= TRIG_COUNT;
962	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
963		err++;
964
965	/* trigger at the end of count events or not, stop condition or not */
966	tmp = cmd->stop_src;
967	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
968	if (!cmd->stop_src || tmp != cmd->stop_src)
969		err++;
970
971	if (err)
972		return 1;
973
974	/* step 2: make sure trigger sources are unique and mutually compatible */
975	/* note that mutual compatiblity is not an issue here */
976	if (cmd->scan_begin_src != TRIG_FOLLOW &&
977		cmd->scan_begin_src != TRIG_EXT &&
978		cmd->scan_begin_src != TRIG_TIMER)
979		err++;
980	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
981		err++;
982
983	if (err)
984		return 2;
985
986	/* step 3: make sure arguments are trivially compatible */
987
988	if (cmd->start_arg != 0) {
989		cmd->start_arg = 0;
990		err++;
991	}
992
993	if (cmd->scan_begin_src == TRIG_FOLLOW) {
994		/* internal trigger */
995		if (cmd->scan_begin_arg != 0) {
996			cmd->scan_begin_arg = 0;
997			err++;
998		}
999	}
1000
1001	if (cmd->scan_begin_src == TRIG_TIMER) {
1002		if (this_usbduxsub->high_speed) {
1003			/*
1004			 * In high speed mode microframes are possible.
1005			 * However, during one microframe we can roughly
1006			 * sample one channel. Thus, the more channels
1007			 * are in the channel list the more time we need.
1008			 */
1009			i = 1;
1010			/* find a power of 2 for the number of channels */
1011			while (i < (cmd->chanlist_len)) {
1012				i = i * 2;
1013			}
1014			if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
1015				cmd->scan_begin_arg = 1000000 / 8 * i;
1016				err++;
1017			}
1018			/* now calc the real sampling rate with all the
1019			 * rounding errors */
1020			tmpTimer =
1021				((unsigned int)(cmd->scan_begin_arg / 125000)) *
1022				125000;
1023			if (cmd->scan_begin_arg != tmpTimer) {
1024				cmd->scan_begin_arg = tmpTimer;
1025				err++;
1026			}
1027		} else {
1028			/* full speed */
1029			/* 1kHz scans every USB frame */
1030			if (cmd->scan_begin_arg < 1000000) {
1031				cmd->scan_begin_arg = 1000000;
1032				err++;
1033			}
1034			/* calc the real sampling rate with the rounding errors */
1035			tmpTimer =
1036				((unsigned int)(cmd->scan_begin_arg /
1037					1000000)) * 1000000;
1038			if (cmd->scan_begin_arg != tmpTimer) {
1039				cmd->scan_begin_arg = tmpTimer;
1040				err++;
1041			}
1042		}
1043	}
1044	/* the same argument */
1045	if (cmd->scan_end_arg != cmd->chanlist_len) {
1046		cmd->scan_end_arg = cmd->chanlist_len;
1047		err++;
1048	}
1049
1050	if (cmd->stop_src == TRIG_COUNT) {
1051		/* any count is allowed */
1052	} else {
1053		/* TRIG_NONE */
1054		if (cmd->stop_arg != 0) {
1055			cmd->stop_arg = 0;
1056			err++;
1057		}
1058	}
1059
1060	if (err)
1061		return 3;
1062
1063	return 0;
1064}
1065
1066/*
1067 * creates the ADC command for the MAX1271
1068 * range is the range value from comedi
1069 */
1070static int8_t create_adc_command(unsigned int chan, int range)
1071{
1072	int8_t p = (range <= 1);
1073	int8_t r = ((range % 2) == 0);
1074	return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
1075}
1076
1077/* bulk transfers to usbdux */
1078
1079#define SENDADCOMMANDS            0
1080#define SENDDACOMMANDS            1
1081#define SENDDIOCONFIGCOMMAND      2
1082#define SENDDIOBITSCOMMAND        3
1083#define SENDSINGLEAD              4
1084#define READCOUNTERCOMMAND        5
1085#define WRITECOUNTERCOMMAND       6
1086#define SENDPWMON                 7
1087#define SENDPWMOFF                8
1088
1089static int send_dux_commands(usbduxsub_t *this_usbduxsub, int cmd_type)
1090{
1091	int result, nsent;
1092
1093	this_usbduxsub->dux_commands[0] = cmd_type;
1094#ifdef NOISY_DUX_DEBUGBUG
1095	printk("comedi%d: usbdux: dux_commands: ",
1096		this_usbduxsub->comedidev->minor);
1097	for (result = 0; result < SIZEOFDUXBUFFER; result++) {
1098		printk(" %02x", this_usbduxsub->dux_commands[result]);
1099	}
1100	printk("\n");
1101#endif
1102	result = USB_BULK_MSG(this_usbduxsub->usbdev,
1103		usb_sndbulkpipe(this_usbduxsub->usbdev,
1104			COMMAND_OUT_EP),
1105		this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, &nsent, 10 * HZ);
1106	if (result < 0)
1107		printk("comedi%d: could not transmit dux_command to the usb-device, err=%d\n", this_usbduxsub->comedidev->minor, result);
1108
1109	return result;
1110}
1111
1112static int receive_dux_commands(usbduxsub_t *this_usbduxsub, int command)
1113{
1114	int result = (-EFAULT);
1115	int nrec;
1116	int i;
1117
1118	for (i = 0; i < RETRIES; i++) {
1119		result = USB_BULK_MSG(this_usbduxsub->usbdev,
1120			usb_rcvbulkpipe(this_usbduxsub->usbdev,
1121				COMMAND_IN_EP),
1122			this_usbduxsub->insnBuffer, SIZEINSNBUF, &nrec, 1 * HZ);
1123		if (result < 0) {
1124			printk("comedi%d: insn: USB error %d while receiving DUX command\n", this_usbduxsub->comedidev->minor, result);
1125			return result;
1126		}
1127		if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command) {
1128			return result;
1129		}
1130	}
1131	/* this is only reached if the data has been requested a couple of times */
1132	printk("comedi%d: insn: wrong data returned from firmware: want cmd %d, got cmd %d.\n", this_usbduxsub->comedidev->minor, command, le16_to_cpu(this_usbduxsub->insnBuffer[0]));
1133	return -EFAULT;
1134}
1135
1136static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
1137			     unsigned int trignum)
1138{
1139	int ret;
1140	usbduxsub_t *this_usbduxsub = dev->private;
1141	if (!this_usbduxsub) {
1142		return -EFAULT;
1143	}
1144	down(&this_usbduxsub->sem);
1145	if (!(this_usbduxsub->probed)) {
1146		up(&this_usbduxsub->sem);
1147		return -ENODEV;
1148	}
1149#ifdef NOISY_DUX_DEBUGBUG
1150	printk("comedi%d: usbdux_ai_inttrig\n", dev->minor);
1151#endif
1152
1153	if (trignum != 0) {
1154		printk("comedi%d: usbdux_ai_inttrig: invalid trignum\n",
1155			dev->minor);
1156		up(&this_usbduxsub->sem);
1157		return -EINVAL;
1158	}
1159	if (!(this_usbduxsub->ai_cmd_running)) {
1160		this_usbduxsub->ai_cmd_running = 1;
1161		ret = usbduxsub_submit_InURBs(this_usbduxsub);
1162		if (ret < 0) {
1163			printk("comedi%d: usbdux_ai_inttrig: urbSubmit: err=%d\n", dev->minor, ret);
1164			this_usbduxsub->ai_cmd_running = 0;
1165			up(&this_usbduxsub->sem);
1166			return ret;
1167		}
1168		s->async->inttrig = NULL;
1169	} else {
1170		printk("comedi%d: ai_inttrig but acqu is already running\n",
1171			dev->minor);
1172	}
1173	up(&this_usbduxsub->sem);
1174	return 1;
1175}
1176
1177static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s)
1178{
1179	comedi_cmd *cmd = &s->async->cmd;
1180	unsigned int chan, range;
1181	int i, ret;
1182	usbduxsub_t *this_usbduxsub = dev->private;
1183	int result;
1184
1185#ifdef NOISY_DUX_DEBUGBUG
1186	printk("comedi%d: usbdux_ai_cmd\n", dev->minor);
1187#endif
1188	if (!this_usbduxsub)
1189		return -EFAULT;
1190
1191	/* block other CPUs from starting an ai_cmd */
1192	down(&this_usbduxsub->sem);
1193
1194	if (!(this_usbduxsub->probed)) {
1195		up(&this_usbduxsub->sem);
1196		return -ENODEV;
1197	}
1198	if (this_usbduxsub->ai_cmd_running) {
1199		printk("comedi%d: ai_cmd not possible. Another ai_cmd is running.\n", dev->minor);
1200		up(&this_usbduxsub->sem);
1201		return -EBUSY;
1202	}
1203	/* set current channel of the running aquisition to zero */
1204	s->async->cur_chan = 0;
1205
1206	this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
1207	for (i = 0; i < cmd->chanlist_len; ++i) {
1208		chan = CR_CHAN(cmd->chanlist[i]);
1209		range = CR_RANGE(cmd->chanlist[i]);
1210		if (i >= NUMCHANNELS) {
1211			printk("comedi%d: channel list too long\n", dev->minor);
1212			break;
1213		}
1214		this_usbduxsub->dux_commands[i + 2] =
1215			create_adc_command(chan, range);
1216	}
1217
1218#ifdef NOISY_DUX_DEBUGBUG
1219	printk("comedi %d: sending commands to the usb device: ", dev->minor);
1220	printk("size=%u\n", NUMCHANNELS);
1221#endif
1222	if ((result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS)) < 0) {
1223		up(&this_usbduxsub->sem);
1224		return result;
1225	}
1226
1227	if (this_usbduxsub->high_speed) {
1228		/*
1229		 * every channel gets a time window of 125us. Thus, if we
1230		 * sample all 8 channels we need 1ms. If we sample only one
1231		 * channel we need only 125us
1232		 */
1233		this_usbduxsub->ai_interval = 1;
1234		/* find a power of 2 for the interval */
1235		while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
1236			this_usbduxsub->ai_interval =
1237				(this_usbduxsub->ai_interval) * 2;
1238		}
1239		this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
1240			(this_usbduxsub->ai_interval));
1241	} else {
1242		/* interval always 1ms */
1243		this_usbduxsub->ai_interval = 1;
1244		this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
1245	}
1246	if (this_usbduxsub->ai_timer < 1) {
1247		printk("comedi%d: usbdux: ai_cmd: timer=%d, scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, this_usbduxsub->ai_timer, cmd->scan_begin_arg);
1248		up(&this_usbduxsub->sem);
1249		return -EINVAL;
1250	}
1251	this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
1252
1253	if (cmd->stop_src == TRIG_COUNT) {
1254		/* data arrives as one packet */
1255		this_usbduxsub->ai_sample_count = cmd->stop_arg;
1256		this_usbduxsub->ai_continous = 0;
1257	} else {
1258		/* continous aquisition */
1259		this_usbduxsub->ai_continous = 1;
1260		this_usbduxsub->ai_sample_count = 0;
1261	}
1262
1263	if (cmd->start_src == TRIG_NOW) {
1264		/* enable this acquisition operation */
1265		this_usbduxsub->ai_cmd_running = 1;
1266		ret = usbduxsub_submit_InURBs(this_usbduxsub);
1267		if (ret < 0) {
1268			this_usbduxsub->ai_cmd_running = 0;
1269			/* fixme: unlink here?? */
1270			up(&this_usbduxsub->sem);
1271			return ret;
1272		}
1273		s->async->inttrig = NULL;
1274	} else {
1275		/* TRIG_INT */
1276		/* don't enable the acquision operation */
1277		/* wait for an internal signal */
1278		s->async->inttrig = usbdux_ai_inttrig;
1279	}
1280	up(&this_usbduxsub->sem);
1281	return 0;
1282}
1283
1284/* Mode 0 is used to get a single conversion on demand */
1285static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
1286			       comedi_insn *insn, lsampl_t *data)
1287{
1288	int i;
1289	lsampl_t one = 0;
1290	int chan, range;
1291	int err;
1292	usbduxsub_t *this_usbduxsub = dev->private;
1293
1294	if (!this_usbduxsub) {
1295		printk("comedi%d: ai_insn_read: no usb dev.\n", dev->minor);
1296		return 0;
1297	}
1298#ifdef NOISY_DUX_DEBUGBUG
1299	printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1300		dev->minor, insn->n, insn->subdev);
1301#endif
1302	down(&this_usbduxsub->sem);
1303	if (!(this_usbduxsub->probed)) {
1304		up(&this_usbduxsub->sem);
1305		return -ENODEV;
1306	}
1307	if (this_usbduxsub->ai_cmd_running) {
1308		printk("comedi%d: ai_insn_read not possible. Async Command is running.\n", dev->minor);
1309		up(&this_usbduxsub->sem);
1310		return 0;
1311	}
1312
1313	/* sample one channel */
1314	chan = CR_CHAN(insn->chanspec);
1315	range = CR_RANGE(insn->chanspec);
1316	/* set command for the first channel */
1317	this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
1318
1319	/* adc commands */
1320	if ((err = send_dux_commands(this_usbduxsub, SENDSINGLEAD)) < 0) {
1321		up(&this_usbduxsub->sem);
1322		return err;
1323	}
1324
1325	for (i = 0; i < insn->n; i++) {
1326		if ((err = receive_dux_commands(this_usbduxsub,
1327					SENDSINGLEAD)) < 0) {
1328			up(&this_usbduxsub->sem);
1329			return 0;
1330		}
1331		one = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1332		if (CR_RANGE(insn->chanspec) <= 1)
1333			one = one ^ 0x800;
1334
1335		data[i] = one;
1336	}
1337	up(&this_usbduxsub->sem);
1338	return i;
1339}
1340
1341/************************************/
1342/* analog out */
1343
1344static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
1345			       comedi_insn *insn, lsampl_t *data)
1346{
1347	int i;
1348	int chan = CR_CHAN(insn->chanspec);
1349	usbduxsub_t *this_usbduxsub = dev->private;
1350
1351	if (!this_usbduxsub)
1352		return -EFAULT;
1353
1354	down(&this_usbduxsub->sem);
1355	if (!(this_usbduxsub->probed)) {
1356		up(&this_usbduxsub->sem);
1357		return -ENODEV;
1358	}
1359	for (i = 0; i < insn->n; i++)
1360		data[i] = this_usbduxsub->outBuffer[chan];
1361
1362	up(&this_usbduxsub->sem);
1363	return i;
1364}
1365
1366static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
1367				comedi_insn *insn, lsampl_t *data)
1368{
1369	int i, err;
1370	int chan = CR_CHAN(insn->chanspec);
1371	usbduxsub_t *this_usbduxsub = dev->private;
1372
1373#ifdef NOISY_DUX_DEBUGBUG
1374	printk("comedi%d: ao_insn_write\n", dev->minor);
1375#endif
1376	if (!this_usbduxsub)
1377		return -EFAULT;
1378
1379	down(&this_usbduxsub->sem);
1380	if (!(this_usbduxsub->probed)) {
1381		up(&this_usbduxsub->sem);
1382		return -ENODEV;
1383	}
1384	if (this_usbduxsub->ao_cmd_running) {
1385		printk("comedi%d: ao_insn_write: ERROR: asynchronous ao_cmd is running\n", dev->minor);
1386		up(&this_usbduxsub->sem);
1387		return 0;
1388	}
1389
1390	for (i = 0; i < insn->n; i++) {
1391#ifdef NOISY_DUX_DEBUGBUG
1392		printk("comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1393			dev->minor, chan, i, data[i]);
1394#endif
1395		/* number of channels: 1 */
1396		this_usbduxsub->dux_commands[1] = 1;
1397		/* one 16 bit value */
1398		*((int16_t *) (this_usbduxsub->dux_commands + 2)) =
1399			cpu_to_le16(data[i]);
1400		this_usbduxsub->outBuffer[chan] = data[i];
1401		/* channel number */
1402		this_usbduxsub->dux_commands[4] = (chan << 6);
1403		if ((err = send_dux_commands(this_usbduxsub,
1404					SENDDACOMMANDS)) < 0) {
1405			up(&this_usbduxsub->sem);
1406			return err;
1407		}
1408	}
1409	up(&this_usbduxsub->sem);
1410
1411	return i;
1412}
1413
1414static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s,
1415			     unsigned int trignum)
1416{
1417	int ret;
1418	usbduxsub_t *this_usbduxsub = dev->private;
1419
1420	if (!this_usbduxsub)
1421		return -EFAULT;
1422
1423	down(&this_usbduxsub->sem);
1424	if (!(this_usbduxsub->probed)) {
1425		up(&this_usbduxsub->sem);
1426		return -ENODEV;
1427	}
1428	if (trignum != 0) {
1429		printk("comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1430			dev->minor);
1431		return -EINVAL;
1432	}
1433	if (!(this_usbduxsub->ao_cmd_running)) {
1434		this_usbduxsub->ao_cmd_running = 1;
1435		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1436		if (ret < 0) {
1437			printk("comedi%d: usbdux_ao_inttrig: submitURB: err=%d\n", dev->minor, ret);
1438			this_usbduxsub->ao_cmd_running = 0;
1439			up(&this_usbduxsub->sem);
1440			return ret;
1441		}
1442		s->async->inttrig = NULL;
1443	} else {
1444		printk("comedi%d: ao_inttrig but acqu is already running.\n",
1445			dev->minor);
1446	}
1447	up(&this_usbduxsub->sem);
1448	return 1;
1449}
1450
1451static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s,
1452			     comedi_cmd *cmd)
1453{
1454	int err = 0, tmp;
1455	usbduxsub_t *this_usbduxsub = dev->private;
1456
1457	if (!this_usbduxsub)
1458		return -EFAULT;
1459
1460	if (!(this_usbduxsub->probed))
1461		return -ENODEV;
1462
1463#ifdef NOISY_DUX_DEBUGBUG
1464	printk("comedi%d: usbdux_ao_cmdtest\n", dev->minor);
1465#endif
1466	/* make sure triggers are valid */
1467	/* Only immediate triggers are allowed */
1468	tmp = cmd->start_src;
1469	cmd->start_src &= TRIG_NOW | TRIG_INT;
1470	if (!cmd->start_src || tmp != cmd->start_src)
1471		err++;
1472
1473	/* trigger should happen timed */
1474	tmp = cmd->scan_begin_src;
1475	/* just now we scan also in the high speed mode every frame */
1476	/* this is due to ehci driver limitations */
1477	if (0) {		/* (this_usbduxsub->high_speed) */
1478		/* start immidiately a new scan */
1479		/* the sampling rate is set by the coversion rate */
1480		cmd->scan_begin_src &= TRIG_FOLLOW;
1481	} else {
1482		/* start a new scan (output at once) with a timer */
1483		cmd->scan_begin_src &= TRIG_TIMER;
1484	}
1485	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1486		err++;
1487
1488	/* scanning is continous */
1489	tmp = cmd->convert_src;
1490	/* we always output at 1kHz just now all channels at once */
1491	if (0) {		/* (this_usbduxsub->high_speed) */
1492		/* in usb-2.0 only one conversion it tranmitted but with 8kHz/n */
1493		cmd->convert_src &= TRIG_TIMER;
1494	} else {
1495		/* all conversion events happen simultaneously with a rate of 1kHz/n */
1496		cmd->convert_src &= TRIG_NOW;
1497	}
1498	if (!cmd->convert_src || tmp != cmd->convert_src)
1499		err++;
1500
1501	/* issue a trigger when scan is finished and start a new scan */
1502	tmp = cmd->scan_end_src;
1503	cmd->scan_end_src &= TRIG_COUNT;
1504	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1505		err++;
1506
1507	/* trigger at the end of count events or not, stop condition or not */
1508	tmp = cmd->stop_src;
1509	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1510	if (!cmd->stop_src || tmp != cmd->stop_src)
1511		err++;
1512
1513	if (err)
1514		return 1;
1515
1516	/* step 2: make sure trigger sources are unique and mutually compatible */
1517	/* note that mutual compatiblity is not an issue here */
1518	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1519		cmd->scan_begin_src != TRIG_EXT &&
1520		cmd->scan_begin_src != TRIG_TIMER)
1521		err++;
1522	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1523		err++;
1524
1525	if (err)
1526		return 2;
1527
1528	/* step 3: make sure arguments are trivially compatible */
1529
1530	if (cmd->start_arg != 0) {
1531		cmd->start_arg = 0;
1532		err++;
1533	}
1534
1535	if (cmd->scan_begin_src == TRIG_FOLLOW) {
1536		/* internal trigger */
1537		if (cmd->scan_begin_arg != 0) {
1538			cmd->scan_begin_arg = 0;
1539			err++;
1540		}
1541	}
1542
1543	if (cmd->scan_begin_src == TRIG_TIMER) {
1544		/* timer */
1545		if (cmd->scan_begin_arg < 1000000) {
1546			cmd->scan_begin_arg = 1000000;
1547			err++;
1548		}
1549	}
1550	/* not used now, is for later use */
1551	if (cmd->convert_src == TRIG_TIMER) {
1552		if (cmd->convert_arg < 125000) {
1553			cmd->convert_arg = 125000;
1554			err++;
1555		}
1556	}
1557
1558	/* the same argument */
1559	if (cmd->scan_end_arg != cmd->chanlist_len) {
1560		cmd->scan_end_arg = cmd->chanlist_len;
1561		err++;
1562	}
1563
1564	if (cmd->stop_src == TRIG_COUNT) {
1565		/* any count is allowed */
1566	} else {
1567		/* TRIG_NONE */
1568		if (cmd->stop_arg != 0) {
1569			cmd->stop_arg = 0;
1570			err++;
1571		}
1572	}
1573
1574#ifdef NOISY_DUX_DEBUGBUG
1575	printk("comedi%d: err=%d, scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src, cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
1576#endif
1577
1578	if (err)
1579		return 3;
1580
1581	return 0;
1582}
1583
1584static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s)
1585{
1586	comedi_cmd *cmd = &s->async->cmd;
1587	unsigned int chan, gain;
1588	int i, ret;
1589	usbduxsub_t *this_usbduxsub = dev->private;
1590
1591	if (!this_usbduxsub)
1592		return -EFAULT;
1593
1594	down(&this_usbduxsub->sem);
1595	if (!(this_usbduxsub->probed)) {
1596		up(&this_usbduxsub->sem);
1597		return -ENODEV;
1598	}
1599#ifdef NOISY_DUX_DEBUGBUG
1600	printk("comedi%d: usbdux_ao_cmd\n", dev->minor);
1601#endif
1602
1603	/* set current channel of the running aquisition to zero */
1604	s->async->cur_chan = 0;
1605	for (i = 0; i < cmd->chanlist_len; ++i) {
1606		chan = CR_CHAN(cmd->chanlist[i]);
1607		gain = CR_RANGE(cmd->chanlist[i]);
1608		if (i >= NUMOUTCHANNELS) {
1609			printk("comedi%d: usbdux_ao_cmd: channel list too long\n", dev->minor);
1610			break;
1611		}
1612		this_usbduxsub->dac_commands[i] = (chan << 6);
1613#ifdef NOISY_DUX_DEBUGBUG
1614		printk("comedi%d: dac command for ch %d is %x\n",
1615			dev->minor, i, this_usbduxsub->dac_commands[i]);
1616#endif
1617	}
1618
1619	/* we count in steps of 1ms (125us) */
1620	/* 125us mode not used yet */
1621	if (0) {		/* (this_usbduxsub->high_speed) */
1622		/* 125us */
1623		/* timing of the conversion itself: every 125 us */
1624		this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1625	} else {
1626		/* 1ms */
1627		/* timing of the scan: we get all channels at once */
1628		this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1629#ifdef NOISY_DUX_DEBUGBUG
1630		printk("comedi%d: usbdux: scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, convert_arg=%d\n", dev->minor, cmd->scan_begin_src, cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
1631		printk("comedi%d: usbdux: ao_timer=%d (ms)\n",
1632			dev->minor, this_usbduxsub->ao_timer);
1633#endif
1634		if (this_usbduxsub->ao_timer < 1) {
1635			printk("comedi%d: usbdux: ao_timer=%d,  scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, this_usbduxsub->ao_timer, cmd->scan_begin_arg);
1636			up(&this_usbduxsub->sem);
1637			return -EINVAL;
1638		}
1639	}
1640	this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1641
1642	if (cmd->stop_src == TRIG_COUNT) {
1643		/* not continous */
1644		/* counter */
1645		/* high speed also scans everything at once */
1646		if (0) {	/* (this_usbduxsub->high_speed) */
1647			this_usbduxsub->ao_sample_count =
1648				(cmd->stop_arg) * (cmd->scan_end_arg);
1649		} else {
1650			/* there's no scan as the scan has been */
1651			/* perf inside the FX2 */
1652			/* data arrives as one packet */
1653			this_usbduxsub->ao_sample_count = cmd->stop_arg;
1654		}
1655		this_usbduxsub->ao_continous = 0;
1656	} else {
1657		/* continous aquisition */
1658		this_usbduxsub->ao_continous = 1;
1659		this_usbduxsub->ao_sample_count = 0;
1660	}
1661
1662	if (cmd->start_src == TRIG_NOW) {
1663		/* enable this acquisition operation */
1664		this_usbduxsub->ao_cmd_running = 1;
1665		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1666		if (ret < 0) {
1667			this_usbduxsub->ao_cmd_running = 0;
1668			/* fixme: unlink here?? */
1669			up(&this_usbduxsub->sem);
1670			return ret;
1671		}
1672		s->async->inttrig = NULL;
1673	} else {
1674		/* TRIG_INT */
1675		/* submit the urbs later */
1676		/* wait for an internal signal */
1677		s->async->inttrig = usbdux_ao_inttrig;
1678	}
1679
1680	up(&this_usbduxsub->sem);
1681	return 0;
1682}
1683
1684static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
1685				  comedi_insn *insn, lsampl_t *data)
1686{
1687	int chan = CR_CHAN(insn->chanspec);
1688
1689	/* The input or output configuration of each digital line is
1690	 * configured by a special insn_config instruction.  chanspec
1691	 * contains the channel to be changed, and data[0] contains the
1692	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
1693
1694	switch (data[0]) {
1695	case INSN_CONFIG_DIO_OUTPUT:
1696		s->io_bits |= 1 << chan;	/* 1 means Out */
1697		break;
1698	case INSN_CONFIG_DIO_INPUT:
1699		s->io_bits &= ~(1 << chan);
1700		break;
1701	case INSN_CONFIG_DIO_QUERY:
1702		data[1] =
1703			(s->
1704			io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1705		break;
1706	default:
1707		return -EINVAL;
1708		break;
1709	}
1710	/* we don't tell the firmware here as it would take 8 frames */
1711	/* to submit the information. We do it in the insn_bits. */
1712	return insn->n;
1713}
1714
1715static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
1716				comedi_insn *insn, lsampl_t *data)
1717{
1718
1719	usbduxsub_t *this_usbduxsub = dev->private;
1720	int err;
1721
1722	if (!this_usbduxsub)
1723		return -EFAULT;
1724
1725
1726	if (insn->n != 2)
1727		return -EINVAL;
1728
1729	down(&this_usbduxsub->sem);
1730
1731	if (!(this_usbduxsub->probed)) {
1732		up(&this_usbduxsub->sem);
1733		return -ENODEV;
1734	}
1735
1736	/* The insn data is a mask in data[0] and the new data
1737	 * in data[1], each channel cooresponding to a bit. */
1738	s->state &= ~data[0];
1739	s->state |= data[0] & data[1];
1740	this_usbduxsub->dux_commands[1] = s->io_bits;
1741	this_usbduxsub->dux_commands[2] = s->state;
1742
1743	/* This command also tells the firmware to return */
1744	/* the digital input lines */
1745	if ((err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND)) < 0) {
1746		up(&this_usbduxsub->sem);
1747		return err;
1748	}
1749	if ((err = receive_dux_commands(this_usbduxsub,
1750				SENDDIOBITSCOMMAND)) < 0) {
1751		up(&this_usbduxsub->sem);
1752		return err;
1753	}
1754
1755	data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1756	up(&this_usbduxsub->sem);
1757	return 2;
1758}
1759
1760/* reads the 4 counters, only two are used just now */
1761static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
1762			       comedi_insn *insn, lsampl_t *data)
1763{
1764	usbduxsub_t *this_usbduxsub = dev->private;
1765	int chan = insn->chanspec;
1766	int err;
1767
1768	if (!this_usbduxsub)
1769		return -EFAULT;
1770
1771	down(&this_usbduxsub->sem);
1772
1773	if (!(this_usbduxsub->probed)) {
1774		up(&this_usbduxsub->sem);
1775		return -ENODEV;
1776	}
1777
1778	if ((err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND)) < 0) {
1779		up(&this_usbduxsub->sem);
1780		return err;
1781	}
1782
1783	if ((err = receive_dux_commands(this_usbduxsub,
1784				READCOUNTERCOMMAND)) < 0) {
1785		up(&this_usbduxsub->sem);
1786		return err;
1787	}
1788
1789	data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]);
1790	up(&this_usbduxsub->sem);
1791	return 1;
1792}
1793
1794static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
1795				comedi_insn *insn, lsampl_t *data)
1796{
1797	usbduxsub_t *this_usbduxsub = dev->private;
1798	int err;
1799
1800	if (!this_usbduxsub)
1801		return -EFAULT;
1802
1803	down(&this_usbduxsub->sem);
1804
1805	if (!(this_usbduxsub->probed)) {
1806		up(&this_usbduxsub->sem);
1807		return -ENODEV;
1808	}
1809
1810	this_usbduxsub->dux_commands[1] = insn->chanspec;
1811	*((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
1812
1813	if ((err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND)) < 0) {
1814		up(&this_usbduxsub->sem);
1815		return err;
1816	}
1817
1818	up(&this_usbduxsub->sem);
1819
1820	return 1;
1821}
1822
1823static int usbdux_counter_config(comedi_device *dev, comedi_subdevice *s,
1824				 comedi_insn *insn, lsampl_t *data)
1825{
1826	/* nothing to do so far */
1827	return 2;
1828}
1829
1830/***********************************/
1831/* PWM */
1832
1833static int usbduxsub_unlink_PwmURBs(usbduxsub_t *usbduxsub_tmp)
1834{
1835	int err = 0;
1836
1837	if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
1838		if (usbduxsub_tmp->urbPwm)
1839			usb_kill_urb(usbduxsub_tmp->urbPwm);
1840#ifdef NOISY_DUX_DEBUGBUG
1841		printk("comedi: usbdux: unlinked PwmURB: res=%d\n", err);
1842#endif
1843	}
1844	return err;
1845}
1846
1847/* This cancels a running acquisition operation
1848 * in any context.
1849 */
1850static int usbdux_pwm_stop(usbduxsub_t *this_usbduxsub, int do_unlink)
1851{
1852	int ret = 0;
1853
1854	if (!this_usbduxsub) {
1855#ifdef NOISY_DUX_DEBUGBUG
1856		printk("comedi?: usbdux_pwm_stop: this_usbduxsub=NULL!\n");
1857#endif
1858		return -EFAULT;
1859	}
1860#ifdef NOISY_DUX_DEBUGBUG
1861	printk("comedi: usbdux_pwm_cancel\n");
1862#endif
1863	if (do_unlink)
1864		ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
1865
1866
1867	this_usbduxsub->pwm_cmd_running = 0;
1868
1869	return ret;
1870}
1871
1872/* force unlink - is called by comedi */
1873static int usbdux_pwm_cancel(comedi_device *dev, comedi_subdevice *s)
1874{
1875	usbduxsub_t *this_usbduxsub = dev->private;
1876	int res = 0;
1877
1878	/* unlink only if it is really running */
1879	res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
1880
1881#ifdef NOISY_DUX_DEBUGBUG
1882	printk("comedi %d: sending pwm off command to the usb device.\n",
1883		dev->minor);
1884#endif
1885	if ((res = send_dux_commands(this_usbduxsub, SENDPWMOFF)) < 0)
1886		return res;
1887
1888	return res;
1889}
1890
1891static void usbduxsub_pwm_irq(struct urb *urb)
1892{
1893	int ret;
1894	usbduxsub_t *this_usbduxsub;
1895	comedi_device *this_comedidev;
1896	comedi_subdevice *s;
1897
1898	/* printk("PWM: IRQ\n"); */
1899
1900	if (!urb) {
1901		printk("comedi_: usbdux_: pwm urb handler called with NULL ptr.\n");
1902		return;
1903	}
1904	/* the context variable points to the subdevice */
1905	this_comedidev = urb->context;
1906	if (!this_comedidev) {
1907		printk("comedi_: usbdux_: pwm urb int-context is a NULL pointer.\n");
1908		return;
1909	}
1910	/* the private structure of the subdevice is usbduxsub_t */
1911	this_usbduxsub = this_comedidev->private;
1912	if (!this_usbduxsub) {
1913		printk("comedi_: usbdux_: private data structure of pwm subdev is NULL p.\n");
1914		return;
1915	}
1916
1917	s = this_comedidev->subdevices + SUBDEV_DA;
1918
1919	switch (urb->status) {
1920	case 0:
1921		/* success */
1922		break;
1923
1924	case -ECONNRESET:
1925	case -ENOENT:
1926	case -ESHUTDOWN:
1927	case -ECONNABORTED:
1928		/*
1929		 * after an unlink command, unplug, ... etc
1930		 * no unlink needed here. Already shutting down.
1931		 */
1932		if (this_usbduxsub->pwm_cmd_running)
1933			usbdux_pwm_stop(this_usbduxsub, 0);
1934
1935		return;
1936
1937	default:
1938		/* a real error */
1939		if (this_usbduxsub->pwm_cmd_running) {
1940			printk("comedi_: usbdux_: Non-zero urb status received in pwm intr context: %d\n", urb->status);
1941			usbdux_pwm_stop(this_usbduxsub, 0);
1942		}
1943		return;
1944	}
1945
1946	/* are we actually running? */
1947	if (!(this_usbduxsub->pwm_cmd_running))
1948		return;
1949
1950	urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
1951	urb->dev = this_usbduxsub->usbdev;
1952	urb->status = 0;
1953	if (this_usbduxsub->pwm_cmd_running) {
1954		if ((ret = USB_SUBMIT_URB(urb)) < 0) {
1955			printk("comedi_: usbdux_: pwm urb resubm failed in int-cont.");
1956			printk("ret=%d", ret);
1957			if (ret == EL2NSYNC)
1958				printk("--> buggy USB host controller or bug in IRQ handling!\n");
1959			else
1960				printk("\n");
1961
1962			/* don't do an unlink here */
1963			usbdux_pwm_stop(this_usbduxsub, 0);
1964		}
1965	}
1966}
1967
1968static int usbduxsub_submit_PwmURBs(usbduxsub_t *usbduxsub)
1969{
1970	int errFlag;
1971
1972	if (!usbduxsub)
1973		return -EFAULT;
1974
1975#ifdef NOISY_DUX_DEBUGBUG
1976	printk("comedi_: usbdux: submitting pwm-urb\n");
1977#endif
1978	/* in case of a resubmission after an unlink... */
1979
1980	usb_fill_bulk_urb(usbduxsub->urbPwm,
1981		usbduxsub->usbdev,
1982		usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
1983		usbduxsub->urbPwm->transfer_buffer,
1984		usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, usbduxsub->comedidev);
1985
1986	errFlag = USB_SUBMIT_URB(usbduxsub->urbPwm);
1987	if (errFlag) {
1988		printk("comedi_: usbdux: pwm: ");
1989		printk("USB_SUBMIT_URB");
1990		printk(" error %d\n", errFlag);
1991		return errFlag;
1992	}
1993	return 0;
1994}
1995
1996static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s,
1997			     lsampl_t period)
1998{
1999	usbduxsub_t *this_usbduxsub = dev->private;
2000	int fx2delay = 255;
2001
2002	if (period < MIN_PWM_PERIOD) {
2003		printk("comedi%d: illegal period setting for pwm.\n", dev->minor);
2004		return -EAGAIN;
2005	} else {
2006		fx2delay = period / ((int)(6*512*(1.0/0.033))) - 6;
2007		if (fx2delay > 255) {
2008			printk("comedi%d: period %d for pwm is too low.\n",
2009			       dev->minor, period);
2010			return -EAGAIN;
2011		}
2012	}
2013	this_usbduxsub->pwmDelay = fx2delay;
2014	this_usbduxsub->pwmPeriod = period;
2015#ifdef NOISY_DUX_DEBUGBUG
2016	printk("usbdux_pwm_period: frequ=%d, period=%d\n", period, fx2delay);
2017#endif
2018	return 0;
2019}
2020
2021
2022/* is called from insn so there's no need to do all the sanity checks */
2023static int usbdux_pwm_start(comedi_device * dev, comedi_subdevice * s)
2024{
2025	int ret, i;
2026	usbduxsub_t *this_usbduxsub = dev->private;
2027
2028#ifdef NOISY_DUX_DEBUGBUG
2029	printk("comedi%d: usbdux_pwm_start\n", dev->minor);
2030#endif
2031	if (this_usbduxsub->pwm_cmd_running) {
2032		/* already running */
2033		return 0;
2034	}
2035
2036	this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay);
2037	if ((ret = send_dux_commands(this_usbduxsub, SENDPWMON)) < 0) {
2038		return ret;
2039	}
2040	/* initalise the buffer */
2041	for (i = 0; i < this_usbduxsub->sizePwmBuf; i++) {
2042		((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
2043	}
2044
2045	this_usbduxsub->pwm_cmd_running = 1;
2046	ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
2047	if (ret < 0) {
2048		this_usbduxsub->pwm_cmd_running = 0;
2049		return ret;
2050	}
2051	return 0;
2052}
2053
2054
2055/* generates the bit pattern for PWM with the optional sign bit */
2056static int usbdux_pwm_pattern(comedi_device * dev, comedi_subdevice * s,
2057			      int channel, lsampl_t value, lsampl_t sign)
2058{
2059	usbduxsub_t *this_usbduxsub = dev->private;
2060	int i, szbuf;
2061	char *pBuf;
2062	char pwm_mask,sgn_mask,c;
2063
2064	if (!this_usbduxsub) {
2065		return -EFAULT;
2066	}
2067	/* this is the DIO bit which carries the PWM data */
2068	pwm_mask = (1 << channel);
2069	/* this is the DIO bit which carries the optional direction bit */
2070	sgn_mask = (16 << channel);
2071	/* this is the buffer which will be filled with the with bit */
2072	/* pattern for one period */
2073	szbuf = this_usbduxsub->sizePwmBuf;
2074	pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
2075	for (i = 0; i < szbuf; i++) {
2076		c = *pBuf;
2077		/* reset bits */
2078		c = c & (~pwm_mask);
2079		/* set the bit as long as the index is lower than the value */
2080		if (i < value)
2081			c = c | pwm_mask;
2082		/* set the optional sign bit for a relay */
2083		if (!sign) {
2084			/* positive value */
2085			c = c & (~sgn_mask);
2086		} else {
2087			/* negative value */
2088			c = c | sgn_mask;
2089		}
2090		*(pBuf++) = c;
2091	}
2092	return 1;
2093}
2094
2095static int usbdux_pwm_write(comedi_device * dev, comedi_subdevice * s,
2096			    comedi_insn * insn, lsampl_t * data)
2097{
2098	usbduxsub_t *this_usbduxsub = dev->private;
2099
2100	if (!this_usbduxsub) {
2101		return -EFAULT;
2102	}
2103
2104	if ((insn->n)!=1) {
2105		/* doesn't make sense to have more than one value here */
2106		/* because it would just overwrite the PWM buffer a couple of times */
2107		return -EINVAL;
2108	}
2109
2110	/* the sign is set via a special INSN only, this gives us 8 bits for */
2111	/* normal operation */
2112	/* relay sign 0 by default */
2113	return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec),
2114				  data[0], 0);
2115}
2116
2117static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
2118			   comedi_insn *x3, lsampl_t *x4)
2119{
2120	/* not needed */
2121	return -EINVAL;
2122};
2123
2124/* switches on/off PWM */
2125static int usbdux_pwm_config(comedi_device *dev, comedi_subdevice *s,
2126			     comedi_insn *insn, lsampl_t *data)
2127{
2128	usbduxsub_t *this_usbduxsub = dev->private;
2129	switch (data[0]) {
2130	case INSN_CONFIG_ARM:
2131#ifdef NOISY_DUX_DEBUGBUG
2132		/* switch it on */
2133		printk("comedi%d: pwm_insn_config: pwm on\n",
2134		       dev->minor);
2135#endif
2136		/*
2137		 * if not zero the PWM is limited to a certain time which is
2138		 * not supported here
2139		 */
2140		if (data[1] != 0)
2141			return -EINVAL;
2142		return usbdux_pwm_start(dev, s);
2143	case INSN_CONFIG_DISARM:
2144#ifdef NOISY_DUX_DEBUGBUG
2145		printk("comedi%d: pwm_insn_config: pwm off\n",
2146		       dev->minor);
2147#endif
2148		return usbdux_pwm_cancel(dev, s);
2149	case INSN_CONFIG_GET_PWM_STATUS:
2150		/*
2151		 * to check if the USB transmission has failed or in case PWM
2152		 * was limited to n cycles to check if it has terminated
2153		 */
2154		data[1] = this_usbduxsub->pwm_cmd_running;
2155		return 0;
2156	case INSN_CONFIG_PWM_SET_PERIOD:
2157#ifdef NOISY_DUX_DEBUGBUG
2158		printk("comedi%d: pwm_insn_config: setting period\n",
2159		       dev->minor);
2160#endif
2161		return usbdux_pwm_period(dev, s, data[1]);
2162	case INSN_CONFIG_PWM_GET_PERIOD:
2163		data[1] = this_usbduxsub->pwmPeriod;
2164		return 0;
2165	case INSN_CONFIG_PWM_SET_H_BRIDGE:
2166		/* value in the first byte and the sign in the second for a
2167		   relay */
2168		return usbdux_pwm_pattern(dev, s,
2169					  /* the channel number */
2170					  CR_CHAN(insn->chanspec),
2171					  /* actual PWM data */
2172					  data[1],
2173					  /* just a sign */
2174					  (data[2] != 0));
2175	case INSN_CONFIG_PWM_GET_H_BRIDGE:
2176		/* values are not kept in this driver, nothing to return here */
2177		return -EINVAL;
2178	}
2179	return -EINVAL;
2180}
2181
2182/* end of PWM */
2183/*****************************************************************/
2184
2185static void tidy_up(usbduxsub_t *usbduxsub_tmp)
2186{
2187	int i;
2188
2189#ifdef CONFIG_COMEDI_DEBUG
2190	printk("comedi_: usbdux: tiding up\n");
2191#endif
2192	if (!usbduxsub_tmp)
2193		return;
2194
2195	/* shows the usb subsystem that the driver is down */
2196	if (usbduxsub_tmp->interface)
2197		usb_set_intfdata(usbduxsub_tmp->interface, NULL);
2198
2199	usbduxsub_tmp->probed = 0;
2200
2201	if (usbduxsub_tmp->urbIn) {
2202		if (usbduxsub_tmp->ai_cmd_running) {
2203			usbduxsub_tmp->ai_cmd_running = 0;
2204			usbduxsub_unlink_InURBs(usbduxsub_tmp);
2205		}
2206		for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
2207			if (usbduxsub_tmp->urbIn[i]->transfer_buffer) {
2208				kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
2209				usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
2210			}
2211			if (usbduxsub_tmp->urbIn[i]) {
2212				usb_kill_urb(usbduxsub_tmp->urbIn[i]);
2213				usb_free_urb(usbduxsub_tmp->urbIn[i]);
2214				usbduxsub_tmp->urbIn[i] = NULL;
2215			}
2216		}
2217		kfree(usbduxsub_tmp->urbIn);
2218		usbduxsub_tmp->urbIn = NULL;
2219	}
2220	if (usbduxsub_tmp->urbOut) {
2221		if (usbduxsub_tmp->ao_cmd_running) {
2222			usbduxsub_tmp->ao_cmd_running = 0;
2223			usbduxsub_unlink_OutURBs(usbduxsub_tmp);
2224		}
2225		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
2226			if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
2227				kfree(usbduxsub_tmp->urbOut[i]->
2228					transfer_buffer);
2229				usbduxsub_tmp->urbOut[i]->transfer_buffer =
2230					NULL;
2231			}
2232			if (usbduxsub_tmp->urbOut[i]) {
2233				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
2234				usb_free_urb(usbduxsub_tmp->urbOut[i]);
2235				usbduxsub_tmp->urbOut[i] = NULL;
2236			}
2237		}
2238		kfree(usbduxsub_tmp->urbOut);
2239		usbduxsub_tmp->urbOut = NULL;
2240	}
2241	if (usbduxsub_tmp->urbPwm) {
2242		if (usbduxsub_tmp->pwm_cmd_running) {
2243			usbduxsub_tmp->pwm_cmd_running = 0;
2244			usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
2245		}
2246		kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
2247		usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
2248		usb_kill_urb(usbduxsub_tmp->urbPwm);
2249		usb_free_urb(usbduxsub_tmp->urbPwm);
2250		usbduxsub_tmp->urbPwm = NULL;
2251	}
2252	kfree(usbduxsub_tmp->inBuffer);
2253	usbduxsub_tmp->inBuffer = NULL;
2254	kfree(usbduxsub_tmp->insnBuffer);
2255	usbduxsub_tmp->insnBuffer = NULL;
2256	kfree(usbduxsub_tmp->inBuffer);
2257	usbduxsub_tmp->inBuffer = NULL;
2258	kfree(usbduxsub_tmp->dac_commands);
2259	usbduxsub_tmp->dac_commands = NULL;
2260	kfree(usbduxsub_tmp->dux_commands);
2261	usbduxsub_tmp->dux_commands = NULL;
2262	usbduxsub_tmp->ai_cmd_running = 0;
2263	usbduxsub_tmp->ao_cmd_running = 0;
2264	usbduxsub_tmp->pwm_cmd_running = 0;
2265}
2266
2267static unsigned hex2unsigned(char *h)
2268{
2269	unsigned hi, lo;
2270
2271	if (h[0] > '9')
2272		hi = h[0] - 'A' + 0x0a;
2273	else
2274		hi = h[0] - '0';
2275
2276	if (h[1] > '9')
2277		lo = h[1] - 'A' + 0x0a;
2278	else
2279		lo = h[1] - '0';
2280
2281	return hi * 0x10 + lo;
2282}
2283
2284/* for FX2 */
2285#define FIRMWARE_MAX_LEN 0x2000
2286
2287/* taken from David Brownell's fxload and adjusted for this driver */
2288static int read_firmware(usbduxsub_t *usbduxsub, void *firmwarePtr, long size)
2289{
2290	int i = 0;
2291	unsigned char *fp = (char *)firmwarePtr;
2292	unsigned char *firmwareBinary = NULL;
2293	int res = 0;
2294	int maxAddr = 0;
2295
2296	firmwareBinary = kzalloc(FIRMWARE_MAX_LEN, GFP_KERNEL);
2297	if (!firmwareBinary) {
2298		printk("comedi_: usbdux: mem alloc for firmware failed\n");
2299		return -ENOMEM;
2300	}
2301
2302	for (;;) {
2303		char buf[256], *cp;
2304		char type;
2305		int len;
2306		int idx, off;
2307		int j = 0;
2308
2309		/* get one line */
2310		while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) {
2311			buf[j] = fp[i];
2312			i++;
2313			j++;
2314			if (j >= sizeof(buf)) {
2315				printk("comedi_: usbdux: bogus firmware file!\n");
2316				return -1;
2317			}
2318		}
2319		/* get rid of LF/CR/... */
2320		while ((i < size) && ((fp[i] == 13) || (fp[i] == 10)
2321				|| (fp[i] == 0))) {
2322			i++;
2323		}
2324
2325		buf[j] = 0;
2326		/*printk("comedi_: buf=%s\n",buf); */
2327
2328		/* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
2329		if (buf[0] == '#')
2330			continue;
2331
2332		if (buf[0] != ':') {
2333			printk("comedi_: usbdux: upload: not an ihex record: %s", buf);
2334			return -EFAULT;
2335		}
2336
2337		/* Read the length field (up to 16 bytes) */
2338		len = hex2unsigned(buf + 1);
2339
2340		/* Read the target offset */
2341		off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5);
2342
2343		if ((off + len) > maxAddr)
2344			maxAddr = off + len;
2345
2346
2347		if (maxAddr >= FIRMWARE_MAX_LEN) {
2348			printk("comedi_: usbdux: firmware upload goes beyond FX2 RAM boundaries.");
2349			return -EFAULT;
2350		}
2351		/*printk("comedi_: usbdux: off=%x, len=%x:",off,len); */
2352
2353		/* Read the record type */
2354		type = hex2unsigned(buf + 7);
2355
2356		/* If this is an EOF record, then make it so. */
2357		if (type == 1)
2358			break;
2359
2360
2361		if (type != 0) {
2362			printk("comedi_: usbdux: unsupported record type: %u\n",
2363				type);
2364			return -EFAULT;
2365		}
2366
2367		for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) {
2368			firmwareBinary[idx + off] = hex2unsigned(cp);
2369			/*printk("%02x ",firmwareBinary[idx+off]); */
2370		}
2371		/*printk("\n"); */
2372
2373		if (i >= size) {
2374			printk("comedi_: usbdux: unexpected end of hex file\n");
2375			break;
2376		}
2377
2378	}
2379	res = firmwareUpload(usbduxsub, firmwareBinary, maxAddr + 1);
2380	kfree(firmwareBinary);
2381	return res;
2382}
2383
2384/* allocate memory for the urbs and initialise them */
2385static int usbduxsub_probe(struct usb_interface *uinterf,
2386	const struct usb_device_id *id)
2387{
2388	struct usb_device *udev = interface_to_usbdev(uinterf);
2389	int i;
2390	int index;
2391
2392#ifdef CONFIG_COMEDI_DEBUG
2393	printk("comedi_: usbdux_: finding a free structure for the usb-device\n");
2394#endif
2395	down(&start_stop_sem);
2396	/* look for a free place in the usbdux array */
2397	index = -1;
2398	for (i = 0; i < NUMUSBDUX; i++) {
2399		if (!(usbduxsub[i].probed)) {
2400			index = i;
2401			break;
2402		}
2403	}
2404
2405	/* no more space */
2406	if (index == -1) {
2407		printk("Too many usbdux-devices connected.\n");
2408		up(&start_stop_sem);
2409		return PROBE_ERR_RETURN(-EMFILE);
2410	}
2411#ifdef CONFIG_COMEDI_DEBUG
2412	printk("comedi_: usbdux: usbduxsub[%d] is ready to connect to comedi.\n", index);
2413#endif
2414
2415	init_MUTEX(&(usbduxsub[index].sem));
2416	/* save a pointer to the usb device */
2417	usbduxsub[index].usbdev = udev;
2418
2419	/* 2.6: save the interface itself */
2420	usbduxsub[index].interface = uinterf;
2421	/* get the interface number from the interface */
2422	usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
2423	/* hand the private data over to the usb subsystem */
2424	/* will be needed for disconnect */
2425	usb_set_intfdata(uinterf, &(usbduxsub[index]));
2426
2427#ifdef CONFIG_COMEDI_DEBUG
2428	printk("comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
2429#endif
2430	/* test if it is high speed (USB 2.0) */
2431	usbduxsub[index].high_speed =
2432		(usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
2433
2434	/* create space for the commands of the DA converter */
2435	usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
2436	if (!usbduxsub[index].dac_commands) {
2437		printk("comedi_: usbdux: error alloc space for dac commands\n");
2438		tidy_up(&(usbduxsub[index]));
2439		up(&start_stop_sem);
2440		return PROBE_ERR_RETURN(-ENOMEM);
2441	}
2442	/* create space for the commands going to the usb device */
2443	usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
2444	if (!usbduxsub[index].dux_commands) {
2445		printk("comedi_: usbdux: error alloc space for dac commands\n");
2446		tidy_up(&(usbduxsub[index]));
2447		up(&start_stop_sem);
2448		return PROBE_ERR_RETURN(-ENOMEM);
2449	}
2450	/* create space for the in buffer and set it to zero */
2451	usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
2452	if (!(usbduxsub[index].inBuffer)) {
2453		printk("comedi_: usbdux: could not alloc space for inBuffer\n");
2454		tidy_up(&(usbduxsub[index]));
2455		up(&start_stop_sem);
2456		return PROBE_ERR_RETURN(-ENOMEM);
2457	}
2458	/* create space of the instruction buffer */
2459	usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
2460	if (!(usbduxsub[index].insnBuffer)) {
2461		printk("comedi_: usbdux: could not alloc space for insnBuffer\n");
2462		tidy_up(&(usbduxsub[index]));
2463		up(&start_stop_sem);
2464		return PROBE_ERR_RETURN(-ENOMEM);
2465	}
2466	/* create space for the outbuffer */
2467	usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
2468	if (!(usbduxsub[index].outBuffer)) {
2469		printk("comedi_: usbdux: could not alloc space for outBuffer\n");
2470		tidy_up(&(usbduxsub[index]));
2471		up(&start_stop_sem);
2472		return PROBE_ERR_RETURN(-ENOMEM);
2473	}
2474	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
2475	i = usb_set_interface(usbduxsub[index].usbdev,
2476			      usbduxsub[index].ifnum, 3);
2477	if (i < 0) {
2478		printk("comedi_: usbdux%d: could not set alternate setting 3 in high speed.\n", index);
2479		tidy_up(&(usbduxsub[index]));
2480		up(&start_stop_sem);
2481		return PROBE_ERR_RETURN(-ENODEV);
2482	}
2483	if (usbduxsub[index].high_speed)
2484		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
2485	else
2486		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
2487
2488	usbduxsub[index].urbIn =
2489		kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
2490		GFP_KERNEL);
2491	if (!(usbduxsub[index].urbIn)) {
2492		printk("comedi_: usbdux: Could not alloc. urbIn array\n");
2493		tidy_up(&(usbduxsub[index]));
2494		up(&start_stop_sem);
2495		return PROBE_ERR_RETURN(-ENOMEM);
2496	}
2497	for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
2498		/* one frame: 1ms */
2499		usbduxsub[index].urbIn[i] = USB_ALLOC_URB(1);
2500		if (usbduxsub[index].urbIn[i] == NULL) {
2501			printk("comedi_: usbdux%d: Could not alloc. urb(%d)\n",
2502				index, i);
2503			tidy_up(&(usbduxsub[index]));
2504			up(&start_stop_sem);
2505			return PROBE_ERR_RETURN(-ENOMEM);
2506		}
2507		usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
2508		/* will be filled later with a pointer to the comedi-device */
2509		/* and ONLY then the urb should be submitted */
2510		usbduxsub[index].urbIn[i]->context = NULL;
2511		usbduxsub[index].urbIn[i]->pipe =
2512			usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
2513		usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
2514		usbduxsub[index].urbIn[i]->transfer_buffer =
2515			kzalloc(SIZEINBUF, GFP_KERNEL);
2516		if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
2517			printk("comedi_: usbdux%d: could not alloc. transb.\n",
2518				index);
2519			tidy_up(&(usbduxsub[index]));
2520			up(&start_stop_sem);
2521			return PROBE_ERR_RETURN(-ENOMEM);
2522		}
2523		usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
2524		usbduxsub[index].urbIn[i]->number_of_packets = 1;
2525		usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
2526		usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
2527		usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF;
2528	}
2529
2530	/* out */
2531	if (usbduxsub[index].high_speed)
2532		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
2533	else
2534		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
2535
2536	usbduxsub[index].urbOut =
2537		kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
2538		GFP_KERNEL);
2539	if (!(usbduxsub[index].urbOut)) {
2540		printk("comedi_: usbdux: Could not alloc. urbOut array\n");
2541		tidy_up(&(usbduxsub[index]));
2542		up(&start_stop_sem);
2543		return PROBE_ERR_RETURN(-ENOMEM);
2544	}
2545	for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
2546		/* one frame: 1ms */
2547		usbduxsub[index].urbOut[i] = USB_ALLOC_URB(1);
2548		if (usbduxsub[index].urbOut[i] == NULL) {
2549			printk("comedi_: usbdux%d: Could not alloc. urb(%d)\n",
2550				index, i);
2551			tidy_up(&(usbduxsub[index]));
2552			up(&start_stop_sem);
2553			return PROBE_ERR_RETURN(-ENOMEM);
2554		}
2555		usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
2556		/* will be filled later with a pointer to the comedi-device */
2557		/* and ONLY then the urb should be submitted */
2558		usbduxsub[index].urbOut[i]->context = NULL;
2559		usbduxsub[index].urbOut[i]->pipe =
2560			usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
2561		usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
2562		usbduxsub[index].urbOut[i]->transfer_buffer =
2563			kzalloc(SIZEOUTBUF, GFP_KERNEL);
2564		if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
2565			printk("comedi_: usbdux%d: could not alloc. transb.\n",
2566				index);
2567			tidy_up(&(usbduxsub[index]));
2568			up(&start_stop_sem);
2569			return PROBE_ERR_RETURN(-ENOMEM);
2570		}
2571		usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
2572		usbduxsub[index].urbOut[i]->number_of_packets = 1;
2573		usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF;
2574		usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
2575		usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
2576			SIZEOUTBUF;
2577		if (usbduxsub[index].high_speed) {
2578			/* uframes */
2579			usbduxsub[index].urbOut[i]->interval = 8;
2580		} else {
2581			/* frames */
2582			usbduxsub[index].urbOut[i]->interval = 1;
2583		}
2584	}
2585
2586	/* pwm */
2587	if (usbduxsub[index].high_speed) {
2588		usbduxsub[index].sizePwmBuf = 512;	/* max bulk ep size in high speed */
2589		usbduxsub[index].urbPwm = USB_ALLOC_URB(0);
2590		if (usbduxsub[index].urbPwm == NULL) {
2591			printk("comedi_: usbdux%d: Could not alloc. pwm urb\n",
2592				index);
2593			tidy_up(&(usbduxsub[index]));
2594			up(&start_stop_sem);
2595			return PROBE_ERR_RETURN(-ENOMEM);
2596		}
2597		usbduxsub[index].urbPwm->transfer_buffer =
2598			kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
2599		if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
2600			printk("comedi_: usbdux%d: could not alloc. transb. for pwm\n", index);
2601			tidy_up(&(usbduxsub[index]));
2602			up(&start_stop_sem);
2603			return PROBE_ERR_RETURN(-ENOMEM);
2604		}
2605	} else {
2606		usbduxsub[index].urbPwm = NULL;
2607		usbduxsub[index].sizePwmBuf = 0;
2608	}
2609
2610	usbduxsub[index].ai_cmd_running = 0;
2611	usbduxsub[index].ao_cmd_running = 0;
2612	usbduxsub[index].pwm_cmd_running = 0;
2613
2614	/* we've reached the bottom of the function */
2615	usbduxsub[index].probed = 1;
2616	up(&start_stop_sem);
2617	printk("comedi_: usbdux%d has been successfully initialised.\n", index);
2618	/* success */
2619	return 0;
2620}
2621
2622static void usbduxsub_disconnect(struct usb_interface *intf)
2623{
2624	usbduxsub_t *usbduxsub_tmp = usb_get_intfdata(intf);
2625	struct usb_device *udev = interface_to_usbdev(intf);
2626
2627	if (!usbduxsub_tmp) {
2628		printk("comedi_: usbdux: disconnect called with null pointer.\n");
2629		return;
2630	}
2631	if (usbduxsub_tmp->usbdev != udev) {
2632		printk("comedi_: usbdux: BUG! called with wrong ptr!!!\n");
2633		return;
2634	}
2635	down(&start_stop_sem);
2636	down(&usbduxsub_tmp->sem);
2637	tidy_up(usbduxsub_tmp);
2638	up(&usbduxsub_tmp->sem);
2639	up(&start_stop_sem);
2640#ifdef CONFIG_COMEDI_DEBUG
2641	printk("comedi_: usbdux: disconnected from the usb\n");
2642#endif
2643}
2644
2645/* is called when comedi-config is called */
2646static int usbdux_attach(comedi_device *dev, comedi_devconfig *it)
2647{
2648	int ret;
2649	int index;
2650	int i;
2651	comedi_subdevice *s = NULL;
2652	dev->private = NULL;
2653
2654	down(&start_stop_sem);
2655	/* find a valid device which has been detected by the probe function of the usb */
2656	index = -1;
2657	for (i = 0; i < NUMUSBDUX; i++) {
2658		if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
2659			index = i;
2660			break;
2661		}
2662	}
2663
2664	if (index < 0) {
2665		printk("comedi%d: usbdux: error: attach failed, no usbdux devs connected to the usb bus.\n", dev->minor);
2666		up(&start_stop_sem);
2667		return -ENODEV;
2668	}
2669
2670	down(&(usbduxsub[index].sem));
2671	/* pointer back to the corresponding comedi device */
2672	usbduxsub[index].comedidev = dev;
2673
2674	/* trying to upload the firmware into the chip */
2675	if (comedi_aux_data(it->options, 0) &&
2676		it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
2677		read_firmware(usbduxsub + index,
2678			comedi_aux_data(it->options, 0),
2679			it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
2680	}
2681
2682	dev->board_name = BOARDNAME;
2683
2684	/* set number of subdevices */
2685	if (usbduxsub[index].high_speed) {
2686		/* with pwm */
2687		dev->n_subdevices = 5;
2688	} else {
2689		/* without pwm */
2690		dev->n_subdevices = 4;
2691	}
2692
2693	/* allocate space for the subdevices */
2694	if ((ret = alloc_subdevices(dev, dev->n_subdevices)) < 0) {
2695		printk("comedi%d: usbdux: error alloc space for subdev\n",
2696			dev->minor);
2697		up(&start_stop_sem);
2698		return ret;
2699	}
2700
2701	printk("comedi%d: usbdux: usb-device %d is attached to comedi.\n",
2702		dev->minor, index);
2703	/* private structure is also simply the usb-structure */
2704	dev->private = usbduxsub + index;
2705
2706	/* the first subdevice is the A/D converter */
2707	s = dev->subdevices + SUBDEV_AD;
2708	/* the URBs get the comedi subdevice */
2709	/* which is responsible for reading */
2710	/* this is the subdevice which reads data */
2711	dev->read_subdev = s;
2712	/* the subdevice receives as private structure the */
2713	/* usb-structure */
2714	s->private = NULL;
2715	/* analog input */
2716	s->type = COMEDI_SUBD_AI;
2717	/* readable and ref is to ground */
2718	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
2719	/* 8 channels */
2720	s->n_chan = 8;
2721	/* length of the channellist */
2722	s->len_chanlist = 8;
2723	/* callback functions */
2724	s->insn_read = usbdux_ai_insn_read;
2725	s->do_cmdtest = usbdux_ai_cmdtest;
2726	s->do_cmd = usbdux_ai_cmd;
2727	s->cancel = usbdux_ai_cancel;
2728	/* max value from the A/D converter (12bit) */
2729	s->maxdata = 0xfff;
2730	/* range table to convert to physical units */
2731	s->range_table = (&range_usbdux_ai_range);
2732
2733	/* analog out */
2734	s = dev->subdevices + SUBDEV_DA;
2735	/* analog out */
2736	s->type = COMEDI_SUBD_AO;
2737	/* backward pointer */
2738	dev->write_subdev = s;
2739	/* the subdevice receives as private structure the */
2740	/* usb-structure */
2741	s->private = NULL;
2742	/* are writable */
2743	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
2744	/* 4 channels */
2745	s->n_chan = 4;
2746	/* length of the channellist */
2747	s->len_chanlist = 4;
2748	/* 12 bit resolution */
2749	s->maxdata = 0x0fff;
2750	/* bipolar range */
2751	s->range_table = (&range_usbdux_ao_range);
2752	/* callback */
2753	s->do_cmdtest = usbdux_ao_cmdtest;
2754	s->do_cmd = usbdux_ao_cmd;
2755	s->cancel = usbdux_ao_cancel;
2756	s->insn_read = usbdux_ao_insn_read;
2757	s->insn_write = usbdux_ao_insn_write;
2758
2759	/* digital I/O */
2760	s = dev->subdevices + SUBDEV_DIO;
2761	s->type = COMEDI_SUBD_DIO;
2762	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2763	s->n_chan = 8;
2764	s->maxdata = 1;
2765	s->range_table = (&range_digital);
2766	s->insn_bits = usbdux_dio_insn_bits;
2767	s->insn_config = usbdux_dio_insn_config;
2768	/* we don't use it */
2769	s->private = NULL;
2770
2771	/* counter */
2772	s = dev->subdevices + SUBDEV_COUNTER;
2773	s->type = COMEDI_SUBD_COUNTER;
2774	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2775	s->n_chan = 4;
2776	s->maxdata = 0xFFFF;
2777	s->insn_read = usbdux_counter_read;
2778	s->insn_write = usbdux_counter_write;
2779	s->insn_config = usbdux_counter_config;
2780
2781	if (usbduxsub[index].high_speed) {
2782		/* timer / pwm */
2783		s = dev->subdevices + SUBDEV_PWM;
2784		s->type = COMEDI_SUBD_PWM;
2785		s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
2786		s->n_chan = 8;
2787		/* this defines the max duty cycle resolution */
2788		s->maxdata = usbduxsub[index].sizePwmBuf;
2789		s->insn_write = usbdux_pwm_write;
2790		s->insn_read = usbdux_pwm_read;
2791		s->insn_config = usbdux_pwm_config;
2792		usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
2793	}
2794	/* finally decide that it's attached */
2795	usbduxsub[index].attached = 1;
2796
2797	up(&(usbduxsub[index].sem));
2798
2799	up(&start_stop_sem);
2800
2801	printk("comedi%d: attached to usbdux.\n", dev->minor);
2802
2803	return 0;
2804}
2805
2806static int usbdux_detach(comedi_device *dev)
2807{
2808	usbduxsub_t *usbduxsub_tmp;
2809
2810#ifdef CONFIG_COMEDI_DEBUG
2811	printk("comedi%d: usbdux: detach usb device\n", dev->minor);
2812#endif
2813
2814	if (!dev) {
2815		printk("comedi?: usbdux: detach without dev variable...\n");
2816		return -EFAULT;
2817	}
2818
2819	usbduxsub_tmp = dev->private;
2820	if (!usbduxsub_tmp) {
2821		printk("comedi?: usbdux: detach without ptr to usbduxsub[]\n");
2822		return -EFAULT;
2823	}
2824
2825	down(&usbduxsub_tmp->sem);
2826	/* Don't allow detach to free the private structure */
2827	/* It's one entry of of usbduxsub[] */
2828	dev->private = NULL;
2829	usbduxsub_tmp->attached = 0;
2830	usbduxsub_tmp->comedidev = NULL;
2831#ifdef CONFIG_COMEDI_DEBUG
2832	printk("comedi%d: usbdux: detach: successfully removed\n", dev->minor);
2833#endif
2834	up(&usbduxsub_tmp->sem);
2835	return 0;
2836}
2837
2838/* main driver struct */
2839static comedi_driver driver_usbdux = {
2840      .driver_name =	"usbdux",
2841      .module =		THIS_MODULE,
2842      .attach =		usbdux_attach,
2843      .detach =		usbdux_detach,
2844};
2845
2846static void init_usb_devices(void)
2847{
2848	int index;
2849#ifdef CONFIG_COMEDI_DEBUG
2850	printk("comedi_: usbdux: setting all possible devs to invalid\n");
2851#endif
2852	/* all devices entries are invalid to begin with */
2853	/* they will become valid by the probe function */
2854	/* and then finally by the attach-function */
2855	for (index = 0; index < NUMUSBDUX; index++) {
2856		memset(&(usbduxsub[index]), 0x00, sizeof(usbduxsub[index]));
2857		init_MUTEX(&(usbduxsub[index].sem));
2858	}
2859}
2860
2861/* Table with the USB-devices: just now only testing IDs */
2862static struct usb_device_id usbduxsub_table[] = {
2863	{USB_DEVICE(0x13d8, 0x0001) },
2864	{USB_DEVICE(0x13d8, 0x0002) },
2865	{}			/* Terminating entry */
2866};
2867
2868MODULE_DEVICE_TABLE(usb, usbduxsub_table);
2869
2870/* The usbduxsub-driver */
2871static struct usb_driver usbduxsub_driver = {
2872      .name =		BOARDNAME,
2873      .probe =		usbduxsub_probe,
2874      .disconnect =	usbduxsub_disconnect,
2875      .id_table =	usbduxsub_table,
2876};
2877
2878/* Can't use the nice macro as I have also to initialise the USB */
2879/* subsystem: */
2880/* registering the usb-system _and_ the comedi-driver */
2881static int init_usbdux(void)
2882{
2883	printk(KERN_INFO KBUILD_MODNAME ": "
2884	       DRIVER_VERSION ":" DRIVER_DESC "\n");
2885	init_usb_devices();
2886	usb_register(&usbduxsub_driver);
2887	comedi_driver_register(&driver_usbdux);
2888	return 0;
2889}
2890
2891/* deregistering the comedi driver and the usb-subsystem */
2892static void exit_usbdux(void)
2893{
2894	comedi_driver_unregister(&driver_usbdux);
2895	usb_deregister(&usbduxsub_driver);
2896}
2897
2898module_init(init_usbdux);
2899module_exit(exit_usbdux);
2900
2901MODULE_AUTHOR(DRIVER_AUTHOR);
2902MODULE_DESCRIPTION(DRIVER_DESC);
2903MODULE_LICENSE("GPL");
2904