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