Version:  2.0.40 2.2.26 2.4.37 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 3.19 4.0

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

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

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