Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/staging/comedi/drivers/usbduxsigma.c

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us