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