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