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