[go: nahoru, domu]

1/*
2 * usbduxsigma.c
3 * Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 */
15
16/*
17 * Driver: usbduxsigma
18 * Description: University of Stirling USB DAQ & INCITE Technology Limited
19 * Devices: (ITL) USB-DUX [usbduxsigma]
20 * Author: Bernd Porr <BerndPorr@f2s.com>
21 * Updated: 8 Nov 2011
22 * Status: testing
23 */
24
25/*
26 * I must give credit here to Chris Baugher who
27 * wrote the driver for AT-MIO-16d. I used some parts of this
28 * driver. I also must give credits to David Brownell
29 * who supported me with the USB development.
30 *
31 * Note: the raw data from the A/D converter is 24 bit big endian
32 * anything else is little endian to/from the dux board
33 *
34 *
35 * Revision history:
36 *   0.1: initial version
37 *   0.2: all basic functions implemented, digital I/O only for one port
38 *   0.3: proper vendor ID and driver name
39 *   0.4: fixed D/A voltage range
40 *   0.5: various bug fixes, health check at startup
41 *   0.6: corrected wrong input range
42 */
43
44#include <linux/kernel.h>
45#include <linux/module.h>
46#include <linux/slab.h>
47#include <linux/input.h>
48#include <linux/usb.h>
49#include <linux/fcntl.h>
50#include <linux/compiler.h>
51#include <asm/unaligned.h>
52
53#include "comedi_fc.h"
54#include "../comedidev.h"
55
56/* timeout for the USB-transfer in ms*/
57#define BULK_TIMEOUT 1000
58
59/* constants for "firmware" upload and download */
60#define FIRMWARE		"usbduxsigma_firmware.bin"
61#define FIRMWARE_MAX_LEN	0x4000
62#define USBDUXSUB_FIRMWARE	0xa0
63#define VENDOR_DIR_IN		0xc0
64#define VENDOR_DIR_OUT		0x40
65
66/* internal addresses of the 8051 processor */
67#define USBDUXSUB_CPUCS 0xE600
68
69/* 300Hz max frequ under PWM */
70#define MIN_PWM_PERIOD  ((long)(1E9/300))
71
72/* Default PWM frequency */
73#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
74
75/* Number of channels (16 AD and offset)*/
76#define NUMCHANNELS 16
77
78/* Size of one A/D value */
79#define SIZEADIN          ((sizeof(uint32_t)))
80
81/*
82 * Size of the async input-buffer IN BYTES, the DIO state is transmitted
83 * as the first byte.
84 */
85#define SIZEINBUF         (((NUMCHANNELS+1)*SIZEADIN))
86
87/* 16 bytes. */
88#define SIZEINSNBUF       16
89
90/* Number of DA channels */
91#define NUMOUTCHANNELS    8
92
93/* size of one value for the D/A converter: channel and value */
94#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(uint16_t)))
95
96/*
97 * Size of the output-buffer in bytes
98 * Actually only the first 4 triplets are used but for the
99 * high speed mode we need to pad it to 8 (microframes).
100 */
101#define SIZEOUTBUF         ((8*SIZEDAOUT))
102
103/*
104 * Size of the buffer for the dux commands: just now max size is determined
105 * by the analogue out + command byte + panic bytes...
106 */
107#define SIZEOFDUXBUFFER    ((8*SIZEDAOUT+2))
108
109/* Number of in-URBs which receive the data: min=2 */
110#define NUMOFINBUFFERSFULL     5
111
112/* Number of out-URBs which send the data: min=2 */
113#define NUMOFOUTBUFFERSFULL    5
114
115/* Number of in-URBs which receive the data: min=5 */
116/* must have more buffers due to buggy USB ctr */
117#define NUMOFINBUFFERSHIGH     10
118
119/* Number of out-URBs which send the data: min=5 */
120/* must have more buffers due to buggy USB ctr */
121#define NUMOFOUTBUFFERSHIGH    10
122
123/* number of retries to get the right dux command */
124#define RETRIES 10
125
126/* bulk transfer commands to usbduxsigma */
127#define USBBUXSIGMA_AD_CMD		0
128#define USBDUXSIGMA_DA_CMD		1
129#define USBDUXSIGMA_DIO_CFG_CMD		2
130#define USBDUXSIGMA_DIO_BITS_CMD	3
131#define USBDUXSIGMA_SINGLE_AD_CMD	4
132#define USBDUXSIGMA_PWM_ON_CMD		7
133#define USBDUXSIGMA_PWM_OFF_CMD		8
134
135static const struct comedi_lrange usbduxsigma_ai_range = {
136	1, {
137		BIP_RANGE(2.5 * 0x800000 / 0x780000 / 2.0)
138	}
139};
140
141struct usbduxsigma_private {
142	/* actual number of in-buffers */
143	int n_ai_urbs;
144	/* actual number of out-buffers */
145	int n_ao_urbs;
146	/* ISO-transfer handling: buffers */
147	struct urb **ai_urbs;
148	struct urb **ao_urbs;
149	/* pwm-transfer handling */
150	struct urb *pwm_urb;
151	/* PWM period */
152	unsigned int pwm_period;
153	/* PWM internal delay for the GPIF in the FX2 */
154	uint8_t pwm_delay;
155	/* size of the PWM buffer which holds the bit pattern */
156	int pwm_buf_sz;
157	/* input buffer for the ISO-transfer */
158	__be32 *in_buf;
159	/* input buffer for single insn */
160	uint8_t *insn_buf;
161
162	unsigned high_speed:1;
163	unsigned ai_cmd_running:1;
164	unsigned ao_cmd_running:1;
165	unsigned pwm_cmd_running:1;
166
167	/* number of samples to acquire */
168	int ai_sample_count;
169	int ao_sample_count;
170	/* time between samples in units of the timer */
171	unsigned int ai_timer;
172	unsigned int ao_timer;
173	/* counter between acquisitions */
174	unsigned int ai_counter;
175	unsigned int ao_counter;
176	/* interval in frames/uframes */
177	unsigned int ai_interval;
178	/* commands */
179	uint8_t *dux_commands;
180	struct semaphore sem;
181};
182
183static void usbduxsigma_unlink_urbs(struct urb **urbs, int num_urbs)
184{
185	int i;
186
187	for (i = 0; i < num_urbs; i++)
188		usb_kill_urb(urbs[i]);
189}
190
191static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink)
192{
193	struct usbduxsigma_private *devpriv = dev->private;
194
195	if (do_unlink && devpriv->ai_urbs)
196		usbduxsigma_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
197
198	devpriv->ai_cmd_running = 0;
199}
200
201static int usbduxsigma_ai_cancel(struct comedi_device *dev,
202				 struct comedi_subdevice *s)
203{
204	struct usbduxsigma_private *devpriv = dev->private;
205
206	down(&devpriv->sem);
207	/* unlink only if it is really running */
208	usbduxsigma_ai_stop(dev, devpriv->ai_cmd_running);
209	up(&devpriv->sem);
210
211	return 0;
212}
213
214static void usbduxsigma_ai_urb_complete(struct urb *urb)
215{
216	struct comedi_device *dev = urb->context;
217	struct usbduxsigma_private *devpriv = dev->private;
218	struct comedi_subdevice *s = dev->read_subdev;
219	struct comedi_cmd *cmd = &s->async->cmd;
220	unsigned int dio_state;
221	uint32_t val;
222	int ret;
223	int i;
224
225	/* first we test if something unusual has just happened */
226	switch (urb->status) {
227	case 0:
228		/* copy the result in the transfer buffer */
229		memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
230		break;
231	case -EILSEQ:
232		/*
233		 * error in the ISOchronous data
234		 * we don't copy the data into the transfer buffer
235		 * and recycle the last data byte
236		 */
237		dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
238
239		break;
240
241	case -ECONNRESET:
242	case -ENOENT:
243	case -ESHUTDOWN:
244	case -ECONNABORTED:
245		/* happens after an unlink command */
246		if (devpriv->ai_cmd_running) {
247			usbduxsigma_ai_stop(dev, 0);	/* w/o unlink */
248			/* we are still running a command, tell comedi */
249			s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
250			comedi_event(dev, s);
251		}
252		return;
253
254	default:
255		/*
256		 * a real error on the bus
257		 * pass error to comedi if we are really running a command
258		 */
259		if (devpriv->ai_cmd_running) {
260			dev_err(dev->class_dev,
261				"%s: non-zero urb status (%d)\n",
262				__func__, urb->status);
263			usbduxsigma_ai_stop(dev, 0);	/* w/o unlink */
264			s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
265			comedi_event(dev, s);
266		}
267		return;
268	}
269
270	if (unlikely(!devpriv->ai_cmd_running))
271		return;
272
273	urb->dev = comedi_to_usb_dev(dev);
274
275	ret = usb_submit_urb(urb, GFP_ATOMIC);
276	if (unlikely(ret < 0)) {
277		dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
278			__func__, ret);
279		if (ret == -EL2NSYNC)
280			dev_err(dev->class_dev,
281				"buggy USB host controller or bug in IRQ handler\n");
282		usbduxsigma_ai_stop(dev, 0);	/* w/o unlink */
283		s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
284		comedi_event(dev, s);
285		return;
286	}
287
288	/* get the state of the dio pins to allow external trigger */
289	dio_state = be32_to_cpu(devpriv->in_buf[0]);
290
291	devpriv->ai_counter--;
292	if (likely(devpriv->ai_counter > 0))
293		return;
294
295	/* timer zero, transfer measurements to comedi */
296	devpriv->ai_counter = devpriv->ai_timer;
297
298	if (cmd->stop_src == TRIG_COUNT) {
299		/* not continuous, fixed number of samples */
300		devpriv->ai_sample_count--;
301		if (devpriv->ai_sample_count < 0) {
302			usbduxsigma_ai_stop(dev, 0);	/* w/o unlink */
303			/* acquistion is over, tell comedi */
304			s->async->events |= COMEDI_CB_EOA;
305			comedi_event(dev, s);
306			return;
307		}
308	}
309
310	/* get the data from the USB bus and hand it over to comedi */
311	for (i = 0; i < cmd->chanlist_len; i++) {
312		/* transfer data, note first byte is the DIO state */
313		val = be32_to_cpu(devpriv->in_buf[i+1]);
314		val &= 0x00ffffff;	/* strip status byte */
315		val ^= 0x00800000;	/* convert to unsigned */
316
317		ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
318		if (unlikely(ret == 0)) {
319			/* buffer overflow */
320			usbduxsigma_ai_stop(dev, 0);	/* w/o unlink */
321			return;
322		}
323	}
324	/* tell comedi that data is there */
325	s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
326	comedi_event(dev, s);
327}
328
329static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink)
330{
331	struct usbduxsigma_private *devpriv = dev->private;
332
333	if (do_unlink && devpriv->ao_urbs)
334		usbduxsigma_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
335
336	devpriv->ao_cmd_running = 0;
337}
338
339static int usbduxsigma_ao_cancel(struct comedi_device *dev,
340				 struct comedi_subdevice *s)
341{
342	struct usbduxsigma_private *devpriv = dev->private;
343
344	down(&devpriv->sem);
345	/* unlink only if it is really running */
346	usbduxsigma_ao_stop(dev, devpriv->ao_cmd_running);
347	up(&devpriv->sem);
348
349	return 0;
350}
351
352static void usbduxsigma_ao_urb_complete(struct urb *urb)
353{
354	struct comedi_device *dev = urb->context;
355	struct usbduxsigma_private *devpriv = dev->private;
356	struct comedi_subdevice *s = dev->write_subdev;
357	struct comedi_cmd *cmd = &s->async->cmd;
358	uint8_t *datap;
359	int ret;
360	int i;
361
362	switch (urb->status) {
363	case 0:
364		/* success */
365		break;
366
367	case -ECONNRESET:
368	case -ENOENT:
369	case -ESHUTDOWN:
370	case -ECONNABORTED:
371		/* happens after an unlink command */
372		if (devpriv->ao_cmd_running) {
373			usbduxsigma_ao_stop(dev, 0);	/* w/o unlink */
374			s->async->events |= COMEDI_CB_EOA;
375			comedi_event(dev, s);
376		}
377		return;
378
379	default:
380		/* a real error */
381		if (devpriv->ao_cmd_running) {
382			dev_err(dev->class_dev,
383				"%s: non-zero urb status (%d)\n",
384				__func__, urb->status);
385			usbduxsigma_ao_stop(dev, 0);	/* w/o unlink */
386			s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
387			comedi_event(dev, s);
388		}
389		return;
390	}
391
392	if (!devpriv->ao_cmd_running)
393		return;
394
395	devpriv->ao_counter--;
396	if ((int)devpriv->ao_counter <= 0) {
397		/* timer zero, transfer from comedi */
398		devpriv->ao_counter = devpriv->ao_timer;
399
400		if (cmd->stop_src == TRIG_COUNT) {
401			/* not continuous, fixed number of samples */
402			devpriv->ao_sample_count--;
403			if (devpriv->ao_sample_count < 0) {
404				usbduxsigma_ao_stop(dev, 0);	/* w/o unlink */
405				/* acquistion is over, tell comedi */
406				s->async->events |= COMEDI_CB_EOA;
407				comedi_event(dev, s);
408				return;
409			}
410		}
411
412		/* transmit data to the USB bus */
413		datap = urb->transfer_buffer;
414		*datap++ = cmd->chanlist_len;
415		for (i = 0; i < cmd->chanlist_len; i++) {
416			unsigned int chan = CR_CHAN(cmd->chanlist[i]);
417			unsigned short val;
418
419			ret = comedi_buf_get(s, &val);
420			if (ret < 0) {
421				dev_err(dev->class_dev, "buffer underflow\n");
422				s->async->events |= (COMEDI_CB_EOA |
423						     COMEDI_CB_OVERFLOW);
424			}
425			*datap++ = val;
426			*datap++ = chan;
427			s->readback[chan] = val;
428
429			s->async->events |= COMEDI_CB_BLOCK;
430			comedi_event(dev, s);
431		}
432	}
433
434	urb->transfer_buffer_length = SIZEOUTBUF;
435	urb->dev = comedi_to_usb_dev(dev);
436	urb->status = 0;
437	if (devpriv->high_speed)
438		urb->interval = 8;	/* uframes */
439	else
440		urb->interval = 1;	/* frames */
441	urb->number_of_packets = 1;
442	urb->iso_frame_desc[0].offset = 0;
443	urb->iso_frame_desc[0].length = SIZEOUTBUF;
444	urb->iso_frame_desc[0].status = 0;
445	ret = usb_submit_urb(urb, GFP_ATOMIC);
446	if (ret < 0) {
447		dev_err(dev->class_dev,
448			"%s: urb resubmit failed (%d)\n",
449			__func__, ret);
450		if (ret == -EL2NSYNC)
451			dev_err(dev->class_dev,
452				"buggy USB host controller or bug in IRQ handler\n");
453		usbduxsigma_ao_stop(dev, 0);	/* w/o unlink */
454		s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
455		comedi_event(dev, s);
456	}
457}
458
459static int usbduxsigma_submit_urbs(struct comedi_device *dev,
460				   struct urb **urbs, int num_urbs,
461				   int input_urb)
462{
463	struct usb_device *usb = comedi_to_usb_dev(dev);
464	struct usbduxsigma_private *devpriv = dev->private;
465	struct urb *urb;
466	int ret;
467	int i;
468
469	/* Submit all URBs and start the transfer on the bus */
470	for (i = 0; i < num_urbs; i++) {
471		urb = urbs[i];
472
473		/* in case of a resubmission after an unlink... */
474		if (input_urb)
475			urb->interval = devpriv->ai_interval;
476		urb->context = dev;
477		urb->dev = usb;
478		urb->status = 0;
479		urb->transfer_flags = URB_ISO_ASAP;
480
481		ret = usb_submit_urb(urb, GFP_ATOMIC);
482		if (ret)
483			return ret;
484	}
485	return 0;
486}
487
488static int usbduxsigma_chans_to_interval(int num_chan)
489{
490	if (num_chan <= 2)
491		return 2;	/* 4kHz */
492	if (num_chan <= 8)
493		return 4;	/* 2kHz */
494	return 8;		/* 1kHz */
495}
496
497static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
498				  struct comedi_subdevice *s,
499				  struct comedi_cmd *cmd)
500{
501	struct usbduxsigma_private *devpriv = dev->private;
502	int high_speed = devpriv->high_speed;
503	int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
504	int err = 0;
505
506	/* Step 1 : check if triggers are trivially valid */
507
508	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
509	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
510	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
511	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
512	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
513
514	if (err)
515		return 1;
516
517	/* Step 2a : make sure trigger sources are unique */
518
519	err |= cfc_check_trigger_is_unique(cmd->start_src);
520	err |= cfc_check_trigger_is_unique(cmd->stop_src);
521
522	/* Step 2b : and mutually compatible */
523
524	if (err)
525		return 2;
526
527	/* Step 3: check if arguments are trivially valid */
528
529	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
530
531	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
532		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
533
534	if (cmd->scan_begin_src == TRIG_TIMER) {
535		unsigned int tmp;
536
537		if (high_speed) {
538			/*
539			 * In high speed mode microframes are possible.
540			 * However, during one microframe we can roughly
541			 * sample two channels. Thus, the more channels
542			 * are in the channel list the more time we need.
543			 */
544			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
545						(1000000 / 8 * interval));
546
547			tmp = (cmd->scan_begin_arg / 125000) * 125000;
548		} else {
549			/* full speed */
550			/* 1kHz scans every USB frame */
551			err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
552							 1000000);
553
554			tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
555		}
556		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
557	}
558
559	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
560
561	if (cmd->stop_src == TRIG_COUNT)
562		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
563	else	/* TRIG_NONE */
564		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
565
566	if (err)
567		return 3;
568
569	/* Step 4: fix up any arguments */
570
571	if (high_speed) {
572		/*
573		 * every 2 channels get a time window of 125us. Thus, if we
574		 * sample all 16 channels we need 1ms. If we sample only one
575		 * channel we need only 125us
576		 */
577		devpriv->ai_interval = interval;
578		devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
579	} else {
580		/* interval always 1ms */
581		devpriv->ai_interval = 1;
582		devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
583	}
584	if (devpriv->ai_timer < 1)
585		err |= -EINVAL;
586
587	if (cmd->stop_src == TRIG_COUNT) {
588		/* data arrives as one packet */
589		devpriv->ai_sample_count = cmd->stop_arg;
590	} else {
591		/* continuous acquisition */
592		devpriv->ai_sample_count = 0;
593	}
594
595	if (err)
596		return 4;
597
598	return 0;
599}
600
601/*
602 * creates the ADC command for the MAX1271
603 * range is the range value from comedi
604 */
605static void create_adc_command(unsigned int chan,
606			       uint8_t *muxsg0,
607			       uint8_t *muxsg1)
608{
609	if (chan < 8)
610		(*muxsg0) = (*muxsg0) | (1 << chan);
611	else if (chan < 16)
612		(*muxsg1) = (*muxsg1) | (1 << (chan-8));
613}
614
615static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type)
616{
617	struct usb_device *usb = comedi_to_usb_dev(dev);
618	struct usbduxsigma_private *devpriv = dev->private;
619	int nsent;
620
621	devpriv->dux_commands[0] = cmd_type;
622
623	return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
624			    devpriv->dux_commands, SIZEOFDUXBUFFER,
625			    &nsent, BULK_TIMEOUT);
626}
627
628static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command)
629{
630	struct usb_device *usb = comedi_to_usb_dev(dev);
631	struct usbduxsigma_private *devpriv = dev->private;
632	int nrec;
633	int ret;
634	int i;
635
636	for (i = 0; i < RETRIES; i++) {
637		ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
638				   devpriv->insn_buf, SIZEINSNBUF,
639				   &nrec, BULK_TIMEOUT);
640		if (ret < 0)
641			return ret;
642
643		if (devpriv->insn_buf[0] == command)
644			return 0;
645	}
646	/*
647	 * This is only reached if the data has been requested a
648	 * couple of times and the command was not received.
649	 */
650	return -EFAULT;
651}
652
653static int usbduxsigma_ai_inttrig(struct comedi_device *dev,
654				  struct comedi_subdevice *s,
655				  unsigned int trig_num)
656{
657	struct usbduxsigma_private *devpriv = dev->private;
658	struct comedi_cmd *cmd = &s->async->cmd;
659	int ret;
660
661	if (trig_num != cmd->start_arg)
662		return -EINVAL;
663
664	down(&devpriv->sem);
665	if (!devpriv->ai_cmd_running) {
666		devpriv->ai_cmd_running = 1;
667		ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
668					      devpriv->n_ai_urbs, 1);
669		if (ret < 0) {
670			devpriv->ai_cmd_running = 0;
671			up(&devpriv->sem);
672			return ret;
673		}
674		s->async->inttrig = NULL;
675	}
676	up(&devpriv->sem);
677
678	return 1;
679}
680
681static int usbduxsigma_ai_cmd(struct comedi_device *dev,
682			      struct comedi_subdevice *s)
683{
684	struct usbduxsigma_private *devpriv = dev->private;
685	struct comedi_cmd *cmd = &s->async->cmd;
686	unsigned int len = cmd->chanlist_len;
687	uint8_t muxsg0 = 0;
688	uint8_t muxsg1 = 0;
689	uint8_t sysred = 0;
690	int ret;
691	int i;
692
693	down(&devpriv->sem);
694
695	/* set current channel of the running acquisition to zero */
696	s->async->cur_chan = 0;
697	for (i = 0; i < len; i++) {
698		unsigned int chan  = CR_CHAN(cmd->chanlist[i]);
699
700		create_adc_command(chan, &muxsg0, &muxsg1);
701	}
702
703	devpriv->dux_commands[1] = len;  /* num channels per time step */
704	devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
705	devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
706	devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
707	devpriv->dux_commands[5] = muxsg0;
708	devpriv->dux_commands[6] = muxsg1;
709	devpriv->dux_commands[7] = sysred;
710
711	ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
712	if (ret < 0) {
713		up(&devpriv->sem);
714		return ret;
715	}
716
717	devpriv->ai_counter = devpriv->ai_timer;
718
719	if (cmd->start_src == TRIG_NOW) {
720		/* enable this acquisition operation */
721		devpriv->ai_cmd_running = 1;
722		ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
723					      devpriv->n_ai_urbs, 1);
724		if (ret < 0) {
725			devpriv->ai_cmd_running = 0;
726			up(&devpriv->sem);
727			return ret;
728		}
729		s->async->inttrig = NULL;
730	} else {	/* TRIG_INT */
731		s->async->inttrig = usbduxsigma_ai_inttrig;
732	}
733
734	up(&devpriv->sem);
735
736	return 0;
737}
738
739static int usbduxsigma_ai_insn_read(struct comedi_device *dev,
740				    struct comedi_subdevice *s,
741				    struct comedi_insn *insn,
742				    unsigned int *data)
743{
744	struct usbduxsigma_private *devpriv = dev->private;
745	unsigned int chan = CR_CHAN(insn->chanspec);
746	uint8_t muxsg0 = 0;
747	uint8_t muxsg1 = 0;
748	uint8_t sysred = 0;
749	int ret;
750	int i;
751
752	down(&devpriv->sem);
753	if (devpriv->ai_cmd_running) {
754		up(&devpriv->sem);
755		return -EBUSY;
756	}
757
758	create_adc_command(chan, &muxsg0, &muxsg1);
759
760	/* Mode 0 is used to get a single conversion on demand */
761	devpriv->dux_commands[1] = 0x16; /* CONFIG0: chopper on */
762	devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
763	devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
764	devpriv->dux_commands[4] = muxsg0;
765	devpriv->dux_commands[5] = muxsg1;
766	devpriv->dux_commands[6] = sysred;
767
768	/* adc commands */
769	ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
770	if (ret < 0) {
771		up(&devpriv->sem);
772		return ret;
773	}
774
775	for (i = 0; i < insn->n; i++) {
776		uint32_t val;
777
778		ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
779		if (ret < 0) {
780			up(&devpriv->sem);
781			return ret;
782		}
783
784		/* 32 bits big endian from the A/D converter */
785		val = be32_to_cpu(get_unaligned((__be32
786						 *)(devpriv->insn_buf + 1)));
787		val &= 0x00ffffff;	/* strip status byte */
788		val ^= 0x00800000;	/* convert to unsigned */
789
790		data[i] = val;
791	}
792	up(&devpriv->sem);
793
794	return insn->n;
795}
796
797static int usbduxsigma_ao_insn_read(struct comedi_device *dev,
798				    struct comedi_subdevice *s,
799				    struct comedi_insn *insn,
800				    unsigned int *data)
801{
802	struct usbduxsigma_private *devpriv = dev->private;
803	int ret;
804
805	down(&devpriv->sem);
806	ret = comedi_readback_insn_read(dev, s, insn, data);
807	up(&devpriv->sem);
808
809	return ret;
810}
811
812static int usbduxsigma_ao_insn_write(struct comedi_device *dev,
813				     struct comedi_subdevice *s,
814				     struct comedi_insn *insn,
815				     unsigned int *data)
816{
817	struct usbduxsigma_private *devpriv = dev->private;
818	unsigned int chan = CR_CHAN(insn->chanspec);
819	int ret;
820	int i;
821
822	down(&devpriv->sem);
823	if (devpriv->ao_cmd_running) {
824		up(&devpriv->sem);
825		return -EBUSY;
826	}
827
828	for (i = 0; i < insn->n; i++) {
829		devpriv->dux_commands[1] = 1;		/* num channels */
830		devpriv->dux_commands[2] = data[i];	/* value */
831		devpriv->dux_commands[3] = chan;	/* channel number */
832		ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD);
833		if (ret < 0) {
834			up(&devpriv->sem);
835			return ret;
836		}
837		s->readback[chan] = data[i];
838	}
839	up(&devpriv->sem);
840
841	return insn->n;
842}
843
844static int usbduxsigma_ao_inttrig(struct comedi_device *dev,
845				  struct comedi_subdevice *s,
846				  unsigned int trig_num)
847{
848	struct usbduxsigma_private *devpriv = dev->private;
849	struct comedi_cmd *cmd = &s->async->cmd;
850	int ret;
851
852	if (trig_num != cmd->start_arg)
853		return -EINVAL;
854
855	down(&devpriv->sem);
856	if (!devpriv->ao_cmd_running) {
857		devpriv->ao_cmd_running = 1;
858		ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
859					      devpriv->n_ao_urbs, 0);
860		if (ret < 0) {
861			devpriv->ao_cmd_running = 0;
862			up(&devpriv->sem);
863			return ret;
864		}
865		s->async->inttrig = NULL;
866	}
867	up(&devpriv->sem);
868
869	return 1;
870}
871
872static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
873				  struct comedi_subdevice *s,
874				  struct comedi_cmd *cmd)
875{
876	struct usbduxsigma_private *devpriv = dev->private;
877	int err = 0;
878	int high_speed;
879	unsigned int flags;
880
881	/* high speed conversions are not used yet */
882	high_speed = 0;		/* (devpriv->high_speed) */
883
884	/* Step 1 : check if triggers are trivially valid */
885
886	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
887
888	if (high_speed) {
889		/*
890		 * start immediately a new scan
891		 * the sampling rate is set by the coversion rate
892		 */
893		flags = TRIG_FOLLOW;
894	} else {
895		/* start a new scan (output at once) with a timer */
896		flags = TRIG_TIMER;
897	}
898	err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
899
900	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
901	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
902	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
903
904	if (err) {
905		up(&devpriv->sem);
906		return 1;
907	}
908
909	/* Step 2a : make sure trigger sources are unique */
910
911	err |= cfc_check_trigger_is_unique(cmd->start_src);
912	err |= cfc_check_trigger_is_unique(cmd->stop_src);
913
914	/* Step 2b : and mutually compatible */
915
916	if (err)
917		return 2;
918
919	/* Step 3: check if arguments are trivially valid */
920
921	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
922
923	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
924		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
925
926	if (cmd->scan_begin_src == TRIG_TIMER)
927		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
928						 1000000);
929
930	/* not used now, is for later use */
931	if (cmd->convert_src == TRIG_TIMER)
932		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
933
934	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
935
936	if (cmd->stop_src == TRIG_COUNT)
937		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
938	else	/* TRIG_NONE */
939		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
940
941	if (err)
942		return 3;
943
944	/* Step 4: fix up any arguments */
945
946	/* we count in timer steps */
947	if (high_speed) {
948		/* timing of the conversion itself: every 125 us */
949		devpriv->ao_timer = cmd->convert_arg / 125000;
950	} else {
951		/*
952		 * timing of the scan: every 1ms
953		 * we get all channels at once
954		 */
955		devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
956	}
957	if (devpriv->ao_timer < 1)
958		err |= -EINVAL;
959
960	if (cmd->stop_src == TRIG_COUNT) {
961		/* not continuous, use counter */
962		if (high_speed) {
963			/* high speed also scans everything at once */
964			devpriv->ao_sample_count = cmd->stop_arg *
965						   cmd->scan_end_arg;
966		} else {
967			/*
968			 * There's no scan as the scan has been
969			 * handled inside the FX2. Data arrives as
970			 * one packet.
971			 */
972			devpriv->ao_sample_count = cmd->stop_arg;
973		}
974	} else {
975		/* continuous acquisition */
976		devpriv->ao_sample_count = 0;
977	}
978
979	if (err)
980		return 4;
981
982	return 0;
983}
984
985static int usbduxsigma_ao_cmd(struct comedi_device *dev,
986			      struct comedi_subdevice *s)
987{
988	struct usbduxsigma_private *devpriv = dev->private;
989	struct comedi_cmd *cmd = &s->async->cmd;
990	int ret;
991
992	down(&devpriv->sem);
993
994	/* set current channel of the running acquisition to zero */
995	s->async->cur_chan = 0;
996
997	devpriv->ao_counter = devpriv->ao_timer;
998
999	if (cmd->start_src == TRIG_NOW) {
1000		/* enable this acquisition operation */
1001		devpriv->ao_cmd_running = 1;
1002		ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
1003					      devpriv->n_ao_urbs, 0);
1004		if (ret < 0) {
1005			devpriv->ao_cmd_running = 0;
1006			up(&devpriv->sem);
1007			return ret;
1008		}
1009		s->async->inttrig = NULL;
1010	} else {	/* TRIG_INT */
1011		s->async->inttrig = usbduxsigma_ao_inttrig;
1012	}
1013
1014	up(&devpriv->sem);
1015
1016	return 0;
1017}
1018
1019static int usbduxsigma_dio_insn_config(struct comedi_device *dev,
1020				       struct comedi_subdevice *s,
1021				       struct comedi_insn *insn,
1022				       unsigned int *data)
1023{
1024	int ret;
1025
1026	ret = comedi_dio_insn_config(dev, s, insn, data, 0);
1027	if (ret)
1028		return ret;
1029
1030	/*
1031	 * We don't tell the firmware here as it would take 8 frames
1032	 * to submit the information. We do it in the (*insn_bits).
1033	 */
1034	return insn->n;
1035}
1036
1037static int usbduxsigma_dio_insn_bits(struct comedi_device *dev,
1038				     struct comedi_subdevice *s,
1039				     struct comedi_insn *insn,
1040				     unsigned int *data)
1041{
1042	struct usbduxsigma_private *devpriv = dev->private;
1043	int ret;
1044
1045	down(&devpriv->sem);
1046
1047	comedi_dio_update_state(s, data);
1048
1049	/* Always update the hardware. See the (*insn_config). */
1050	devpriv->dux_commands[1] = s->io_bits & 0xff;
1051	devpriv->dux_commands[4] = s->state & 0xff;
1052	devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
1053	devpriv->dux_commands[5] = (s->state >> 8) & 0xff;
1054	devpriv->dux_commands[3] = (s->io_bits >> 16) & 0xff;
1055	devpriv->dux_commands[6] = (s->state >> 16) & 0xff;
1056
1057	ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
1058	if (ret < 0)
1059		goto done;
1060	ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
1061	if (ret < 0)
1062		goto done;
1063
1064	s->state = devpriv->insn_buf[1] |
1065		   (devpriv->insn_buf[2] << 8) |
1066		   (devpriv->insn_buf[3] << 16);
1067
1068	data[1] = s->state;
1069	ret = insn->n;
1070
1071done:
1072	up(&devpriv->sem);
1073
1074	return ret;
1075}
1076
1077static void usbduxsigma_pwm_stop(struct comedi_device *dev, int do_unlink)
1078{
1079	struct usbduxsigma_private *devpriv = dev->private;
1080
1081	if (do_unlink) {
1082		if (devpriv->pwm_urb)
1083			usb_kill_urb(devpriv->pwm_urb);
1084	}
1085
1086	devpriv->pwm_cmd_running = 0;
1087}
1088
1089static int usbduxsigma_pwm_cancel(struct comedi_device *dev,
1090				  struct comedi_subdevice *s)
1091{
1092	struct usbduxsigma_private *devpriv = dev->private;
1093
1094	/* unlink only if it is really running */
1095	usbduxsigma_pwm_stop(dev, devpriv->pwm_cmd_running);
1096
1097	return usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_OFF_CMD);
1098}
1099
1100static void usbduxsigma_pwm_urb_complete(struct urb *urb)
1101{
1102	struct comedi_device *dev = urb->context;
1103	struct usbduxsigma_private *devpriv = dev->private;
1104	int ret;
1105
1106	switch (urb->status) {
1107	case 0:
1108		/* success */
1109		break;
1110
1111	case -ECONNRESET:
1112	case -ENOENT:
1113	case -ESHUTDOWN:
1114	case -ECONNABORTED:
1115		/* happens after an unlink command */
1116		if (devpriv->pwm_cmd_running)
1117			usbduxsigma_pwm_stop(dev, 0);	/* w/o unlink */
1118		return;
1119
1120	default:
1121		/* a real error */
1122		if (devpriv->pwm_cmd_running) {
1123			dev_err(dev->class_dev,
1124				"%s: non-zero urb status (%d)\n",
1125				__func__, urb->status);
1126			usbduxsigma_pwm_stop(dev, 0);	/* w/o unlink */
1127		}
1128		return;
1129	}
1130
1131	if (!devpriv->pwm_cmd_running)
1132		return;
1133
1134	urb->transfer_buffer_length = devpriv->pwm_buf_sz;
1135	urb->dev = comedi_to_usb_dev(dev);
1136	urb->status = 0;
1137	ret = usb_submit_urb(urb, GFP_ATOMIC);
1138	if (ret < 0) {
1139		dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
1140			__func__, ret);
1141		if (ret == -EL2NSYNC)
1142			dev_err(dev->class_dev,
1143				"buggy USB host controller or bug in IRQ handler\n");
1144		usbduxsigma_pwm_stop(dev, 0);	/* w/o unlink */
1145	}
1146}
1147
1148static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev)
1149{
1150	struct usb_device *usb = comedi_to_usb_dev(dev);
1151	struct usbduxsigma_private *devpriv = dev->private;
1152	struct urb *urb = devpriv->pwm_urb;
1153
1154	/* in case of a resubmission after an unlink... */
1155	usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
1156			  urb->transfer_buffer, devpriv->pwm_buf_sz,
1157			  usbduxsigma_pwm_urb_complete, dev);
1158
1159	return usb_submit_urb(urb, GFP_ATOMIC);
1160}
1161
1162static int usbduxsigma_pwm_period(struct comedi_device *dev,
1163				  struct comedi_subdevice *s,
1164				  unsigned int period)
1165{
1166	struct usbduxsigma_private *devpriv = dev->private;
1167	int fx2delay = 255;
1168
1169	if (period < MIN_PWM_PERIOD)
1170		return -EAGAIN;
1171
1172	fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
1173	if (fx2delay > 255)
1174		return -EAGAIN;
1175
1176	devpriv->pwm_delay = fx2delay;
1177	devpriv->pwm_period = period;
1178	return 0;
1179}
1180
1181static int usbduxsigma_pwm_start(struct comedi_device *dev,
1182				 struct comedi_subdevice *s)
1183{
1184	struct usbduxsigma_private *devpriv = dev->private;
1185	int ret;
1186
1187	if (devpriv->pwm_cmd_running)
1188		return 0;
1189
1190	devpriv->dux_commands[1] = devpriv->pwm_delay;
1191	ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_ON_CMD);
1192	if (ret < 0)
1193		return ret;
1194
1195	memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
1196
1197	devpriv->pwm_cmd_running = 1;
1198	ret = usbduxsigma_submit_pwm_urb(dev);
1199	if (ret < 0) {
1200		devpriv->pwm_cmd_running = 0;
1201		return ret;
1202	}
1203
1204	return 0;
1205}
1206
1207static void usbduxsigma_pwm_pattern(struct comedi_device *dev,
1208				    struct comedi_subdevice *s,
1209				    unsigned int chan,
1210				    unsigned int value,
1211				    unsigned int sign)
1212{
1213	struct usbduxsigma_private *devpriv = dev->private;
1214	char pwm_mask = (1 << chan);	/* DIO bit for the PWM data */
1215	char sgn_mask = (16 << chan);	/* DIO bit for the sign */
1216	char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
1217	int szbuf = devpriv->pwm_buf_sz;
1218	int i;
1219
1220	for (i = 0; i < szbuf; i++) {
1221		char c = *buf;
1222
1223		c &= ~pwm_mask;
1224		if (i < value)
1225			c |= pwm_mask;
1226		if (!sign)
1227			c &= ~sgn_mask;
1228		else
1229			c |= sgn_mask;
1230		*buf++ = c;
1231	}
1232}
1233
1234static int usbduxsigma_pwm_write(struct comedi_device *dev,
1235				 struct comedi_subdevice *s,
1236				 struct comedi_insn *insn,
1237				 unsigned int *data)
1238{
1239	unsigned int chan = CR_CHAN(insn->chanspec);
1240
1241	/*
1242	 * It doesn't make sense to support more than one value here
1243	 * because it would just overwrite the PWM buffer.
1244	 */
1245	if (insn->n != 1)
1246		return -EINVAL;
1247
1248	/*
1249	 * The sign is set via a special INSN only, this gives us 8 bits
1250	 * for normal operation, sign is 0 by default.
1251	 */
1252	usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
1253
1254	return insn->n;
1255}
1256
1257static int usbduxsigma_pwm_config(struct comedi_device *dev,
1258				  struct comedi_subdevice *s,
1259				  struct comedi_insn *insn,
1260				  unsigned int *data)
1261{
1262	struct usbduxsigma_private *devpriv = dev->private;
1263	unsigned int chan = CR_CHAN(insn->chanspec);
1264
1265	switch (data[0]) {
1266	case INSN_CONFIG_ARM:
1267		/*
1268		 * if not zero the PWM is limited to a certain time which is
1269		 * not supported here
1270		 */
1271		if (data[1] != 0)
1272			return -EINVAL;
1273		return usbduxsigma_pwm_start(dev, s);
1274	case INSN_CONFIG_DISARM:
1275		return usbduxsigma_pwm_cancel(dev, s);
1276	case INSN_CONFIG_GET_PWM_STATUS:
1277		data[1] = devpriv->pwm_cmd_running;
1278		return 0;
1279	case INSN_CONFIG_PWM_SET_PERIOD:
1280		return usbduxsigma_pwm_period(dev, s, data[1]);
1281	case INSN_CONFIG_PWM_GET_PERIOD:
1282		data[1] = devpriv->pwm_period;
1283		return 0;
1284	case INSN_CONFIG_PWM_SET_H_BRIDGE:
1285		/*
1286		 * data[1] = value
1287		 * data[2] = sign (for a relay)
1288		 */
1289		usbduxsigma_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
1290		return 0;
1291	case INSN_CONFIG_PWM_GET_H_BRIDGE:
1292		/* values are not kept in this driver, nothing to return */
1293		return -EINVAL;
1294	}
1295	return -EINVAL;
1296}
1297
1298static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
1299{
1300	struct usbduxsigma_private *devpriv = dev->private;
1301	uint8_t sysred;
1302	uint32_t val;
1303	int ret;
1304
1305	switch (chan) {
1306	default:
1307	case 0:
1308		sysred = 0;		/* ADC zero */
1309		break;
1310	case 1:
1311		sysred = 1;		/* ADC offset */
1312		break;
1313	case 2:
1314		sysred = 4;		/* VCC */
1315		break;
1316	case 3:
1317		sysred = 8;		/* temperature */
1318		break;
1319	case 4:
1320		sysred = 16;		/* gain */
1321		break;
1322	case 5:
1323		sysred =  32;		/* ref */
1324		break;
1325	}
1326
1327	devpriv->dux_commands[1] = 0x12; /* CONFIG0 */
1328	devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
1329	devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
1330	devpriv->dux_commands[4] = 0;
1331	devpriv->dux_commands[5] = 0;
1332	devpriv->dux_commands[6] = sysred;
1333	ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
1334	if (ret < 0)
1335		return ret;
1336
1337	ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
1338	if (ret < 0)
1339		return ret;
1340
1341	/* 32 bits big endian from the A/D converter */
1342	val = be32_to_cpu(get_unaligned((__be32 *)(devpriv->insn_buf + 1)));
1343	val &= 0x00ffffff;	/* strip status byte */
1344	val ^= 0x00800000;	/* convert to unsigned */
1345
1346	return (int)val;
1347}
1348
1349static int usbduxsigma_firmware_upload(struct comedi_device *dev,
1350				       const u8 *data, size_t size,
1351				       unsigned long context)
1352{
1353	struct usb_device *usb = comedi_to_usb_dev(dev);
1354	uint8_t *buf;
1355	uint8_t *tmp;
1356	int ret;
1357
1358	if (!data)
1359		return 0;
1360
1361	if (size > FIRMWARE_MAX_LEN) {
1362		dev_err(dev->class_dev, "firmware binary too large for FX2\n");
1363		return -ENOMEM;
1364	}
1365
1366	/* we generate a local buffer for the firmware */
1367	buf = kmemdup(data, size, GFP_KERNEL);
1368	if (!buf)
1369		return -ENOMEM;
1370
1371	/* we need a malloc'ed buffer for usb_control_msg() */
1372	tmp = kmalloc(1, GFP_KERNEL);
1373	if (!tmp) {
1374		kfree(buf);
1375		return -ENOMEM;
1376	}
1377
1378	/* stop the current firmware on the device */
1379	*tmp = 1;	/* 7f92 to one */
1380	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1381			      USBDUXSUB_FIRMWARE,
1382			      VENDOR_DIR_OUT,
1383			      USBDUXSUB_CPUCS, 0x0000,
1384			      tmp, 1,
1385			      BULK_TIMEOUT);
1386	if (ret < 0) {
1387		dev_err(dev->class_dev, "can not stop firmware\n");
1388		goto done;
1389	}
1390
1391	/* upload the new firmware to the device */
1392	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1393			      USBDUXSUB_FIRMWARE,
1394			      VENDOR_DIR_OUT,
1395			      0, 0x0000,
1396			      buf, size,
1397			      BULK_TIMEOUT);
1398	if (ret < 0) {
1399		dev_err(dev->class_dev, "firmware upload failed\n");
1400		goto done;
1401	}
1402
1403	/* start the new firmware on the device */
1404	*tmp = 0;	/* 7f92 to zero */
1405	ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1406			      USBDUXSUB_FIRMWARE,
1407			      VENDOR_DIR_OUT,
1408			      USBDUXSUB_CPUCS, 0x0000,
1409			      tmp, 1,
1410			      BULK_TIMEOUT);
1411	if (ret < 0)
1412		dev_err(dev->class_dev, "can not start firmware\n");
1413
1414done:
1415	kfree(tmp);
1416	kfree(buf);
1417	return ret;
1418}
1419
1420static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
1421{
1422	struct usb_device *usb = comedi_to_usb_dev(dev);
1423	struct usbduxsigma_private *devpriv = dev->private;
1424	struct urb *urb;
1425	int i;
1426
1427	devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
1428	devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
1429	devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1430	devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(urb), GFP_KERNEL);
1431	devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(urb), GFP_KERNEL);
1432	if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
1433	    !devpriv->ai_urbs || !devpriv->ao_urbs)
1434		return -ENOMEM;
1435
1436	for (i = 0; i < devpriv->n_ai_urbs; i++) {
1437		/* one frame: 1ms */
1438		urb = usb_alloc_urb(1, GFP_KERNEL);
1439		if (!urb)
1440			return -ENOMEM;
1441		devpriv->ai_urbs[i] = urb;
1442		urb->dev = usb;
1443		/* will be filled later with a pointer to the comedi-device */
1444		/* and ONLY then the urb should be submitted */
1445		urb->context = NULL;
1446		urb->pipe = usb_rcvisocpipe(usb, 6);
1447		urb->transfer_flags = URB_ISO_ASAP;
1448		urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1449		if (!urb->transfer_buffer)
1450			return -ENOMEM;
1451		urb->complete = usbduxsigma_ai_urb_complete;
1452		urb->number_of_packets = 1;
1453		urb->transfer_buffer_length = SIZEINBUF;
1454		urb->iso_frame_desc[0].offset = 0;
1455		urb->iso_frame_desc[0].length = SIZEINBUF;
1456	}
1457
1458	for (i = 0; i < devpriv->n_ao_urbs; i++) {
1459		/* one frame: 1ms */
1460		urb = usb_alloc_urb(1, GFP_KERNEL);
1461		if (!urb)
1462			return -ENOMEM;
1463		devpriv->ao_urbs[i] = urb;
1464		urb->dev = usb;
1465		/* will be filled later with a pointer to the comedi-device */
1466		/* and ONLY then the urb should be submitted */
1467		urb->context = NULL;
1468		urb->pipe = usb_sndisocpipe(usb, 2);
1469		urb->transfer_flags = URB_ISO_ASAP;
1470		urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1471		if (!urb->transfer_buffer)
1472			return -ENOMEM;
1473		urb->complete = usbduxsigma_ao_urb_complete;
1474		urb->number_of_packets = 1;
1475		urb->transfer_buffer_length = SIZEOUTBUF;
1476		urb->iso_frame_desc[0].offset = 0;
1477		urb->iso_frame_desc[0].length = SIZEOUTBUF;
1478		if (devpriv->high_speed)
1479			urb->interval = 8;	/* uframes */
1480		else
1481			urb->interval = 1;	/* frames */
1482	}
1483
1484	if (devpriv->pwm_buf_sz) {
1485		urb = usb_alloc_urb(0, GFP_KERNEL);
1486		if (!urb)
1487			return -ENOMEM;
1488		devpriv->pwm_urb = urb;
1489
1490		urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
1491					       GFP_KERNEL);
1492		if (!urb->transfer_buffer)
1493			return -ENOMEM;
1494	}
1495
1496	return 0;
1497}
1498
1499static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
1500{
1501	struct usbduxsigma_private *devpriv = dev->private;
1502	struct urb *urb;
1503	int i;
1504
1505	urb = devpriv->pwm_urb;
1506	if (urb) {
1507		kfree(urb->transfer_buffer);
1508		usb_free_urb(urb);
1509	}
1510	if (devpriv->ao_urbs) {
1511		for (i = 0; i < devpriv->n_ao_urbs; i++) {
1512			urb = devpriv->ao_urbs[i];
1513			if (urb) {
1514				kfree(urb->transfer_buffer);
1515				usb_free_urb(urb);
1516			}
1517		}
1518		kfree(devpriv->ao_urbs);
1519	}
1520	if (devpriv->ai_urbs) {
1521		for (i = 0; i < devpriv->n_ai_urbs; i++) {
1522			urb = devpriv->ai_urbs[i];
1523			if (urb) {
1524				kfree(urb->transfer_buffer);
1525				usb_free_urb(urb);
1526			}
1527		}
1528		kfree(devpriv->ai_urbs);
1529	}
1530	kfree(devpriv->insn_buf);
1531	kfree(devpriv->in_buf);
1532	kfree(devpriv->dux_commands);
1533}
1534
1535static int usbduxsigma_auto_attach(struct comedi_device *dev,
1536				   unsigned long context_unused)
1537{
1538	struct usb_interface *intf = comedi_to_usb_interface(dev);
1539	struct usb_device *usb = comedi_to_usb_dev(dev);
1540	struct usbduxsigma_private *devpriv;
1541	struct comedi_subdevice *s;
1542	int offset;
1543	int ret;
1544
1545	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1546	if (!devpriv)
1547		return -ENOMEM;
1548
1549	sema_init(&devpriv->sem, 1);
1550
1551	usb_set_intfdata(intf, devpriv);
1552
1553	devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
1554	if (devpriv->high_speed) {
1555		devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
1556		devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
1557		devpriv->pwm_buf_sz = 512;
1558	} else {
1559		devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
1560		devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
1561	}
1562
1563	ret = usbduxsigma_alloc_usb_buffers(dev);
1564	if (ret)
1565		return ret;
1566
1567	/* setting to alternate setting 3: enabling iso ep and bulk ep. */
1568	ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
1569				3);
1570	if (ret < 0) {
1571		dev_err(dev->class_dev,
1572			"could not set alternate setting 3 in high speed\n");
1573		return ret;
1574	}
1575
1576	ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
1577				   usbduxsigma_firmware_upload, 0);
1578	if (ret)
1579		return ret;
1580
1581	ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 4 : 3);
1582	if (ret)
1583		return ret;
1584
1585	/* Analog Input subdevice */
1586	s = &dev->subdevices[0];
1587	dev->read_subdev = s;
1588	s->type		= COMEDI_SUBD_AI;
1589	s->subdev_flags	= SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
1590	s->n_chan	= NUMCHANNELS;
1591	s->len_chanlist	= NUMCHANNELS;
1592	s->maxdata	= 0x00ffffff;
1593	s->range_table	= &usbduxsigma_ai_range;
1594	s->insn_read	= usbduxsigma_ai_insn_read;
1595	s->do_cmdtest	= usbduxsigma_ai_cmdtest;
1596	s->do_cmd	= usbduxsigma_ai_cmd;
1597	s->cancel	= usbduxsigma_ai_cancel;
1598
1599	/* Analog Output subdevice */
1600	s = &dev->subdevices[1];
1601	dev->write_subdev = s;
1602	s->type		= COMEDI_SUBD_AO;
1603	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1604	s->n_chan	= 4;
1605	s->len_chanlist	= s->n_chan;
1606	s->maxdata	= 0x00ff;
1607	s->range_table	= &range_unipolar2_5;
1608	s->insn_write	= usbduxsigma_ao_insn_write;
1609	s->insn_read	= usbduxsigma_ao_insn_read;
1610	s->do_cmdtest	= usbduxsigma_ao_cmdtest;
1611	s->do_cmd	= usbduxsigma_ao_cmd;
1612	s->cancel	= usbduxsigma_ao_cancel;
1613
1614	ret = comedi_alloc_subdev_readback(s);
1615	if (ret)
1616		return ret;
1617
1618	/* Digital I/O subdevice */
1619	s = &dev->subdevices[2];
1620	s->type		= COMEDI_SUBD_DIO;
1621	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
1622	s->n_chan	= 24;
1623	s->maxdata	= 1;
1624	s->range_table	= &range_digital;
1625	s->insn_bits	= usbduxsigma_dio_insn_bits;
1626	s->insn_config	= usbduxsigma_dio_insn_config;
1627
1628	if (devpriv->high_speed) {
1629		/* Timer / pwm subdevice */
1630		s = &dev->subdevices[3];
1631		s->type		= COMEDI_SUBD_PWM;
1632		s->subdev_flags	= SDF_WRITABLE | SDF_PWM_HBRIDGE;
1633		s->n_chan	= 8;
1634		s->maxdata	= devpriv->pwm_buf_sz;
1635		s->insn_write	= usbduxsigma_pwm_write;
1636		s->insn_config	= usbduxsigma_pwm_config;
1637
1638		usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1639	}
1640
1641	offset = usbduxsigma_getstatusinfo(dev, 0);
1642	if (offset < 0) {
1643		dev_err(dev->class_dev,
1644			"Communication to USBDUXSIGMA failed! Check firmware and cabling.\n");
1645		return offset;
1646	}
1647
1648	dev_info(dev->class_dev, "ADC_zero = %x\n", offset);
1649
1650	return 0;
1651}
1652
1653static void usbduxsigma_detach(struct comedi_device *dev)
1654{
1655	struct usb_interface *intf = comedi_to_usb_interface(dev);
1656	struct usbduxsigma_private *devpriv = dev->private;
1657
1658	usb_set_intfdata(intf, NULL);
1659
1660	if (!devpriv)
1661		return;
1662
1663	down(&devpriv->sem);
1664
1665	/* force unlink all urbs */
1666	usbduxsigma_ai_stop(dev, 1);
1667	usbduxsigma_ao_stop(dev, 1);
1668	usbduxsigma_pwm_stop(dev, 1);
1669
1670	usbduxsigma_free_usb_buffers(dev);
1671
1672	up(&devpriv->sem);
1673}
1674
1675static struct comedi_driver usbduxsigma_driver = {
1676	.driver_name	= "usbduxsigma",
1677	.module		= THIS_MODULE,
1678	.auto_attach	= usbduxsigma_auto_attach,
1679	.detach		= usbduxsigma_detach,
1680};
1681
1682static int usbduxsigma_usb_probe(struct usb_interface *intf,
1683				 const struct usb_device_id *id)
1684{
1685	return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);
1686}
1687
1688static const struct usb_device_id usbduxsigma_usb_table[] = {
1689	{ USB_DEVICE(0x13d8, 0x0020) },
1690	{ USB_DEVICE(0x13d8, 0x0021) },
1691	{ USB_DEVICE(0x13d8, 0x0022) },
1692	{ }
1693};
1694MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
1695
1696static struct usb_driver usbduxsigma_usb_driver = {
1697	.name		= "usbduxsigma",
1698	.probe		= usbduxsigma_usb_probe,
1699	.disconnect	= comedi_usb_auto_unconfig,
1700	.id_table	= usbduxsigma_usb_table,
1701};
1702module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
1703
1704MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1705MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
1706MODULE_LICENSE("GPL");
1707MODULE_FIRMWARE(FIRMWARE);
1708