usbdux.c revision 81874ff7895f332920621104308e803434a17183
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
812#define FIRMWARE_MAX_LEN 0x2000
813
814static int firmwareUpload(struct usbduxsub *usbduxsub,
815			  const u8 *firmwareBinary,
816			  int sizeFirmware)
817{
818	int ret;
819	uint8_t *fwBuf;
820
821	if (!firmwareBinary)
822		return 0;
823
824	if (sizeFirmware>FIRMWARE_MAX_LEN) {
825		dev_err(&usbduxsub->interface->dev,
826			"comedi_: usbdux firmware binary it too large for FX2.\n");
827		return -ENOMEM;
828	}
829
830	/* we generate a local buffer for the firmware */
831	fwBuf = kzalloc(sizeFirmware, GFP_KERNEL);
832	if (!fwBuf) {
833		dev_err(&usbduxsub->interface->dev,
834			"comedi_: mem alloc for firmware failed\n");
835		return -ENOMEM;
836	}
837	memcpy(fwBuf,firmwareBinary,sizeFirmware);
838
839	ret = usbduxsub_stop(usbduxsub);
840	if (ret < 0) {
841		dev_err(&usbduxsub->interface->dev,
842			"comedi_: can not stop firmware\n");
843		kfree(fwBuf);
844		return ret;
845	}
846
847	ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware);
848	if (ret < 0) {
849		dev_err(&usbduxsub->interface->dev,
850			"comedi_: firmware upload failed\n");
851		kfree(fwBuf);
852		return ret;
853	}
854	ret = usbduxsub_start(usbduxsub);
855	if (ret < 0) {
856		dev_err(&usbduxsub->interface->dev,
857			"comedi_: can not start firmware\n");
858		kfree(fwBuf);
859		return ret;
860	}
861	kfree(fwBuf);
862	return 0;
863}
864
865static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
866{
867	int i, errFlag;
868
869	if (!usbduxsub)
870		return -EFAULT;
871
872	/* Submit all URBs and start the transfer on the bus */
873	for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
874		/* in case of a resubmission after an unlink... */
875		usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
876		usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
877		usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
878		usbduxsub->urbIn[i]->status = 0;
879		usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
880		dev_dbg(&usbduxsub->interface->dev,
881			"comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
882			usbduxsub->comedidev->minor, i,
883			(usbduxsub->urbIn[i]->context),
884			(usbduxsub->urbIn[i]->dev),
885			(usbduxsub->urbIn[i]->interval));
886		errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
887		if (errFlag) {
888			dev_err(&usbduxsub->interface->dev,
889				"comedi_: ai: usb_submit_urb(%d) error %d\n",
890				i, errFlag);
891			return errFlag;
892		}
893	}
894	return 0;
895}
896
897static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
898{
899	int i, errFlag;
900
901	if (!usbduxsub)
902		return -EFAULT;
903
904	for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
905		dev_dbg(&usbduxsub->interface->dev,
906			"comedi_: submitting out-urb[%d]\n", i);
907		/* in case of a resubmission after an unlink... */
908		usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
909		usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
910		usbduxsub->urbOut[i]->status = 0;
911		usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
912		errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
913		if (errFlag) {
914			dev_err(&usbduxsub->interface->dev,
915				"comedi_: ao: usb_submit_urb(%d) error %d\n",
916				i, errFlag);
917			return errFlag;
918		}
919	}
920	return 0;
921}
922
923static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
924			     struct comedi_cmd *cmd)
925{
926	int err = 0, tmp, i;
927	unsigned int tmpTimer;
928	struct usbduxsub *this_usbduxsub = dev->private;
929
930	if (!(this_usbduxsub->probed))
931		return -ENODEV;
932
933	dev_dbg(&this_usbduxsub->interface->dev,
934		"comedi%d: usbdux_ai_cmdtest\n", dev->minor);
935
936	/* make sure triggers are valid */
937	/* Only immediate triggers are allowed */
938	tmp = cmd->start_src;
939	cmd->start_src &= TRIG_NOW | TRIG_INT;
940	if (!cmd->start_src || tmp != cmd->start_src)
941		err++;
942
943	/* trigger should happen timed */
944	tmp = cmd->scan_begin_src;
945	/* start a new _scan_ with a timer */
946	cmd->scan_begin_src &= TRIG_TIMER;
947	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
948		err++;
949
950	/* scanning is continous */
951	tmp = cmd->convert_src;
952	cmd->convert_src &= TRIG_NOW;
953	if (!cmd->convert_src || tmp != cmd->convert_src)
954		err++;
955
956	/* issue a trigger when scan is finished and start a new scan */
957	tmp = cmd->scan_end_src;
958	cmd->scan_end_src &= TRIG_COUNT;
959	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
960		err++;
961
962	/* trigger at the end of count events or not, stop condition or not */
963	tmp = cmd->stop_src;
964	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
965	if (!cmd->stop_src || tmp != cmd->stop_src)
966		err++;
967
968	if (err)
969		return 1;
970
971	/*
972	 * step 2: make sure trigger sources are unique and mutually compatible
973	 * note that mutual compatiblity is not an issue here
974	 */
975	if (cmd->scan_begin_src != TRIG_FOLLOW &&
976		cmd->scan_begin_src != TRIG_EXT &&
977		cmd->scan_begin_src != TRIG_TIMER)
978		err++;
979	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
980		err++;
981
982	if (err)
983		return 2;
984
985	/* step 3: make sure arguments are trivially compatible */
986	if (cmd->start_arg != 0) {
987		cmd->start_arg = 0;
988		err++;
989	}
990
991	if (cmd->scan_begin_src == TRIG_FOLLOW) {
992		/* internal trigger */
993		if (cmd->scan_begin_arg != 0) {
994			cmd->scan_begin_arg = 0;
995			err++;
996		}
997	}
998
999	if (cmd->scan_begin_src == TRIG_TIMER) {
1000		if (this_usbduxsub->high_speed) {
1001			/*
1002			 * In high speed mode microframes are possible.
1003			 * However, during one microframe we can roughly
1004			 * sample one channel. Thus, the more channels
1005			 * are in the channel list the more time we need.
1006			 */
1007			i = 1;
1008			/* find a power of 2 for the number of channels */
1009			while (i < (cmd->chanlist_len))
1010				i = i * 2;
1011
1012			if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
1013				cmd->scan_begin_arg = 1000000 / 8 * i;
1014				err++;
1015			}
1016			/* now calc the real sampling rate with all the
1017			 * rounding errors */
1018			tmpTimer =
1019				((unsigned int)(cmd->scan_begin_arg / 125000)) *
1020				125000;
1021			if (cmd->scan_begin_arg != tmpTimer) {
1022				cmd->scan_begin_arg = tmpTimer;
1023				err++;
1024			}
1025		} else {
1026			/* full speed */
1027			/* 1kHz scans every USB frame */
1028			if (cmd->scan_begin_arg < 1000000) {
1029				cmd->scan_begin_arg = 1000000;
1030				err++;
1031			}
1032			/*
1033			 * calc the real sampling rate with the rounding errors
1034			 */
1035			tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
1036					1000000)) * 1000000;
1037			if (cmd->scan_begin_arg != tmpTimer) {
1038				cmd->scan_begin_arg = tmpTimer;
1039				err++;
1040			}
1041		}
1042	}
1043	/* the same argument */
1044	if (cmd->scan_end_arg != cmd->chanlist_len) {
1045		cmd->scan_end_arg = cmd->chanlist_len;
1046		err++;
1047	}
1048
1049	if (cmd->stop_src == TRIG_COUNT) {
1050		/* any count is allowed */
1051	} else {
1052		/* TRIG_NONE */
1053		if (cmd->stop_arg != 0) {
1054			cmd->stop_arg = 0;
1055			err++;
1056		}
1057	}
1058
1059	if (err)
1060		return 3;
1061
1062	return 0;
1063}
1064
1065/*
1066 * creates the ADC command for the MAX1271
1067 * range is the range value from comedi
1068 */
1069static int8_t create_adc_command(unsigned int chan, int range)
1070{
1071	int8_t p = (range <= 1);
1072	int8_t r = ((range % 2) == 0);
1073	return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
1074}
1075
1076/* bulk transfers to usbdux */
1077
1078#define SENDADCOMMANDS            0
1079#define SENDDACOMMANDS            1
1080#define SENDDIOCONFIGCOMMAND      2
1081#define SENDDIOBITSCOMMAND        3
1082#define SENDSINGLEAD              4
1083#define READCOUNTERCOMMAND        5
1084#define WRITECOUNTERCOMMAND       6
1085#define SENDPWMON                 7
1086#define SENDPWMOFF                8
1087
1088static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
1089{
1090	int result, nsent;
1091
1092	this_usbduxsub->dux_commands[0] = cmd_type;
1093#ifdef NOISY_DUX_DEBUGBUG
1094	printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
1095		this_usbduxsub->comedidev->minor);
1096	for (result = 0; result < SIZEOFDUXBUFFER; result++)
1097		printk(" %02x", this_usbduxsub->dux_commands[result]);
1098	printk("\n");
1099#endif
1100	result = usb_bulk_msg(this_usbduxsub->usbdev,
1101			      usb_sndbulkpipe(this_usbduxsub->usbdev,
1102					      COMMAND_OUT_EP),
1103			      this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
1104			      &nsent, 10);
1105	if (result < 0)
1106		dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1107			"could not transmit dux_command to the usb-device, "
1108			"err=%d\n", this_usbduxsub->comedidev->minor, result);
1109
1110	return result;
1111}
1112
1113static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
1114{
1115	int result = (-EFAULT);
1116	int nrec;
1117	int i;
1118
1119	for (i = 0; i < RETRIES; i++) {
1120		result = usb_bulk_msg(this_usbduxsub->usbdev,
1121				      usb_rcvbulkpipe(this_usbduxsub->usbdev,
1122						      COMMAND_IN_EP),
1123				      this_usbduxsub->insnBuffer, SIZEINSNBUF,
1124				      &nrec, 1);
1125		if (result < 0) {
1126			dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1127				"insn: USB error %d while receiving DUX command"
1128				"\n", this_usbduxsub->comedidev->minor, result);
1129			return result;
1130		}
1131		if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command)
1132			return result;
1133	}
1134	/* this is only reached if the data has been requested a couple of
1135	 * times */
1136	dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
1137		"wrong data returned from firmware: want cmd %d, got cmd %d.\n",
1138		this_usbduxsub->comedidev->minor, command,
1139		le16_to_cpu(this_usbduxsub->insnBuffer[0]));
1140	return -EFAULT;
1141}
1142
1143static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
1144			     unsigned int trignum)
1145{
1146	int ret;
1147	struct usbduxsub *this_usbduxsub = dev->private;
1148	if (!this_usbduxsub)
1149		return -EFAULT;
1150
1151	down(&this_usbduxsub->sem);
1152	if (!(this_usbduxsub->probed)) {
1153		up(&this_usbduxsub->sem);
1154		return -ENODEV;
1155	}
1156	dev_dbg(&this_usbduxsub->interface->dev,
1157		"comedi%d: usbdux_ai_inttrig\n", dev->minor);
1158
1159	if (trignum != 0) {
1160		dev_err(&this_usbduxsub->interface->dev,
1161			"comedi%d: usbdux_ai_inttrig: invalid trignum\n",
1162			dev->minor);
1163		up(&this_usbduxsub->sem);
1164		return -EINVAL;
1165	}
1166	if (!(this_usbduxsub->ai_cmd_running)) {
1167		this_usbduxsub->ai_cmd_running = 1;
1168		ret = usbduxsub_submit_InURBs(this_usbduxsub);
1169		if (ret < 0) {
1170			dev_err(&this_usbduxsub->interface->dev,
1171				"comedi%d: usbdux_ai_inttrig: "
1172				"urbSubmit: err=%d\n", dev->minor, ret);
1173			this_usbduxsub->ai_cmd_running = 0;
1174			up(&this_usbduxsub->sem);
1175			return ret;
1176		}
1177		s->async->inttrig = NULL;
1178	} else {
1179		dev_err(&this_usbduxsub->interface->dev,
1180			"comedi%d: ai_inttrig but acqu is already running\n",
1181			dev->minor);
1182	}
1183	up(&this_usbduxsub->sem);
1184	return 1;
1185}
1186
1187static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1188{
1189	struct comedi_cmd *cmd = &s->async->cmd;
1190	unsigned int chan, range;
1191	int i, ret;
1192	struct usbduxsub *this_usbduxsub = dev->private;
1193	int result;
1194
1195	if (!this_usbduxsub)
1196		return -EFAULT;
1197
1198	dev_dbg(&this_usbduxsub->interface->dev,
1199		"comedi%d: usbdux_ai_cmd\n", dev->minor);
1200
1201	/* block other CPUs from starting an ai_cmd */
1202	down(&this_usbduxsub->sem);
1203
1204	if (!(this_usbduxsub->probed)) {
1205		up(&this_usbduxsub->sem);
1206		return -ENODEV;
1207	}
1208	if (this_usbduxsub->ai_cmd_running) {
1209		dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
1210			"ai_cmd not possible. Another ai_cmd is running.\n",
1211			dev->minor);
1212		up(&this_usbduxsub->sem);
1213		return -EBUSY;
1214	}
1215	/* set current channel of the running aquisition to zero */
1216	s->async->cur_chan = 0;
1217
1218	this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
1219	for (i = 0; i < cmd->chanlist_len; ++i) {
1220		chan = CR_CHAN(cmd->chanlist[i]);
1221		range = CR_RANGE(cmd->chanlist[i]);
1222		if (i >= NUMCHANNELS) {
1223			dev_err(&this_usbduxsub->interface->dev,
1224				"comedi%d: channel list too long\n",
1225				dev->minor);
1226			break;
1227		}
1228		this_usbduxsub->dux_commands[i + 2] =
1229			create_adc_command(chan, range);
1230	}
1231
1232	dev_dbg(&this_usbduxsub->interface->dev,
1233		"comedi %d: sending commands to the usb device: size=%u\n",
1234		dev->minor, NUMCHANNELS);
1235
1236	result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
1237	if (result < 0) {
1238		up(&this_usbduxsub->sem);
1239		return result;
1240	}
1241
1242	if (this_usbduxsub->high_speed) {
1243		/*
1244		 * every channel gets a time window of 125us. Thus, if we
1245		 * sample all 8 channels we need 1ms. If we sample only one
1246		 * channel we need only 125us
1247		 */
1248		this_usbduxsub->ai_interval = 1;
1249		/* find a power of 2 for the interval */
1250		while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
1251			this_usbduxsub->ai_interval =
1252				(this_usbduxsub->ai_interval) * 2;
1253		}
1254		this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
1255			(this_usbduxsub->ai_interval));
1256	} else {
1257		/* interval always 1ms */
1258		this_usbduxsub->ai_interval = 1;
1259		this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
1260	}
1261	if (this_usbduxsub->ai_timer < 1) {
1262		dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
1263			"timer=%d, scan_begin_arg=%d. "
1264			"Not properly tested by cmdtest?\n", dev->minor,
1265			this_usbduxsub->ai_timer, cmd->scan_begin_arg);
1266		up(&this_usbduxsub->sem);
1267		return -EINVAL;
1268	}
1269	this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
1270
1271	if (cmd->stop_src == TRIG_COUNT) {
1272		/* data arrives as one packet */
1273		this_usbduxsub->ai_sample_count = cmd->stop_arg;
1274		this_usbduxsub->ai_continous = 0;
1275	} else {
1276		/* continous aquisition */
1277		this_usbduxsub->ai_continous = 1;
1278		this_usbduxsub->ai_sample_count = 0;
1279	}
1280
1281	if (cmd->start_src == TRIG_NOW) {
1282		/* enable this acquisition operation */
1283		this_usbduxsub->ai_cmd_running = 1;
1284		ret = usbduxsub_submit_InURBs(this_usbduxsub);
1285		if (ret < 0) {
1286			this_usbduxsub->ai_cmd_running = 0;
1287			/* fixme: unlink here?? */
1288			up(&this_usbduxsub->sem);
1289			return ret;
1290		}
1291		s->async->inttrig = NULL;
1292	} else {
1293		/* TRIG_INT */
1294		/* don't enable the acquision operation */
1295		/* wait for an internal signal */
1296		s->async->inttrig = usbdux_ai_inttrig;
1297	}
1298	up(&this_usbduxsub->sem);
1299	return 0;
1300}
1301
1302/* Mode 0 is used to get a single conversion on demand */
1303static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
1304			       struct comedi_insn *insn, unsigned int *data)
1305{
1306	int i;
1307	unsigned int one = 0;
1308	int chan, range;
1309	int err;
1310	struct usbduxsub *this_usbduxsub = dev->private;
1311
1312	if (!this_usbduxsub)
1313		return 0;
1314
1315	dev_dbg(&this_usbduxsub->interface->dev,
1316		"comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
1317		dev->minor, insn->n, insn->subdev);
1318
1319	down(&this_usbduxsub->sem);
1320	if (!(this_usbduxsub->probed)) {
1321		up(&this_usbduxsub->sem);
1322		return -ENODEV;
1323	}
1324	if (this_usbduxsub->ai_cmd_running) {
1325		dev_err(&this_usbduxsub->interface->dev,
1326			"comedi%d: ai_insn_read not possible. "
1327			"Async Command is running.\n", dev->minor);
1328		up(&this_usbduxsub->sem);
1329		return 0;
1330	}
1331
1332	/* sample one channel */
1333	chan = CR_CHAN(insn->chanspec);
1334	range = CR_RANGE(insn->chanspec);
1335	/* set command for the first channel */
1336	this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
1337
1338	/* adc commands */
1339	err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1340	if (err < 0) {
1341		up(&this_usbduxsub->sem);
1342		return err;
1343	}
1344
1345	for (i = 0; i < insn->n; i++) {
1346		err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1347		if (err < 0) {
1348			up(&this_usbduxsub->sem);
1349			return 0;
1350		}
1351		one = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1352		if (CR_RANGE(insn->chanspec) <= 1)
1353			one = one ^ 0x800;
1354
1355		data[i] = one;
1356	}
1357	up(&this_usbduxsub->sem);
1358	return i;
1359}
1360
1361/************************************/
1362/* analog out */
1363
1364static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
1365			       struct comedi_insn *insn, unsigned int *data)
1366{
1367	int i;
1368	int chan = CR_CHAN(insn->chanspec);
1369	struct usbduxsub *this_usbduxsub = dev->private;
1370
1371	if (!this_usbduxsub)
1372		return -EFAULT;
1373
1374	down(&this_usbduxsub->sem);
1375	if (!(this_usbduxsub->probed)) {
1376		up(&this_usbduxsub->sem);
1377		return -ENODEV;
1378	}
1379	for (i = 0; i < insn->n; i++)
1380		data[i] = this_usbduxsub->outBuffer[chan];
1381
1382	up(&this_usbduxsub->sem);
1383	return i;
1384}
1385
1386static int usbdux_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
1387				struct comedi_insn *insn, unsigned int *data)
1388{
1389	int i, err;
1390	int chan = CR_CHAN(insn->chanspec);
1391	struct usbduxsub *this_usbduxsub = dev->private;
1392
1393	if (!this_usbduxsub)
1394		return -EFAULT;
1395
1396	dev_dbg(&this_usbduxsub->interface->dev,
1397		"comedi%d: ao_insn_write\n", dev->minor);
1398
1399	down(&this_usbduxsub->sem);
1400	if (!(this_usbduxsub->probed)) {
1401		up(&this_usbduxsub->sem);
1402		return -ENODEV;
1403	}
1404	if (this_usbduxsub->ao_cmd_running) {
1405		dev_err(&this_usbduxsub->interface->dev,
1406			"comedi%d: ao_insn_write: "
1407			"ERROR: asynchronous ao_cmd is running\n", dev->minor);
1408		up(&this_usbduxsub->sem);
1409		return 0;
1410	}
1411
1412	for (i = 0; i < insn->n; i++) {
1413		dev_dbg(&this_usbduxsub->interface->dev,
1414			"comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1415			dev->minor, chan, i, data[i]);
1416
1417		/* number of channels: 1 */
1418		this_usbduxsub->dux_commands[1] = 1;
1419		/* one 16 bit value */
1420		*((int16_t *) (this_usbduxsub->dux_commands + 2)) =
1421			cpu_to_le16(data[i]);
1422		this_usbduxsub->outBuffer[chan] = data[i];
1423		/* channel number */
1424		this_usbduxsub->dux_commands[4] = (chan << 6);
1425		err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
1426		if (err < 0) {
1427			up(&this_usbduxsub->sem);
1428			return err;
1429		}
1430	}
1431	up(&this_usbduxsub->sem);
1432
1433	return i;
1434}
1435
1436static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
1437			     unsigned int trignum)
1438{
1439	int ret;
1440	struct usbduxsub *this_usbduxsub = dev->private;
1441
1442	if (!this_usbduxsub)
1443		return -EFAULT;
1444
1445	down(&this_usbduxsub->sem);
1446	if (!(this_usbduxsub->probed)) {
1447		up(&this_usbduxsub->sem);
1448		return -ENODEV;
1449	}
1450	if (trignum != 0) {
1451		dev_err(&this_usbduxsub->interface->dev,
1452			"comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1453			dev->minor);
1454		return -EINVAL;
1455	}
1456	if (!(this_usbduxsub->ao_cmd_running)) {
1457		this_usbduxsub->ao_cmd_running = 1;
1458		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1459		if (ret < 0) {
1460			dev_err(&this_usbduxsub->interface->dev,
1461				"comedi%d: usbdux_ao_inttrig: submitURB: "
1462				"err=%d\n", dev->minor, ret);
1463			this_usbduxsub->ao_cmd_running = 0;
1464			up(&this_usbduxsub->sem);
1465			return ret;
1466		}
1467		s->async->inttrig = NULL;
1468	} else {
1469		dev_err(&this_usbduxsub->interface->dev,
1470			"comedi%d: ao_inttrig but acqu is already running.\n",
1471			dev->minor);
1472	}
1473	up(&this_usbduxsub->sem);
1474	return 1;
1475}
1476
1477static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1478			     struct comedi_cmd *cmd)
1479{
1480	int err = 0, tmp;
1481	struct usbduxsub *this_usbduxsub = dev->private;
1482
1483	if (!this_usbduxsub)
1484		return -EFAULT;
1485
1486	if (!(this_usbduxsub->probed))
1487		return -ENODEV;
1488
1489	dev_dbg(&this_usbduxsub->interface->dev,
1490		"comedi%d: usbdux_ao_cmdtest\n", dev->minor);
1491
1492	/* make sure triggers are valid */
1493	/* Only immediate triggers are allowed */
1494	tmp = cmd->start_src;
1495	cmd->start_src &= TRIG_NOW | TRIG_INT;
1496	if (!cmd->start_src || tmp != cmd->start_src)
1497		err++;
1498
1499	/* trigger should happen timed */
1500	tmp = cmd->scan_begin_src;
1501	/* just now we scan also in the high speed mode every frame */
1502	/* this is due to ehci driver limitations */
1503	if (0) {		/* (this_usbduxsub->high_speed) */
1504		/* start immidiately a new scan */
1505		/* the sampling rate is set by the coversion rate */
1506		cmd->scan_begin_src &= TRIG_FOLLOW;
1507	} else {
1508		/* start a new scan (output at once) with a timer */
1509		cmd->scan_begin_src &= TRIG_TIMER;
1510	}
1511	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1512		err++;
1513
1514	/* scanning is continous */
1515	tmp = cmd->convert_src;
1516	/* we always output at 1kHz just now all channels at once */
1517	if (0) {		/* (this_usbduxsub->high_speed) */
1518		/*
1519		 * in usb-2.0 only one conversion it tranmitted but with 8kHz/n
1520		 */
1521		cmd->convert_src &= TRIG_TIMER;
1522	} else {
1523		/* all conversion events happen simultaneously with a rate of
1524		 * 1kHz/n */
1525		cmd->convert_src &= TRIG_NOW;
1526	}
1527	if (!cmd->convert_src || tmp != cmd->convert_src)
1528		err++;
1529
1530	/* issue a trigger when scan is finished and start a new scan */
1531	tmp = cmd->scan_end_src;
1532	cmd->scan_end_src &= TRIG_COUNT;
1533	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1534		err++;
1535
1536	/* trigger at the end of count events or not, stop condition or not */
1537	tmp = cmd->stop_src;
1538	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1539	if (!cmd->stop_src || tmp != cmd->stop_src)
1540		err++;
1541
1542	if (err)
1543		return 1;
1544
1545	/*
1546	 * step 2: make sure trigger sources are unique and mutually compatible
1547	 * note that mutual compatiblity is not an issue here
1548	 */
1549	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1550		cmd->scan_begin_src != TRIG_EXT &&
1551		cmd->scan_begin_src != TRIG_TIMER)
1552		err++;
1553	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1554		err++;
1555
1556	if (err)
1557		return 2;
1558
1559	/* step 3: make sure arguments are trivially compatible */
1560
1561	if (cmd->start_arg != 0) {
1562		cmd->start_arg = 0;
1563		err++;
1564	}
1565
1566	if (cmd->scan_begin_src == TRIG_FOLLOW) {
1567		/* internal trigger */
1568		if (cmd->scan_begin_arg != 0) {
1569			cmd->scan_begin_arg = 0;
1570			err++;
1571		}
1572	}
1573
1574	if (cmd->scan_begin_src == TRIG_TIMER) {
1575		/* timer */
1576		if (cmd->scan_begin_arg < 1000000) {
1577			cmd->scan_begin_arg = 1000000;
1578			err++;
1579		}
1580	}
1581	/* not used now, is for later use */
1582	if (cmd->convert_src == TRIG_TIMER) {
1583		if (cmd->convert_arg < 125000) {
1584			cmd->convert_arg = 125000;
1585			err++;
1586		}
1587	}
1588
1589	/* the same argument */
1590	if (cmd->scan_end_arg != cmd->chanlist_len) {
1591		cmd->scan_end_arg = cmd->chanlist_len;
1592		err++;
1593	}
1594
1595	if (cmd->stop_src == TRIG_COUNT) {
1596		/* any count is allowed */
1597	} else {
1598		/* TRIG_NONE */
1599		if (cmd->stop_arg != 0) {
1600			cmd->stop_arg = 0;
1601			err++;
1602		}
1603	}
1604
1605	dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, "
1606		"scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, "
1607		"convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src,
1608		cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
1609
1610	if (err)
1611		return 3;
1612
1613	return 0;
1614}
1615
1616static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1617{
1618	struct comedi_cmd *cmd = &s->async->cmd;
1619	unsigned int chan, gain;
1620	int i, ret;
1621	struct usbduxsub *this_usbduxsub = dev->private;
1622
1623	if (!this_usbduxsub)
1624		return -EFAULT;
1625
1626	down(&this_usbduxsub->sem);
1627	if (!(this_usbduxsub->probed)) {
1628		up(&this_usbduxsub->sem);
1629		return -ENODEV;
1630	}
1631	dev_dbg(&this_usbduxsub->interface->dev,
1632		"comedi%d: %s\n", dev->minor, __func__);
1633
1634	/* set current channel of the running aquisition to zero */
1635	s->async->cur_chan = 0;
1636	for (i = 0; i < cmd->chanlist_len; ++i) {
1637		chan = CR_CHAN(cmd->chanlist[i]);
1638		gain = CR_RANGE(cmd->chanlist[i]);
1639		if (i >= NUMOUTCHANNELS) {
1640			dev_err(&this_usbduxsub->interface->dev,
1641				"comedi%d: %s: channel list too long\n",
1642				dev->minor, __func__);
1643			break;
1644		}
1645		this_usbduxsub->dac_commands[i] = (chan << 6);
1646		dev_dbg(&this_usbduxsub->interface->dev,
1647			"comedi%d: dac command for ch %d is %x\n",
1648			dev->minor, i, this_usbduxsub->dac_commands[i]);
1649	}
1650
1651	/* we count in steps of 1ms (125us) */
1652	/* 125us mode not used yet */
1653	if (0) {		/* (this_usbduxsub->high_speed) */
1654		/* 125us */
1655		/* timing of the conversion itself: every 125 us */
1656		this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1657	} else {
1658		/* 1ms */
1659		/* timing of the scan: we get all channels at once */
1660		this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1661		dev_dbg(&this_usbduxsub->interface->dev,
1662			"comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
1663			"convert_src=%d, convert_arg=%d\n", dev->minor,
1664			cmd->scan_begin_src, cmd->scan_begin_arg,
1665			cmd->convert_src, cmd->convert_arg);
1666		dev_dbg(&this_usbduxsub->interface->dev,
1667			"comedi%d: ao_timer=%d (ms)\n",
1668			dev->minor, this_usbduxsub->ao_timer);
1669		if (this_usbduxsub->ao_timer < 1) {
1670			dev_err(&this_usbduxsub->interface->dev,
1671				"comedi%d: usbdux: ao_timer=%d, "
1672				"scan_begin_arg=%d. "
1673				"Not properly tested by cmdtest?\n",
1674				dev->minor, this_usbduxsub->ao_timer,
1675				cmd->scan_begin_arg);
1676			up(&this_usbduxsub->sem);
1677			return -EINVAL;
1678		}
1679	}
1680	this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1681
1682	if (cmd->stop_src == TRIG_COUNT) {
1683		/* not continous */
1684		/* counter */
1685		/* high speed also scans everything at once */
1686		if (0) {	/* (this_usbduxsub->high_speed) */
1687			this_usbduxsub->ao_sample_count =
1688				(cmd->stop_arg) * (cmd->scan_end_arg);
1689		} else {
1690			/* there's no scan as the scan has been */
1691			/* perf inside the FX2 */
1692			/* data arrives as one packet */
1693			this_usbduxsub->ao_sample_count = cmd->stop_arg;
1694		}
1695		this_usbduxsub->ao_continous = 0;
1696	} else {
1697		/* continous aquisition */
1698		this_usbduxsub->ao_continous = 1;
1699		this_usbduxsub->ao_sample_count = 0;
1700	}
1701
1702	if (cmd->start_src == TRIG_NOW) {
1703		/* enable this acquisition operation */
1704		this_usbduxsub->ao_cmd_running = 1;
1705		ret = usbduxsub_submit_OutURBs(this_usbduxsub);
1706		if (ret < 0) {
1707			this_usbduxsub->ao_cmd_running = 0;
1708			/* fixme: unlink here?? */
1709			up(&this_usbduxsub->sem);
1710			return ret;
1711		}
1712		s->async->inttrig = NULL;
1713	} else {
1714		/* TRIG_INT */
1715		/* submit the urbs later */
1716		/* wait for an internal signal */
1717		s->async->inttrig = usbdux_ao_inttrig;
1718	}
1719
1720	up(&this_usbduxsub->sem);
1721	return 0;
1722}
1723
1724static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s,
1725				  struct comedi_insn *insn, unsigned int *data)
1726{
1727	int chan = CR_CHAN(insn->chanspec);
1728
1729	/* The input or output configuration of each digital line is
1730	 * configured by a special insn_config instruction.  chanspec
1731	 * contains the channel to be changed, and data[0] contains the
1732	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
1733
1734	switch (data[0]) {
1735	case INSN_CONFIG_DIO_OUTPUT:
1736		s->io_bits |= 1 << chan;	/* 1 means Out */
1737		break;
1738	case INSN_CONFIG_DIO_INPUT:
1739		s->io_bits &= ~(1 << chan);
1740		break;
1741	case INSN_CONFIG_DIO_QUERY:
1742		data[1] =
1743			(s->
1744			io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1745		break;
1746	default:
1747		return -EINVAL;
1748		break;
1749	}
1750	/* we don't tell the firmware here as it would take 8 frames */
1751	/* to submit the information. We do it in the insn_bits. */
1752	return insn->n;
1753}
1754
1755static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
1756				struct comedi_insn *insn, unsigned int *data)
1757{
1758
1759	struct usbduxsub *this_usbduxsub = dev->private;
1760	int err;
1761
1762	if (!this_usbduxsub)
1763		return -EFAULT;
1764
1765
1766	if (insn->n != 2)
1767		return -EINVAL;
1768
1769	down(&this_usbduxsub->sem);
1770
1771	if (!(this_usbduxsub->probed)) {
1772		up(&this_usbduxsub->sem);
1773		return -ENODEV;
1774	}
1775
1776	/* The insn data is a mask in data[0] and the new data
1777	 * in data[1], each channel cooresponding to a bit. */
1778	s->state &= ~data[0];
1779	s->state |= data[0] & data[1];
1780	this_usbduxsub->dux_commands[1] = s->io_bits;
1781	this_usbduxsub->dux_commands[2] = s->state;
1782
1783	/* This command also tells the firmware to return */
1784	/* the digital input lines */
1785	err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1786	if (err < 0) {
1787		up(&this_usbduxsub->sem);
1788		return err;
1789	}
1790	err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1791	if (err < 0) {
1792		up(&this_usbduxsub->sem);
1793		return err;
1794	}
1795
1796	data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
1797	up(&this_usbduxsub->sem);
1798	return 2;
1799}
1800
1801/* reads the 4 counters, only two are used just now */
1802static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s,
1803			       struct comedi_insn *insn, unsigned int *data)
1804{
1805	struct usbduxsub *this_usbduxsub = dev->private;
1806	int chan = insn->chanspec;
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	err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1820	if (err < 0) {
1821		up(&this_usbduxsub->sem);
1822		return err;
1823	}
1824
1825	err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
1826	if (err < 0) {
1827		up(&this_usbduxsub->sem);
1828		return err;
1829	}
1830
1831	data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]);
1832	up(&this_usbduxsub->sem);
1833	return 1;
1834}
1835
1836static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s,
1837				struct comedi_insn *insn, unsigned int *data)
1838{
1839	struct usbduxsub *this_usbduxsub = dev->private;
1840	int err;
1841
1842	if (!this_usbduxsub)
1843		return -EFAULT;
1844
1845	down(&this_usbduxsub->sem);
1846
1847	if (!(this_usbduxsub->probed)) {
1848		up(&this_usbduxsub->sem);
1849		return -ENODEV;
1850	}
1851
1852	this_usbduxsub->dux_commands[1] = insn->chanspec;
1853	*((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
1854
1855	err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
1856	if (err < 0) {
1857		up(&this_usbduxsub->sem);
1858		return err;
1859	}
1860
1861	up(&this_usbduxsub->sem);
1862
1863	return 1;
1864}
1865
1866static int usbdux_counter_config(struct comedi_device *dev, struct comedi_subdevice *s,
1867				 struct comedi_insn *insn, unsigned int *data)
1868{
1869	/* nothing to do so far */
1870	return 2;
1871}
1872
1873/***********************************/
1874/* PWM */
1875
1876static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
1877{
1878	int err = 0;
1879
1880	if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
1881		if (usbduxsub_tmp->urbPwm)
1882			usb_kill_urb(usbduxsub_tmp->urbPwm);
1883		dev_dbg(&usbduxsub_tmp->interface->dev,
1884			"comedi: unlinked PwmURB: res=%d\n", err);
1885	}
1886	return err;
1887}
1888
1889/* This cancels a running acquisition operation
1890 * in any context.
1891 */
1892static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
1893{
1894	int ret = 0;
1895
1896	if (!this_usbduxsub)
1897		return -EFAULT;
1898
1899	dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
1900	if (do_unlink)
1901		ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
1902
1903
1904	this_usbduxsub->pwm_cmd_running = 0;
1905
1906	return ret;
1907}
1908
1909/* force unlink - is called by comedi */
1910static int usbdux_pwm_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1911{
1912	struct usbduxsub *this_usbduxsub = dev->private;
1913	int res = 0;
1914
1915	/* unlink only if it is really running */
1916	res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
1917
1918	dev_dbg(&this_usbduxsub->interface->dev,
1919		"comedi %d: sending pwm off command to the usb device.\n",
1920		dev->minor);
1921	res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
1922	if (res < 0)
1923		return res;
1924
1925	return res;
1926}
1927
1928static void usbduxsub_pwm_irq(struct urb *urb)
1929{
1930	int ret;
1931	struct usbduxsub *this_usbduxsub;
1932	struct comedi_device *this_comedidev;
1933	struct comedi_subdevice *s;
1934
1935	/* printk(KERN_DEBUG "PWM: IRQ\n"); */
1936
1937	/* the context variable points to the subdevice */
1938	this_comedidev = urb->context;
1939	/* the private structure of the subdevice is struct usbduxsub */
1940	this_usbduxsub = this_comedidev->private;
1941
1942	s = this_comedidev->subdevices + SUBDEV_DA;
1943
1944	switch (urb->status) {
1945	case 0:
1946		/* success */
1947		break;
1948
1949	case -ECONNRESET:
1950	case -ENOENT:
1951	case -ESHUTDOWN:
1952	case -ECONNABORTED:
1953		/*
1954		 * after an unlink command, unplug, ... etc
1955		 * no unlink needed here. Already shutting down.
1956		 */
1957		if (this_usbduxsub->pwm_cmd_running)
1958			usbdux_pwm_stop(this_usbduxsub, 0);
1959
1960		return;
1961
1962	default:
1963		/* a real error */
1964		if (this_usbduxsub->pwm_cmd_running) {
1965			dev_err(&this_usbduxsub->interface->dev,
1966				"comedi_: Non-zero urb status received in "
1967				"pwm intr context: %d\n", urb->status);
1968			usbdux_pwm_stop(this_usbduxsub, 0);
1969		}
1970		return;
1971	}
1972
1973	/* are we actually running? */
1974	if (!(this_usbduxsub->pwm_cmd_running))
1975		return;
1976
1977	urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
1978	urb->dev = this_usbduxsub->usbdev;
1979	urb->status = 0;
1980	if (this_usbduxsub->pwm_cmd_running) {
1981		ret = usb_submit_urb(urb, GFP_ATOMIC);
1982		if (ret < 0) {
1983			dev_err(&this_usbduxsub->interface->dev,
1984				"comedi_: pwm urb resubm failed in int-cont. "
1985				"ret=%d", ret);
1986			if (ret == EL2NSYNC)
1987				dev_err(&this_usbduxsub->interface->dev,
1988					"buggy USB host controller or bug in "
1989					"IRQ handling!\n");
1990
1991			/* don't do an unlink here */
1992			usbdux_pwm_stop(this_usbduxsub, 0);
1993		}
1994	}
1995}
1996
1997static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
1998{
1999	int errFlag;
2000
2001	if (!usbduxsub)
2002		return -EFAULT;
2003
2004	dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
2005
2006	/* in case of a resubmission after an unlink... */
2007	usb_fill_bulk_urb(usbduxsub->urbPwm,
2008		usbduxsub->usbdev,
2009		usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
2010		usbduxsub->urbPwm->transfer_buffer,
2011		usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, usbduxsub->comedidev);
2012
2013	errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
2014	if (errFlag) {
2015		dev_err(&usbduxsub->interface->dev,
2016			"comedi_: usbdux: pwm: usb_submit_urb error %d\n",
2017			errFlag);
2018		return errFlag;
2019	}
2020	return 0;
2021}
2022
2023static int usbdux_pwm_period(struct comedi_device *dev, struct comedi_subdevice *s,
2024			     unsigned int period)
2025{
2026	struct usbduxsub *this_usbduxsub = dev->private;
2027	int fx2delay = 255;
2028
2029	if (period < MIN_PWM_PERIOD) {
2030		dev_err(&this_usbduxsub->interface->dev,
2031			"comedi%d: illegal period setting for pwm.\n",
2032			dev->minor);
2033		return -EAGAIN;
2034	} else {
2035		fx2delay = period / ((int)(6*512*(1.0/0.033))) - 6;
2036		if (fx2delay > 255) {
2037			dev_err(&this_usbduxsub->interface->dev,
2038				"comedi%d: period %d for pwm is too low.\n",
2039			       dev->minor, period);
2040			return -EAGAIN;
2041		}
2042	}
2043	this_usbduxsub->pwmDelay = fx2delay;
2044	this_usbduxsub->pwmPeriod = period;
2045	dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
2046		__func__, period, fx2delay);
2047	return 0;
2048}
2049
2050/* is called from insn so there's no need to do all the sanity checks */
2051static int usbdux_pwm_start(struct comedi_device *dev, struct comedi_subdevice *s)
2052{
2053	int ret, i;
2054	struct usbduxsub *this_usbduxsub = dev->private;
2055
2056	dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
2057		dev->minor, __func__);
2058
2059	if (this_usbduxsub->pwm_cmd_running) {
2060		/* already running */
2061		return 0;
2062	}
2063
2064	this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay);
2065	ret = send_dux_commands(this_usbduxsub, SENDPWMON);
2066	if (ret < 0)
2067		return ret;
2068
2069	/* initalise the buffer */
2070	for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
2071		((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
2072
2073	this_usbduxsub->pwm_cmd_running = 1;
2074	ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
2075	if (ret < 0) {
2076		this_usbduxsub->pwm_cmd_running = 0;
2077		return ret;
2078	}
2079	return 0;
2080}
2081
2082/* generates the bit pattern for PWM with the optional sign bit */
2083static int usbdux_pwm_pattern(struct comedi_device *dev, struct comedi_subdevice *s,
2084			      int channel, unsigned int value, unsigned int sign)
2085{
2086	struct usbduxsub *this_usbduxsub = dev->private;
2087	int i, szbuf;
2088	char *pBuf;
2089	char pwm_mask;
2090	char sgn_mask;
2091	char c;
2092
2093	if (!this_usbduxsub)
2094		return -EFAULT;
2095
2096	/* this is the DIO bit which carries the PWM data */
2097	pwm_mask = (1 << channel);
2098	/* this is the DIO bit which carries the optional direction bit */
2099	sgn_mask = (16 << channel);
2100	/* this is the buffer which will be filled with the with bit */
2101	/* pattern for one period */
2102	szbuf = this_usbduxsub->sizePwmBuf;
2103	pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
2104	for (i = 0; i < szbuf; i++) {
2105		c = *pBuf;
2106		/* reset bits */
2107		c = c & (~pwm_mask);
2108		/* set the bit as long as the index is lower than the value */
2109		if (i < value)
2110			c = c | pwm_mask;
2111		/* set the optional sign bit for a relay */
2112		if (!sign) {
2113			/* positive value */
2114			c = c & (~sgn_mask);
2115		} else {
2116			/* negative value */
2117			c = c | sgn_mask;
2118		}
2119		*(pBuf++) = c;
2120	}
2121	return 1;
2122}
2123
2124static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s,
2125			    struct comedi_insn *insn, unsigned int *data)
2126{
2127	struct usbduxsub *this_usbduxsub = dev->private;
2128
2129	if (!this_usbduxsub)
2130		return -EFAULT;
2131
2132	if ((insn->n) != 1) {
2133		/*
2134		 * doesn't make sense to have more than one value here because
2135		 * it would just overwrite the PWM buffer a couple of times
2136		 */
2137		return -EINVAL;
2138	}
2139
2140	/*
2141	 * the sign is set via a special INSN only, this gives us 8 bits for
2142	 * normal operation
2143	 * relay sign 0 by default
2144	 */
2145	return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec),
2146				  data[0], 0);
2147}
2148
2149static int usbdux_pwm_read(struct comedi_device *x1, struct comedi_subdevice *x2,
2150			   struct comedi_insn *x3, unsigned int *x4)
2151{
2152	/* not needed */
2153	return -EINVAL;
2154};
2155
2156/* switches on/off PWM */
2157static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s,
2158			     struct comedi_insn *insn, unsigned int *data)
2159{
2160	struct usbduxsub *this_usbduxsub = dev->private;
2161	switch (data[0]) {
2162	case INSN_CONFIG_ARM:
2163		/* switch it on */
2164		dev_dbg(&this_usbduxsub->interface->dev,
2165			"comedi%d: %s: pwm on\n", dev->minor, __func__);
2166		/*
2167		 * if not zero the PWM is limited to a certain time which is
2168		 * not supported here
2169		 */
2170		if (data[1] != 0)
2171			return -EINVAL;
2172		return usbdux_pwm_start(dev, s);
2173	case INSN_CONFIG_DISARM:
2174		dev_dbg(&this_usbduxsub->interface->dev,
2175			"comedi%d: %s: pwm off\n", dev->minor, __func__);
2176		return usbdux_pwm_cancel(dev, s);
2177	case INSN_CONFIG_GET_PWM_STATUS:
2178		/*
2179		 * to check if the USB transmission has failed or in case PWM
2180		 * was limited to n cycles to check if it has terminated
2181		 */
2182		data[1] = this_usbduxsub->pwm_cmd_running;
2183		return 0;
2184	case INSN_CONFIG_PWM_SET_PERIOD:
2185		dev_dbg(&this_usbduxsub->interface->dev,
2186			"comedi%d: %s: setting period\n", dev->minor, __func__);
2187		return usbdux_pwm_period(dev, s, data[1]);
2188	case INSN_CONFIG_PWM_GET_PERIOD:
2189		data[1] = this_usbduxsub->pwmPeriod;
2190		return 0;
2191	case INSN_CONFIG_PWM_SET_H_BRIDGE:
2192		/* value in the first byte and the sign in the second for a
2193		   relay */
2194		return usbdux_pwm_pattern(dev, s,
2195					  /* the channel number */
2196					  CR_CHAN(insn->chanspec),
2197					  /* actual PWM data */
2198					  data[1],
2199					  /* just a sign */
2200					  (data[2] != 0));
2201	case INSN_CONFIG_PWM_GET_H_BRIDGE:
2202		/* values are not kept in this driver, nothing to return here */
2203		return -EINVAL;
2204	}
2205	return -EINVAL;
2206}
2207
2208/* end of PWM */
2209/*****************************************************************/
2210
2211static void tidy_up(struct usbduxsub *usbduxsub_tmp)
2212{
2213	int i;
2214
2215	if (!usbduxsub_tmp)
2216		return;
2217	dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
2218
2219	/* shows the usb subsystem that the driver is down */
2220	if (usbduxsub_tmp->interface)
2221		usb_set_intfdata(usbduxsub_tmp->interface, NULL);
2222
2223	usbduxsub_tmp->probed = 0;
2224
2225	if (usbduxsub_tmp->urbIn) {
2226		if (usbduxsub_tmp->ai_cmd_running) {
2227			usbduxsub_tmp->ai_cmd_running = 0;
2228			usbduxsub_unlink_InURBs(usbduxsub_tmp);
2229		}
2230		for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
2231			kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
2232			usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
2233			usb_kill_urb(usbduxsub_tmp->urbIn[i]);
2234			usb_free_urb(usbduxsub_tmp->urbIn[i]);
2235			usbduxsub_tmp->urbIn[i] = NULL;
2236		}
2237		kfree(usbduxsub_tmp->urbIn);
2238		usbduxsub_tmp->urbIn = NULL;
2239	}
2240	if (usbduxsub_tmp->urbOut) {
2241		if (usbduxsub_tmp->ao_cmd_running) {
2242			usbduxsub_tmp->ao_cmd_running = 0;
2243			usbduxsub_unlink_OutURBs(usbduxsub_tmp);
2244		}
2245		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
2246			if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
2247				kfree(usbduxsub_tmp->urbOut[i]->
2248					transfer_buffer);
2249				usbduxsub_tmp->urbOut[i]->transfer_buffer =
2250					NULL;
2251			}
2252			if (usbduxsub_tmp->urbOut[i]) {
2253				usb_kill_urb(usbduxsub_tmp->urbOut[i]);
2254				usb_free_urb(usbduxsub_tmp->urbOut[i]);
2255				usbduxsub_tmp->urbOut[i] = NULL;
2256			}
2257		}
2258		kfree(usbduxsub_tmp->urbOut);
2259		usbduxsub_tmp->urbOut = NULL;
2260	}
2261	if (usbduxsub_tmp->urbPwm) {
2262		if (usbduxsub_tmp->pwm_cmd_running) {
2263			usbduxsub_tmp->pwm_cmd_running = 0;
2264			usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
2265		}
2266		kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
2267		usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
2268		usb_kill_urb(usbduxsub_tmp->urbPwm);
2269		usb_free_urb(usbduxsub_tmp->urbPwm);
2270		usbduxsub_tmp->urbPwm = NULL;
2271	}
2272	kfree(usbduxsub_tmp->inBuffer);
2273	usbduxsub_tmp->inBuffer = NULL;
2274	kfree(usbduxsub_tmp->insnBuffer);
2275	usbduxsub_tmp->insnBuffer = NULL;
2276	kfree(usbduxsub_tmp->inBuffer);
2277	usbduxsub_tmp->inBuffer = NULL;
2278	kfree(usbduxsub_tmp->dac_commands);
2279	usbduxsub_tmp->dac_commands = NULL;
2280	kfree(usbduxsub_tmp->dux_commands);
2281	usbduxsub_tmp->dux_commands = NULL;
2282	usbduxsub_tmp->ai_cmd_running = 0;
2283	usbduxsub_tmp->ao_cmd_running = 0;
2284	usbduxsub_tmp->pwm_cmd_running = 0;
2285}
2286
2287static void usbdux_firmware_request_complete_handler(const struct firmware *fw,
2288						     void *context)
2289{
2290	struct usbduxsub *usbduxsub_tmp = context;
2291	struct usb_device *usbdev = usbduxsub_tmp->usbdev;
2292	int ret;
2293
2294	if (fw == NULL) {
2295		dev_err(&usbdev->dev,
2296			"Firmware complete handler without firmware!\n");
2297		return;
2298	}
2299
2300	/*
2301	 * we need to upload the firmware here because fw will be
2302	 * freed once we've left this function
2303	 */
2304	ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size);
2305
2306	if (ret) {
2307		dev_err(&usbdev->dev,
2308			"Could not upload firmware (err=%d)\n",
2309			ret);
2310		return;
2311	}
2312	comedi_usb_auto_config(usbdev, BOARDNAME);
2313}
2314
2315/* allocate memory for the urbs and initialise them */
2316static int usbduxsub_probe(struct usb_interface *uinterf,
2317			   const struct usb_device_id *id)
2318{
2319	struct usb_device *udev = interface_to_usbdev(uinterf);
2320	struct device *dev = &uinterf->dev;
2321	int i;
2322	int index;
2323	int ret;
2324
2325	dev_dbg(dev, "comedi_: usbdux_: "
2326		"finding a free structure for the usb-device\n");
2327
2328	down(&start_stop_sem);
2329	/* look for a free place in the usbdux array */
2330	index = -1;
2331	for (i = 0; i < NUMUSBDUX; i++) {
2332		if (!(usbduxsub[i].probed)) {
2333			index = i;
2334			break;
2335		}
2336	}
2337
2338	/* no more space */
2339	if (index == -1) {
2340		dev_err(dev, "Too many usbdux-devices connected.\n");
2341		up(&start_stop_sem);
2342		return -EMFILE;
2343	}
2344	dev_dbg(dev, "comedi_: usbdux: "
2345		"usbduxsub[%d] is ready to connect to comedi.\n", index);
2346
2347	init_MUTEX(&(usbduxsub[index].sem));
2348	/* save a pointer to the usb device */
2349	usbduxsub[index].usbdev = udev;
2350
2351	/* 2.6: save the interface itself */
2352	usbduxsub[index].interface = uinterf;
2353	/* get the interface number from the interface */
2354	usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
2355	/* hand the private data over to the usb subsystem */
2356	/* will be needed for disconnect */
2357	usb_set_intfdata(uinterf, &(usbduxsub[index]));
2358
2359	dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
2360
2361	/* test if it is high speed (USB 2.0) */
2362	usbduxsub[index].high_speed =
2363		(usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
2364
2365	/* create space for the commands of the DA converter */
2366	usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
2367	if (!usbduxsub[index].dac_commands) {
2368		dev_err(dev, "comedi_: usbdux: "
2369			"error alloc space for dac commands\n");
2370		tidy_up(&(usbduxsub[index]));
2371		up(&start_stop_sem);
2372		return -ENOMEM;
2373	}
2374	/* create space for the commands going to the usb device */
2375	usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
2376	if (!usbduxsub[index].dux_commands) {
2377		dev_err(dev, "comedi_: usbdux: "
2378			"error alloc space for dac commands\n");
2379		tidy_up(&(usbduxsub[index]));
2380		up(&start_stop_sem);
2381		return -ENOMEM;
2382	}
2383	/* create space for the in buffer and set it to zero */
2384	usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
2385	if (!(usbduxsub[index].inBuffer)) {
2386		dev_err(dev, "comedi_: usbdux: "
2387			"could not alloc space for inBuffer\n");
2388		tidy_up(&(usbduxsub[index]));
2389		up(&start_stop_sem);
2390		return -ENOMEM;
2391	}
2392	/* create space of the instruction buffer */
2393	usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
2394	if (!(usbduxsub[index].insnBuffer)) {
2395		dev_err(dev, "comedi_: usbdux: "
2396			"could not alloc space for insnBuffer\n");
2397		tidy_up(&(usbduxsub[index]));
2398		up(&start_stop_sem);
2399		return -ENOMEM;
2400	}
2401	/* create space for the outbuffer */
2402	usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
2403	if (!(usbduxsub[index].outBuffer)) {
2404		dev_err(dev, "comedi_: usbdux: "
2405			"could not alloc space for outBuffer\n");
2406		tidy_up(&(usbduxsub[index]));
2407		up(&start_stop_sem);
2408		return -ENOMEM;
2409	}
2410	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
2411	i = usb_set_interface(usbduxsub[index].usbdev,
2412			      usbduxsub[index].ifnum, 3);
2413	if (i < 0) {
2414		dev_err(dev, "comedi_: usbdux%d: "
2415			"could not set alternate setting 3 in high speed.\n",
2416			index);
2417		tidy_up(&(usbduxsub[index]));
2418		up(&start_stop_sem);
2419		return -ENODEV;
2420	}
2421	if (usbduxsub[index].high_speed)
2422		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
2423	else
2424		usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
2425
2426	usbduxsub[index].urbIn =
2427		kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
2428		GFP_KERNEL);
2429	if (!(usbduxsub[index].urbIn)) {
2430		dev_err(dev, "comedi_: usbdux: Could not alloc. urbIn array\n");
2431		tidy_up(&(usbduxsub[index]));
2432		up(&start_stop_sem);
2433		return -ENOMEM;
2434	}
2435	for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
2436		/* one frame: 1ms */
2437		usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
2438		if (usbduxsub[index].urbIn[i] == NULL) {
2439			dev_err(dev, "comedi_: usbdux%d: "
2440				"Could not alloc. urb(%d)\n", index, i);
2441			tidy_up(&(usbduxsub[index]));
2442			up(&start_stop_sem);
2443			return -ENOMEM;
2444		}
2445		usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
2446		/* will be filled later with a pointer to the comedi-device */
2447		/* and ONLY then the urb should be submitted */
2448		usbduxsub[index].urbIn[i]->context = NULL;
2449		usbduxsub[index].urbIn[i]->pipe =
2450			usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
2451		usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
2452		usbduxsub[index].urbIn[i]->transfer_buffer =
2453			kzalloc(SIZEINBUF, GFP_KERNEL);
2454		if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
2455			dev_err(dev, "comedi_: usbdux%d: "
2456				"could not alloc. transb.\n", index);
2457			tidy_up(&(usbduxsub[index]));
2458			up(&start_stop_sem);
2459			return -ENOMEM;
2460		}
2461		usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
2462		usbduxsub[index].urbIn[i]->number_of_packets = 1;
2463		usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
2464		usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
2465		usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF;
2466	}
2467
2468	/* out */
2469	if (usbduxsub[index].high_speed)
2470		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
2471	else
2472		usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
2473
2474	usbduxsub[index].urbOut =
2475		kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
2476		GFP_KERNEL);
2477	if (!(usbduxsub[index].urbOut)) {
2478		dev_err(dev, "comedi_: usbdux: "
2479			"Could not alloc. urbOut array\n");
2480		tidy_up(&(usbduxsub[index]));
2481		up(&start_stop_sem);
2482		return -ENOMEM;
2483	}
2484	for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
2485		/* one frame: 1ms */
2486		usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
2487		if (usbduxsub[index].urbOut[i] == NULL) {
2488			dev_err(dev, "comedi_: usbdux%d: "
2489				"Could not alloc. urb(%d)\n", index, i);
2490			tidy_up(&(usbduxsub[index]));
2491			up(&start_stop_sem);
2492			return -ENOMEM;
2493		}
2494		usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
2495		/* will be filled later with a pointer to the comedi-device */
2496		/* and ONLY then the urb should be submitted */
2497		usbduxsub[index].urbOut[i]->context = NULL;
2498		usbduxsub[index].urbOut[i]->pipe =
2499			usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
2500		usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
2501		usbduxsub[index].urbOut[i]->transfer_buffer =
2502			kzalloc(SIZEOUTBUF, GFP_KERNEL);
2503		if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
2504			dev_err(dev, "comedi_: usbdux%d: "
2505				"could not alloc. transb.\n", index);
2506			tidy_up(&(usbduxsub[index]));
2507			up(&start_stop_sem);
2508			return -ENOMEM;
2509		}
2510		usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
2511		usbduxsub[index].urbOut[i]->number_of_packets = 1;
2512		usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF;
2513		usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
2514		usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
2515			SIZEOUTBUF;
2516		if (usbduxsub[index].high_speed) {
2517			/* uframes */
2518			usbduxsub[index].urbOut[i]->interval = 8;
2519		} else {
2520			/* frames */
2521			usbduxsub[index].urbOut[i]->interval = 1;
2522		}
2523	}
2524
2525	/* pwm */
2526	if (usbduxsub[index].high_speed) {
2527		/* max bulk ep size in high speed */
2528		usbduxsub[index].sizePwmBuf = 512;
2529		usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
2530		if (usbduxsub[index].urbPwm == NULL) {
2531			dev_err(dev, "comedi_: usbdux%d: "
2532				"Could not alloc. pwm urb\n", index);
2533			tidy_up(&(usbduxsub[index]));
2534			up(&start_stop_sem);
2535			return -ENOMEM;
2536		}
2537		usbduxsub[index].urbPwm->transfer_buffer =
2538			kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
2539		if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
2540			dev_err(dev, "comedi_: usbdux%d: "
2541				"could not alloc. transb. for pwm\n", index);
2542			tidy_up(&(usbduxsub[index]));
2543			up(&start_stop_sem);
2544			return -ENOMEM;
2545		}
2546	} else {
2547		usbduxsub[index].urbPwm = NULL;
2548		usbduxsub[index].sizePwmBuf = 0;
2549	}
2550
2551	usbduxsub[index].ai_cmd_running = 0;
2552	usbduxsub[index].ao_cmd_running = 0;
2553	usbduxsub[index].pwm_cmd_running = 0;
2554
2555	/* we've reached the bottom of the function */
2556	usbduxsub[index].probed = 1;
2557	up(&start_stop_sem);
2558
2559	ret = request_firmware_nowait(THIS_MODULE,
2560				      FW_ACTION_HOTPLUG,
2561				      "usbdux_firmware.bin",
2562				      &udev->dev,
2563				      usbduxsub + index,
2564				      usbdux_firmware_request_complete_handler);
2565
2566
2567
2568	if (ret) {
2569		dev_err(dev, "Could not load firmware (err=%d)\n", ret);
2570		return ret;
2571	}
2572
2573	dev_info(dev, "comedi_: usbdux%d "
2574		 "has been successfully initialised.\n", index);
2575	/* success */
2576	return 0;
2577}
2578
2579static void usbduxsub_disconnect(struct usb_interface *intf)
2580{
2581	struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
2582	struct usb_device *udev = interface_to_usbdev(intf);
2583
2584	if (!usbduxsub_tmp) {
2585		dev_err(&intf->dev,
2586			"comedi_: disconnect called with null pointer.\n");
2587		return;
2588	}
2589	if (usbduxsub_tmp->usbdev != udev) {
2590		dev_err(&intf->dev,
2591			"comedi_: BUG! called with wrong ptr!!!\n");
2592		return;
2593	}
2594	comedi_usb_auto_unconfig(udev);
2595	down(&start_stop_sem);
2596	down(&usbduxsub_tmp->sem);
2597	tidy_up(usbduxsub_tmp);
2598	up(&usbduxsub_tmp->sem);
2599	up(&start_stop_sem);
2600	dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
2601}
2602
2603/* is called when comedi-config is called */
2604static int usbdux_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2605{
2606	int ret;
2607	int index;
2608	int i;
2609	struct usbduxsub *udev;
2610
2611	struct comedi_subdevice *s = NULL;
2612	dev->private = NULL;
2613
2614	down(&start_stop_sem);
2615	/* find a valid device which has been detected by the probe function of
2616	 * the usb */
2617	index = -1;
2618	for (i = 0; i < NUMUSBDUX; i++) {
2619		if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
2620			index = i;
2621			break;
2622		}
2623	}
2624
2625	if (index < 0) {
2626		printk(KERN_ERR "comedi%d: usbdux: error: attach failed, no "
2627		       "usbdux devs connected to the usb bus.\n", dev->minor);
2628		up(&start_stop_sem);
2629		return -ENODEV;
2630	}
2631
2632	udev = &usbduxsub[index];
2633	down(&udev->sem);
2634	/* pointer back to the corresponding comedi device */
2635	udev->comedidev = dev;
2636
2637	/* trying to upload the firmware into the chip */
2638	if (comedi_aux_data(it->options, 0) &&
2639		it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
2640		firmwareUpload(udev, comedi_aux_data(it->options, 0),
2641			       it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
2642	}
2643
2644	dev->board_name = BOARDNAME;
2645
2646	/* set number of subdevices */
2647	if (udev->high_speed) {
2648		/* with pwm */
2649		dev->n_subdevices = 5;
2650	} else {
2651		/* without pwm */
2652		dev->n_subdevices = 4;
2653	}
2654
2655	/* allocate space for the subdevices */
2656	ret = alloc_subdevices(dev, dev->n_subdevices);
2657	if (ret < 0) {
2658		dev_err(&udev->interface->dev,
2659			"comedi%d: error alloc space for subdev\n", dev->minor);
2660		up(&start_stop_sem);
2661		return ret;
2662	}
2663
2664	dev_info(&udev->interface->dev,
2665		"comedi%d: usb-device %d is attached to comedi.\n",
2666		dev->minor, index);
2667	/* private structure is also simply the usb-structure */
2668	dev->private = udev;
2669
2670	/* the first subdevice is the A/D converter */
2671	s = dev->subdevices + SUBDEV_AD;
2672	/* the URBs get the comedi subdevice */
2673	/* which is responsible for reading */
2674	/* this is the subdevice which reads data */
2675	dev->read_subdev = s;
2676	/* the subdevice receives as private structure the */
2677	/* usb-structure */
2678	s->private = NULL;
2679	/* analog input */
2680	s->type = COMEDI_SUBD_AI;
2681	/* readable and ref is to ground */
2682	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
2683	/* 8 channels */
2684	s->n_chan = 8;
2685	/* length of the channellist */
2686	s->len_chanlist = 8;
2687	/* callback functions */
2688	s->insn_read = usbdux_ai_insn_read;
2689	s->do_cmdtest = usbdux_ai_cmdtest;
2690	s->do_cmd = usbdux_ai_cmd;
2691	s->cancel = usbdux_ai_cancel;
2692	/* max value from the A/D converter (12bit) */
2693	s->maxdata = 0xfff;
2694	/* range table to convert to physical units */
2695	s->range_table = (&range_usbdux_ai_range);
2696
2697	/* analog out */
2698	s = dev->subdevices + SUBDEV_DA;
2699	/* analog out */
2700	s->type = COMEDI_SUBD_AO;
2701	/* backward pointer */
2702	dev->write_subdev = s;
2703	/* the subdevice receives as private structure the */
2704	/* usb-structure */
2705	s->private = NULL;
2706	/* are writable */
2707	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
2708	/* 4 channels */
2709	s->n_chan = 4;
2710	/* length of the channellist */
2711	s->len_chanlist = 4;
2712	/* 12 bit resolution */
2713	s->maxdata = 0x0fff;
2714	/* bipolar range */
2715	s->range_table = (&range_usbdux_ao_range);
2716	/* callback */
2717	s->do_cmdtest = usbdux_ao_cmdtest;
2718	s->do_cmd = usbdux_ao_cmd;
2719	s->cancel = usbdux_ao_cancel;
2720	s->insn_read = usbdux_ao_insn_read;
2721	s->insn_write = usbdux_ao_insn_write;
2722
2723	/* digital I/O */
2724	s = dev->subdevices + SUBDEV_DIO;
2725	s->type = COMEDI_SUBD_DIO;
2726	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2727	s->n_chan = 8;
2728	s->maxdata = 1;
2729	s->range_table = (&range_digital);
2730	s->insn_bits = usbdux_dio_insn_bits;
2731	s->insn_config = usbdux_dio_insn_config;
2732	/* we don't use it */
2733	s->private = NULL;
2734
2735	/* counter */
2736	s = dev->subdevices + SUBDEV_COUNTER;
2737	s->type = COMEDI_SUBD_COUNTER;
2738	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
2739	s->n_chan = 4;
2740	s->maxdata = 0xFFFF;
2741	s->insn_read = usbdux_counter_read;
2742	s->insn_write = usbdux_counter_write;
2743	s->insn_config = usbdux_counter_config;
2744
2745	if (udev->high_speed) {
2746		/* timer / pwm */
2747		s = dev->subdevices + SUBDEV_PWM;
2748		s->type = COMEDI_SUBD_PWM;
2749		s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
2750		s->n_chan = 8;
2751		/* this defines the max duty cycle resolution */
2752		s->maxdata = udev->sizePwmBuf;
2753		s->insn_write = usbdux_pwm_write;
2754		s->insn_read = usbdux_pwm_read;
2755		s->insn_config = usbdux_pwm_config;
2756		usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
2757	}
2758	/* finally decide that it's attached */
2759	udev->attached = 1;
2760
2761	up(&udev->sem);
2762
2763	up(&start_stop_sem);
2764
2765	dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
2766		 dev->minor);
2767
2768	return 0;
2769}
2770
2771static int usbdux_detach(struct comedi_device *dev)
2772{
2773	struct usbduxsub *usbduxsub_tmp;
2774
2775	if (!dev) {
2776		printk(KERN_ERR
2777			"comedi?: usbdux: detach without dev variable...\n");
2778		return -EFAULT;
2779	}
2780
2781	usbduxsub_tmp = dev->private;
2782	if (!usbduxsub_tmp) {
2783		printk(KERN_ERR
2784			"comedi?: usbdux: detach without ptr to usbduxsub[]\n");
2785		return -EFAULT;
2786	}
2787
2788	dev_dbg(&usbduxsub_tmp->interface->dev, "comedi%d: detach usb device\n",
2789		dev->minor);
2790
2791	down(&usbduxsub_tmp->sem);
2792	/* Don't allow detach to free the private structure */
2793	/* It's one entry of of usbduxsub[] */
2794	dev->private = NULL;
2795	usbduxsub_tmp->attached = 0;
2796	usbduxsub_tmp->comedidev = NULL;
2797	dev_dbg(&usbduxsub_tmp->interface->dev,
2798		"comedi%d: detach: successfully removed\n", dev->minor);
2799	up(&usbduxsub_tmp->sem);
2800	return 0;
2801}
2802
2803/* main driver struct */
2804static struct comedi_driver driver_usbdux = {
2805      .driver_name =	"usbdux",
2806      .module =		THIS_MODULE,
2807      .attach =		usbdux_attach,
2808      .detach =		usbdux_detach,
2809};
2810
2811/* Table with the USB-devices: just now only testing IDs */
2812static struct usb_device_id usbduxsub_table[] = {
2813	{USB_DEVICE(0x13d8, 0x0001) },
2814	{USB_DEVICE(0x13d8, 0x0002) },
2815	{}			/* Terminating entry */
2816};
2817
2818MODULE_DEVICE_TABLE(usb, usbduxsub_table);
2819
2820/* The usbduxsub-driver */
2821static struct usb_driver usbduxsub_driver = {
2822      .name =		BOARDNAME,
2823      .probe =		usbduxsub_probe,
2824      .disconnect =	usbduxsub_disconnect,
2825      .id_table =	usbduxsub_table,
2826};
2827
2828/* Can't use the nice macro as I have also to initialise the USB */
2829/* subsystem: */
2830/* registering the usb-system _and_ the comedi-driver */
2831static int __init init_usbdux(void)
2832{
2833	printk(KERN_INFO KBUILD_MODNAME ": "
2834	       DRIVER_VERSION ":" DRIVER_DESC "\n");
2835	usb_register(&usbduxsub_driver);
2836	comedi_driver_register(&driver_usbdux);
2837	return 0;
2838}
2839
2840/* deregistering the comedi driver and the usb-subsystem */
2841static void __exit exit_usbdux(void)
2842{
2843	comedi_driver_unregister(&driver_usbdux);
2844	usb_deregister(&usbduxsub_driver);
2845}
2846
2847module_init(init_usbdux);
2848module_exit(exit_usbdux);
2849
2850MODULE_AUTHOR(DRIVER_AUTHOR);
2851MODULE_DESCRIPTION(DRIVER_DESC);
2852MODULE_LICENSE("GPL");
2853