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