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

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

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