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