Version:  2.0.40 2.2.26 2.4.37 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 3.16 3.17 3.18

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

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