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