2 comedi/drivers/usbdux.c
3 Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com
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.
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.
17 Description: University of Stirling USB DAQ & INCITE Technology Limited
18 Devices: [ITL] USB-DUX (usbduxsigma.o)
19 Author: Bernd Porr <BerndPorr@f2s.com>
24 * I must give credit here to Chris Baugher who
25 * wrote the driver for AT-MIO-16d. I used some parts of this
26 * driver. I also must give credits to David Brownell
27 * who supported me with the USB development.
29 * Note: the raw data from the A/D converter is 24 bit big endian
30 * anything else is little endian to/from the dux board
34 * 0.1: initial version
35 * 0.2: all basic functions implemented, digital I/O only for one port
36 * 0.3: proper vendor ID and driver name
37 * 0.4: fixed D/A voltage range
38 * 0.5: various bug fixes, health check at startup
39 * 0.6: corrected wrong input range
42 /* generates loads of debug info */
43 /* #define NOISY_DUX_DEBUGBUG */
45 #include <linux/kernel.h>
46 #include <linux/module.h>
47 #include <linux/init.h>
48 #include <linux/slab.h>
49 #include <linux/input.h>
50 #include <linux/usb.h>
51 #include <linux/fcntl.h>
52 #include <linux/compiler.h>
54 #include "comedi_fc.h"
55 #include "../comedidev.h"
57 /* timeout for the USB-transfer in ms*/
58 #define BULK_TIMEOUT 1000
60 /* constants for "firmware" upload and download */
61 #define FIRMWARE "usbduxsigma_firmware.bin"
62 #define USBDUXSUB_FIRMWARE 0xA0
63 #define VENDOR_DIR_IN 0xC0
64 #define VENDOR_DIR_OUT 0x40
66 /* internal addresses of the 8051 processor */
67 #define USBDUXSUB_CPUCS 0xE600
70 * the minor device number, major is 180 only for debugging purposes and to
71 * upload special firmware (programming the eeprom etc) which is not
72 * compatible with the comedi framwork
74 #define USBDUXSUB_MINOR 32
76 /* max lenghth of the transfer-buffer for software upload */
79 /* Input endpoint number: ISO/IRQ */
82 /* Output endpoint number: ISO/IRQ */
85 /* This EP sends DUX commands to USBDUX */
86 #define COMMAND_OUT_EP 1
88 /* This EP receives the DUX commands from USBDUX */
89 #define COMMAND_IN_EP 8
91 /* Output endpoint for PWM */
94 /* 300Hz max frequ under PWM */
95 #define MIN_PWM_PERIOD ((long)(1E9/300))
97 /* Default PWM frequency */
98 #define PWM_DEFAULT_PERIOD ((long)(1E9/100))
100 /* Number of channels (16 AD and offset)*/
101 #define NUMCHANNELS 16
103 /* Size of one A/D value */
104 #define SIZEADIN ((sizeof(int32_t)))
107 * Size of the async input-buffer IN BYTES, the DIO state is transmitted
110 #define SIZEINBUF (((NUMCHANNELS+1)*SIZEADIN))
113 #define SIZEINSNBUF 16
115 /* Number of DA channels */
116 #define NUMOUTCHANNELS 8
118 /* size of one value for the D/A converter: channel and value */
119 #define SIZEDAOUT ((sizeof(uint8_t)+sizeof(int16_t)))
122 * Size of the output-buffer in bytes
123 * Actually only the first 4 triplets are used but for the
124 * high speed mode we need to pad it to 8 (microframes).
126 #define SIZEOUTBUF ((8*SIZEDAOUT))
129 * Size of the buffer for the dux commands: just now max size is determined
130 * by the analogue out + command byte + panic bytes...
132 #define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2))
134 /* Number of in-URBs which receive the data: min=2 */
135 #define NUMOFINBUFFERSFULL 5
137 /* Number of out-URBs which send the data: min=2 */
138 #define NUMOFOUTBUFFERSFULL 5
140 /* Number of in-URBs which receive the data: min=5 */
141 /* must have more buffers due to buggy USB ctr */
142 #define NUMOFINBUFFERSHIGH 10
144 /* Number of out-URBs which send the data: min=5 */
145 /* must have more buffers due to buggy USB ctr */
146 #define NUMOFOUTBUFFERSHIGH 10
148 /* Total number of usbdux devices */
151 /* Analogue in subdevice */
154 /* Analogue out subdevice */
160 /* timer aka pwm output */
163 /* number of retries to get the right dux command */
166 /**************************************************/
167 /* comedi constants */
168 static const struct comedi_lrange range_usbdux_ai_range = { 1, {
174 struct usbduxsigma_private {
177 /* is it associated with a subdevice? */
179 /* pointer to the usb-device */
180 struct usb_device *usbdev;
181 /* actual number of in-buffers */
183 /* actual number of out-buffers */
185 /* ISO-transfer handling: buffers */
188 /* pwm-transfer handling */
191 unsigned int pwmPeriod;
192 /* PWM internal delay for the GPIF in the FX2 */
194 /* size of the PWM buffer which holds the bit pattern */
196 /* input buffer for the ISO-transfer */
198 /* input buffer for single insn */
200 /* output buffer for single DA outputs */
202 /* interface number */
204 /* interface structure in 2.6 */
205 struct usb_interface *interface;
206 /* comedi device for the interrupt context */
207 struct comedi_device *comedidev;
208 /* is it USB_SPEED_HIGH or not? */
209 short int high_speed;
210 /* asynchronous command is running */
211 short int ai_cmd_running;
212 short int ao_cmd_running;
214 short int pwm_cmd_running;
215 /* continuous acquisition */
216 short int ai_continuous;
217 short int ao_continuous;
218 /* number of samples to acquire */
221 /* time between samples in units of the timer */
222 unsigned int ai_timer;
223 unsigned int ao_timer;
224 /* counter between acquisitions */
225 unsigned int ai_counter;
226 unsigned int ao_counter;
227 /* interval in frames/uframes */
228 unsigned int ai_interval;
230 uint8_t *dac_commands;
232 uint8_t *dux_commands;
233 struct semaphore sem;
237 * The pointer to the private usb-data of the driver is also the private data
238 * for the comedi-device. This has to be global as the usb subsystem needs
239 * global variables. The other reason is that this structure must be there
240 * _before_ any comedi command is issued. The usb subsystem must be initialised
241 * before comedi can access it.
243 static struct usbduxsigma_private usbduxsub[NUMUSBDUX];
245 static DEFINE_SEMAPHORE(start_stop_sem);
247 static void usbdux_ai_stop(struct usbduxsigma_private *devpriv, int do_unlink)
252 for (i = 0; i < devpriv->numOfInBuffers; i++) {
253 if (devpriv->urbIn[i])
254 usb_kill_urb(devpriv->urbIn[i]);
258 devpriv->ai_cmd_running = 0;
261 static int usbdux_ai_cancel(struct comedi_device *dev,
262 struct comedi_subdevice *s)
264 struct usbduxsigma_private *devpriv = dev->private;
267 /* unlink only if it is really running */
268 usbdux_ai_stop(devpriv, devpriv->ai_cmd_running);
274 static void usbduxsub_ai_IsocIrq(struct urb *urb)
276 struct comedi_device *dev = urb->context;
277 struct usbduxsigma_private *devpriv = dev->private;
278 struct comedi_subdevice *s = dev->read_subdev;
279 unsigned int dio_state;
284 /* first we test if something unusual has just happened */
285 switch (urb->status) {
287 /* copy the result in the transfer buffer */
288 memcpy(devpriv->inBuffer, urb->transfer_buffer, SIZEINBUF);
292 * error in the ISOchronous data
293 * we don't copy the data into the transfer buffer
294 * and recycle the last data byte
296 dev_dbg(dev->class_dev,"CRC error in ISO IN stream\n");
304 /* happens after an unlink command */
305 if (devpriv->ai_cmd_running) {
306 usbdux_ai_stop(devpriv, 0); /* w/o unlink */
307 /* we are still running a command, tell comedi */
308 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
309 comedi_event(dev, s);
315 * a real error on the bus
316 * pass error to comedi if we are really running a command
318 if (devpriv->ai_cmd_running) {
319 dev_err(dev->class_dev,
320 "%s: non-zero urb status (%d)\n",
321 __func__, urb->status);
322 usbdux_ai_stop(devpriv, 0); /* w/o unlink */
323 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
324 comedi_event(dev, s);
329 if (unlikely(!devpriv->ai_cmd_running))
332 urb->dev = devpriv->usbdev;
334 ret = usb_submit_urb(urb, GFP_ATOMIC);
335 if (unlikely(ret < 0)) {
336 dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
338 if (ret == -EL2NSYNC)
339 dev_err(dev->class_dev,
340 "buggy USB host controller or bug in IRQ handler\n");
341 usbdux_ai_stop(devpriv, 0); /* w/o unlink */
342 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
343 comedi_event(dev, s);
347 /* get the state of the dio pins to allow external trigger */
348 dio_state = be32_to_cpu(devpriv->inBuffer[0]);
350 devpriv->ai_counter--;
351 if (likely(devpriv->ai_counter > 0))
354 /* timer zero, transfer measurements to comedi */
355 devpriv->ai_counter = devpriv->ai_timer;
357 if (!devpriv->ai_continuous) {
358 /* not continuous, fixed number of samples */
359 devpriv->ai_sample_count--;
360 if (devpriv->ai_sample_count < 0) {
361 usbdux_ai_stop(devpriv, 0); /* w/o unlink */
362 /* acquistion is over, tell comedi */
363 s->async->events |= COMEDI_CB_EOA;
364 comedi_event(dev, s);
369 /* get the data from the USB bus and hand it over to comedi */
370 for (i = 0; i < s->async->cmd.chanlist_len; i++) {
371 /* transfer data, note first byte is the DIO state */
372 val = be32_to_cpu(devpriv->inBuffer[i+1]);
373 val &= 0x00ffffff; /* strip status byte */
374 val ^= 0x00800000; /* convert to unsigned */
376 ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
377 if (unlikely(ret == 0)) {
378 /* buffer overflow */
379 usbdux_ai_stop(devpriv, 0); /* w/o unlink */
383 /* tell comedi that data is there */
384 s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
385 comedi_event(dev, s);
388 static void usbdux_ao_stop(struct usbduxsigma_private *devpriv, int do_unlink)
393 for (i = 0; i < devpriv->numOfOutBuffers; i++) {
394 if (devpriv->urbOut[i])
395 usb_kill_urb(devpriv->urbOut[i]);
399 devpriv->ao_cmd_running = 0;
402 static int usbdux_ao_cancel(struct comedi_device *dev,
403 struct comedi_subdevice *s)
405 struct usbduxsigma_private *devpriv = dev->private;
408 /* unlink only if it is really running */
409 usbdux_ao_stop(devpriv, devpriv->ao_cmd_running);
415 static void usbduxsub_ao_IsocIrq(struct urb *urb)
417 struct comedi_device *dev = urb->context;
418 struct usbduxsigma_private *devpriv = dev->private;
419 struct comedi_subdevice *s = dev->write_subdev;
425 switch (urb->status) {
434 /* happens after an unlink command */
435 if (devpriv->ao_cmd_running) {
436 usbdux_ao_stop(devpriv, 0); /* w/o unlink */
437 s->async->events |= COMEDI_CB_EOA;
438 comedi_event(devpriv->comedidev, s);
444 if (devpriv->ao_cmd_running) {
445 dev_err(dev->class_dev,
446 "%s: non-zero urb status (%d)\n",
447 __func__, urb->status);
448 usbdux_ao_stop(devpriv, 0); /* w/o unlink */
449 s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
450 comedi_event(devpriv->comedidev, s);
455 if (!devpriv->ao_cmd_running)
458 devpriv->ao_counter--;
459 if ((int)devpriv->ao_counter <= 0) {
460 /* timer zero, transfer from comedi */
461 devpriv->ao_counter = devpriv->ao_timer;
463 if (!devpriv->ao_continuous) {
464 /* not continuous, fixed number of samples */
465 devpriv->ao_sample_count--;
466 if (devpriv->ao_sample_count < 0) {
467 usbdux_ao_stop(devpriv, 0); /* w/o unlink */
468 /* acquistion is over, tell comedi */
469 s->async->events |= COMEDI_CB_EOA;
470 comedi_event(devpriv->comedidev, s);
475 /* transmit data to the USB bus */
476 datap = urb->transfer_buffer;
477 len = s->async->cmd.chanlist_len;
479 for (i = 0; i < len; i++) {
482 if (i >= NUMOUTCHANNELS)
485 ret = comedi_buf_get(s->async, &val);
487 dev_err(dev->class_dev, "buffer underflow\n");
488 s->async->events |= (COMEDI_CB_EOA |
492 *datap++ = devpriv->dac_commands[i];
494 s->async->events |= COMEDI_CB_BLOCK;
495 comedi_event(dev, s);
499 urb->transfer_buffer_length = SIZEOUTBUF;
500 urb->dev = devpriv->usbdev;
502 if (devpriv->high_speed)
503 urb->interval = 8; /* uframes */
505 urb->interval = 1; /* frames */
506 urb->number_of_packets = 1;
507 urb->iso_frame_desc[0].offset = 0;
508 urb->iso_frame_desc[0].length = SIZEOUTBUF;
509 urb->iso_frame_desc[0].status = 0;
510 ret = usb_submit_urb(urb, GFP_ATOMIC);
512 dev_err(dev->class_dev,
513 "%s: urb resubmit failed (%d)\n",
516 dev_err(dev->class_dev,
517 "buggy USB host controller or bug in IRQ handler\n");
518 usbdux_ao_stop(devpriv, 0); /* w/o unlink */
519 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
520 comedi_event(dev, s);
524 /* the FX2LP has twice as much as the standard FX2 */
525 #define FIRMWARE_MAX_LEN 0x4000
527 static int usbduxsigma_firmware_upload(struct comedi_device *dev,
528 const u8 *data, size_t size,
529 unsigned long context)
531 struct usbduxsigma_private *usbduxsub = dev->private;
532 struct usb_device *usb = usbduxsub->usbdev;
540 if (size > FIRMWARE_MAX_LEN) {
541 dev_err(&usbduxsub->interface->dev,
542 "usbduxsigma firmware binary it too large for FX2.\n");
546 /* we generate a local buffer for the firmware */
547 buf = kmemdup(data, size, GFP_KERNEL);
549 dev_err(&usbduxsub->interface->dev,
550 "comedi_: mem alloc for firmware failed\n");
554 /* we need a malloc'ed buffer for usb_control_msg() */
555 tmp = kmalloc(1, GFP_KERNEL);
561 /* stop the current firmware on the device */
562 *tmp = 1; /* 7f92 to one */
563 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
566 USBDUXSUB_CPUCS, 0x0000,
570 dev_err(&usbduxsub->interface->dev,
571 "comedi_: can not stop firmware\n");
575 /* upload the new firmware to the device */
576 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
583 dev_err(&usbduxsub->interface->dev,
584 "comedi_: firmware upload failed\n");
588 /* start the new firmware on the device */
589 *tmp = 0; /* 7f92 to zero */
590 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
593 USBDUXSUB_CPUCS, 0x0000,
597 dev_err(&usbduxsub->interface->dev,
598 "comedi_: can not start firmware\n");
606 static int usbduxsigma_submit_urbs(struct comedi_device *dev,
607 struct urb **urbs, int num_urbs,
610 struct usbduxsigma_private *devpriv = dev->private;
615 /* Submit all URBs and start the transfer on the bus */
616 for (i = 0; i < num_urbs; i++) {
619 /* in case of a resubmission after an unlink... */
621 urb->interval = devpriv->ai_interval;
623 urb->dev = devpriv->usbdev;
625 urb->transfer_flags = URB_ISO_ASAP;
627 ret = usb_submit_urb(urb, GFP_ATOMIC);
634 static int chanToInterval(int nChannels)
646 static int usbdux_ai_cmdtest(struct comedi_device *dev,
647 struct comedi_subdevice *s,
648 struct comedi_cmd *cmd)
650 struct usbduxsigma_private *this_usbduxsub = dev->private;
652 unsigned int tmpTimer;
654 /* Step 1 : check if triggers are trivially valid */
656 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
657 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
658 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
659 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
660 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
665 /* Step 2a : make sure trigger sources are unique */
667 err |= cfc_check_trigger_is_unique(cmd->start_src);
668 err |= cfc_check_trigger_is_unique(cmd->stop_src);
670 /* Step 2b : and mutually compatible */
675 /* Step 3: check if arguments are trivially valid */
677 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
679 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
680 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
682 if (cmd->scan_begin_src == TRIG_TIMER) {
683 if (this_usbduxsub->high_speed) {
685 * In high speed mode microframes are possible.
686 * However, during one microframe we can roughly
687 * sample two channels. Thus, the more channels
688 * are in the channel list the more time we need.
690 i = chanToInterval(cmd->chanlist_len);
691 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
693 /* now calc the real sampling rate with all the
696 ((unsigned int)(cmd->scan_begin_arg / 125000)) *
700 /* 1kHz scans every USB frame */
701 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
704 * calc the real sampling rate with the rounding errors
706 tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
709 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
713 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
715 if (cmd->stop_src == TRIG_COUNT) {
716 /* any count is allowed */
719 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
729 * creates the ADC command for the MAX1271
730 * range is the range value from comedi
732 static void create_adc_command(unsigned int chan,
737 (*muxsg0) = (*muxsg0) | (1 << chan);
739 (*muxsg1) = (*muxsg1) | (1 << (chan-8));
743 /* bulk transfers to usbdux */
745 #define SENDADCOMMANDS 0
746 #define SENDDACOMMANDS 1
747 #define SENDDIOCONFIGCOMMAND 2
748 #define SENDDIOBITSCOMMAND 3
749 #define SENDSINGLEAD 4
753 static int send_dux_commands(struct usbduxsigma_private *this_usbduxsub,
758 this_usbduxsub->dux_commands[0] = cmd_type;
759 #ifdef NOISY_DUX_DEBUGBUG
760 printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
761 this_usbduxsub->comedidev->minor);
762 for (result = 0; result < SIZEOFDUXBUFFER; result++)
763 printk(" %02x", this_usbduxsub->dux_commands[result]);
766 result = usb_bulk_msg(this_usbduxsub->usbdev,
767 usb_sndbulkpipe(this_usbduxsub->usbdev,
769 this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
770 &nsent, BULK_TIMEOUT);
772 dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
773 "could not transmit dux_command to the usb-device, "
774 "err=%d\n", this_usbduxsub->comedidev->minor, result);
779 static int receive_dux_commands(struct usbduxsigma_private *this_usbduxsub,
782 int result = (-EFAULT);
786 for (i = 0; i < RETRIES; i++) {
787 result = usb_bulk_msg(this_usbduxsub->usbdev,
788 usb_rcvbulkpipe(this_usbduxsub->usbdev,
790 this_usbduxsub->insnBuffer, SIZEINSNBUF,
791 &nrec, BULK_TIMEOUT);
793 dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
794 "insn: USB error %d "
795 "while receiving DUX command"
796 "\n", this_usbduxsub->comedidev->minor,
800 if (this_usbduxsub->insnBuffer[0] == command)
803 /* this is only reached if the data has been requested a couple of
808 static int usbdux_ai_inttrig(struct comedi_device *dev,
809 struct comedi_subdevice *s, unsigned int trignum)
811 struct usbduxsigma_private *this_usbduxsub = dev->private;
816 down(&this_usbduxsub->sem);
818 dev_err(&this_usbduxsub->interface->dev,
819 "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
821 up(&this_usbduxsub->sem);
824 if (!this_usbduxsub->ai_cmd_running) {
825 ret = usbduxsigma_submit_urbs(dev, this_usbduxsub->urbIn,
826 this_usbduxsub->numOfInBuffers,
829 up(&this_usbduxsub->sem);
832 this_usbduxsub->ai_cmd_running = 1;
833 s->async->inttrig = NULL;
835 dev_err(&this_usbduxsub->interface->dev,
836 "comedi%d: ai_inttrig but acqu is already running\n",
839 up(&this_usbduxsub->sem);
843 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
845 struct usbduxsigma_private *this_usbduxsub = dev->private;
846 struct comedi_cmd *cmd = &s->async->cmd;
857 /* block other CPUs from starting an ai_cmd */
858 down(&this_usbduxsub->sem);
859 if (this_usbduxsub->ai_cmd_running) {
860 dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
861 "ai_cmd not possible. Another ai_cmd is running.\n",
863 up(&this_usbduxsub->sem);
866 /* set current channel of the running acquisition to zero */
867 s->async->cur_chan = 0;
869 /* first the number of channels per time step */
870 this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
873 this_usbduxsub->dux_commands[2] = 0x12;
875 /* CONFIG1: 23kHz sampling rate, delay = 0us, */
876 this_usbduxsub->dux_commands[3] = 0x03;
878 /* CONFIG3: differential channels off */
879 this_usbduxsub->dux_commands[4] = 0x00;
881 for (i = 0; i < cmd->chanlist_len; i++) {
882 chan = CR_CHAN(cmd->chanlist[i]);
883 create_adc_command(chan, &muxsg0, &muxsg1);
884 if (i >= NUMCHANNELS) {
885 dev_err(&this_usbduxsub->interface->dev,
886 "comedi%d: channel list too long\n",
891 this_usbduxsub->dux_commands[5] = muxsg0;
892 this_usbduxsub->dux_commands[6] = muxsg1;
893 this_usbduxsub->dux_commands[7] = sysred;
895 result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
897 up(&this_usbduxsub->sem);
901 if (this_usbduxsub->high_speed) {
903 * every 2 channels get a time window of 125us. Thus, if we
904 * sample all 16 channels we need 1ms. If we sample only one
905 * channel we need only 125us
907 this_usbduxsub->ai_interval =
908 chanToInterval(cmd->chanlist_len);
909 this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
913 /* interval always 1ms */
914 this_usbduxsub->ai_interval = 1;
915 this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
917 if (this_usbduxsub->ai_timer < 1) {
918 dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
919 "timer=%d, scan_begin_arg=%d. "
920 "Not properly tested by cmdtest?\n", dev->minor,
921 this_usbduxsub->ai_timer, cmd->scan_begin_arg);
922 up(&this_usbduxsub->sem);
925 this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
927 if (cmd->stop_src == TRIG_COUNT) {
928 /* data arrives as one packet */
929 this_usbduxsub->ai_sample_count = cmd->stop_arg;
930 this_usbduxsub->ai_continuous = 0;
932 /* continuous acquisition */
933 this_usbduxsub->ai_continuous = 1;
934 this_usbduxsub->ai_sample_count = 0;
937 if (cmd->start_src == TRIG_NOW) {
938 /* enable this acquisition operation */
939 ret = usbduxsigma_submit_urbs(dev, this_usbduxsub->urbIn,
940 this_usbduxsub->numOfInBuffers,
943 up(&this_usbduxsub->sem);
946 this_usbduxsub->ai_cmd_running = 1;
947 s->async->inttrig = NULL;
950 /* don't enable the acquision operation */
951 /* wait for an internal signal */
952 s->async->inttrig = usbdux_ai_inttrig;
954 up(&this_usbduxsub->sem);
958 /* Mode 0 is used to get a single conversion on demand */
959 static int usbdux_ai_insn_read(struct comedi_device *dev,
960 struct comedi_subdevice *s,
961 struct comedi_insn *insn, unsigned int *data)
963 struct usbduxsigma_private *this_usbduxsub = dev->private;
975 down(&this_usbduxsub->sem);
976 if (this_usbduxsub->ai_cmd_running) {
977 dev_err(&this_usbduxsub->interface->dev,
978 "comedi%d: ai_insn_read not possible. "
979 "Async Command is running.\n", dev->minor);
980 up(&this_usbduxsub->sem);
984 /* sample one channel */
985 /* CONFIG0: chopper on */
986 this_usbduxsub->dux_commands[1] = 0x16;
988 /* CONFIG1: 2kHz sampling rate */
989 this_usbduxsub->dux_commands[2] = 0x80;
991 /* CONFIG3: differential channels off */
992 this_usbduxsub->dux_commands[3] = 0x00;
994 chan = CR_CHAN(insn->chanspec);
995 create_adc_command(chan, &muxsg0, &muxsg1);
997 this_usbduxsub->dux_commands[4] = muxsg0;
998 this_usbduxsub->dux_commands[5] = muxsg1;
999 this_usbduxsub->dux_commands[6] = sysred;
1002 err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1004 up(&this_usbduxsub->sem);
1008 for (i = 0; i < insn->n; i++) {
1009 err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1011 up(&this_usbduxsub->sem);
1014 /* 32 bits big endian from the A/D converter */
1015 one = be32_to_cpu(*((int32_t *)
1016 ((this_usbduxsub->insnBuffer)+1)));
1017 /* mask out the status byte */
1018 one = one & 0x00ffffff;
1019 /* turn it into an unsigned integer */
1020 one = one ^ 0x00800000;
1023 up(&this_usbduxsub->sem);
1030 static int usbdux_getstatusinfo(struct comedi_device *dev, int chan)
1032 struct usbduxsigma_private *this_usbduxsub = dev->private;
1037 if (!this_usbduxsub)
1040 if (this_usbduxsub->ai_cmd_running) {
1041 dev_err(&this_usbduxsub->interface->dev,
1042 "comedi%d: status read not possible. "
1043 "Async Command is running.\n", dev->minor);
1048 this_usbduxsub->dux_commands[1] = 0x12;
1050 /* CONFIG1: 2kHz sampling rate */
1051 this_usbduxsub->dux_commands[2] = 0x80;
1053 /* CONFIG3: differential channels off */
1054 this_usbduxsub->dux_commands[3] = 0x00;
1058 sysred = sysred | 1;
1059 } else if (chan == 2) {
1061 sysred = sysred | 4;
1062 } else if (chan == 3) {
1064 sysred = sysred | 8;
1065 } else if (chan == 4) {
1067 sysred = sysred | 16;
1068 } else if (chan == 5) {
1070 sysred = sysred | 32;
1073 this_usbduxsub->dux_commands[4] = 0;
1074 this_usbduxsub->dux_commands[5] = 0;
1075 this_usbduxsub->dux_commands[6] = sysred;
1078 err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
1082 err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
1086 /* 32 bits big endian from the A/D converter */
1087 one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1)));
1088 /* mask out the status byte */
1089 one = one & 0x00ffffff;
1090 one = one ^ 0x00800000;
1100 /************************************/
1103 static int usbdux_ao_insn_read(struct comedi_device *dev,
1104 struct comedi_subdevice *s,
1105 struct comedi_insn *insn, unsigned int *data)
1107 struct usbduxsigma_private *this_usbduxsub = dev->private;
1109 int chan = CR_CHAN(insn->chanspec);
1111 if (!this_usbduxsub)
1114 down(&this_usbduxsub->sem);
1115 for (i = 0; i < insn->n; i++)
1116 data[i] = this_usbduxsub->outBuffer[chan];
1118 up(&this_usbduxsub->sem);
1122 static int usbdux_ao_insn_write(struct comedi_device *dev,
1123 struct comedi_subdevice *s,
1124 struct comedi_insn *insn, unsigned int *data)
1126 struct usbduxsigma_private *this_usbduxsub = dev->private;
1128 int chan = CR_CHAN(insn->chanspec);
1130 if (!this_usbduxsub)
1133 down(&this_usbduxsub->sem);
1134 if (this_usbduxsub->ao_cmd_running) {
1135 dev_err(&this_usbduxsub->interface->dev,
1136 "comedi%d: ao_insn_write: "
1137 "ERROR: asynchronous ao_cmd is running\n", dev->minor);
1138 up(&this_usbduxsub->sem);
1142 for (i = 0; i < insn->n; i++) {
1143 dev_dbg(&this_usbduxsub->interface->dev,
1144 "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
1145 dev->minor, chan, i, data[i]);
1147 /* number of channels: 1 */
1148 this_usbduxsub->dux_commands[1] = 1;
1149 /* channel number */
1150 this_usbduxsub->dux_commands[2] = data[i];
1151 this_usbduxsub->outBuffer[chan] = data[i];
1152 this_usbduxsub->dux_commands[3] = chan;
1153 err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
1155 up(&this_usbduxsub->sem);
1159 up(&this_usbduxsub->sem);
1164 static int usbdux_ao_inttrig(struct comedi_device *dev,
1165 struct comedi_subdevice *s, unsigned int trignum)
1167 struct usbduxsigma_private *this_usbduxsub = dev->private;
1170 if (!this_usbduxsub)
1173 down(&this_usbduxsub->sem);
1175 dev_err(&this_usbduxsub->interface->dev,
1176 "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
1181 if (!(this_usbduxsub->ao_cmd_running)) {
1182 ret = usbduxsigma_submit_urbs(dev, this_usbduxsub->urbOut,
1183 this_usbduxsub->numOfOutBuffers,
1187 this_usbduxsub->ao_cmd_running = 1;
1188 s->async->inttrig = NULL;
1190 dev_err(&this_usbduxsub->interface->dev,
1191 "comedi%d: ao_inttrig but acqu is already running.\n",
1196 up(&this_usbduxsub->sem);
1200 static int usbdux_ao_cmdtest(struct comedi_device *dev,
1201 struct comedi_subdevice *s,
1202 struct comedi_cmd *cmd)
1204 struct usbduxsigma_private *this_usbduxsub = dev->private;
1208 if (!this_usbduxsub)
1211 /* Step 1 : check if triggers are trivially valid */
1213 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
1215 if (0) { /* (this_usbduxsub->high_speed) */
1217 * start immediately a new scan
1218 * the sampling rate is set by the coversion rate
1220 flags = TRIG_FOLLOW;
1222 /* start a new scan (output at once) with a timer */
1225 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1227 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
1228 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1229 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1234 /* Step 2a : make sure trigger sources are unique */
1236 err |= cfc_check_trigger_is_unique(cmd->start_src);
1237 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1239 /* Step 2b : and mutually compatible */
1244 /* Step 3: check if arguments are trivially valid */
1246 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1248 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
1249 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1251 if (cmd->scan_begin_src == TRIG_TIMER)
1252 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1255 /* not used now, is for later use */
1256 if (cmd->convert_src == TRIG_TIMER)
1257 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
1259 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1261 if (cmd->stop_src == TRIG_COUNT) {
1262 /* any count is allowed */
1265 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1274 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1276 struct usbduxsigma_private *this_usbduxsub = dev->private;
1277 struct comedi_cmd *cmd = &s->async->cmd;
1278 unsigned int chan, gain;
1281 if (!this_usbduxsub)
1284 down(&this_usbduxsub->sem);
1285 /* set current channel of the running acquisition to zero */
1286 s->async->cur_chan = 0;
1287 for (i = 0; i < cmd->chanlist_len; ++i) {
1288 chan = CR_CHAN(cmd->chanlist[i]);
1289 gain = CR_RANGE(cmd->chanlist[i]);
1290 if (i >= NUMOUTCHANNELS) {
1291 dev_err(&this_usbduxsub->interface->dev,
1292 "comedi%d: %s: channel list too long\n",
1293 dev->minor, __func__);
1296 this_usbduxsub->dac_commands[i] = chan;
1297 dev_dbg(&this_usbduxsub->interface->dev,
1298 "comedi%d: dac command for ch %d is %x\n",
1299 dev->minor, i, this_usbduxsub->dac_commands[i]);
1302 /* we count in steps of 1ms (125us) */
1303 /* 125us mode not used yet */
1304 if (0) { /* (this_usbduxsub->high_speed) */
1306 /* timing of the conversion itself: every 125 us */
1307 this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
1310 /* timing of the scan: we get all channels at once */
1311 this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
1312 dev_dbg(&this_usbduxsub->interface->dev,
1313 "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
1314 "convert_src=%d, convert_arg=%d\n", dev->minor,
1315 cmd->scan_begin_src, cmd->scan_begin_arg,
1316 cmd->convert_src, cmd->convert_arg);
1317 dev_dbg(&this_usbduxsub->interface->dev,
1318 "comedi%d: ao_timer=%d (ms)\n",
1319 dev->minor, this_usbduxsub->ao_timer);
1320 if (this_usbduxsub->ao_timer < 1) {
1321 dev_err(&this_usbduxsub->interface->dev,
1322 "comedi%d: usbdux: ao_timer=%d, "
1323 "scan_begin_arg=%d. "
1324 "Not properly tested by cmdtest?\n",
1325 dev->minor, this_usbduxsub->ao_timer,
1326 cmd->scan_begin_arg);
1327 up(&this_usbduxsub->sem);
1331 this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
1333 if (cmd->stop_src == TRIG_COUNT) {
1334 /* not continuous */
1336 /* high speed also scans everything at once */
1337 if (0) { /* (this_usbduxsub->high_speed) */
1338 this_usbduxsub->ao_sample_count =
1339 (cmd->stop_arg) * (cmd->scan_end_arg);
1341 /* there's no scan as the scan has been */
1342 /* perf inside the FX2 */
1343 /* data arrives as one packet */
1344 this_usbduxsub->ao_sample_count = cmd->stop_arg;
1346 this_usbduxsub->ao_continuous = 0;
1348 /* continuous acquisition */
1349 this_usbduxsub->ao_continuous = 1;
1350 this_usbduxsub->ao_sample_count = 0;
1353 if (cmd->start_src == TRIG_NOW) {
1354 /* enable this acquisition operation */
1355 ret = usbduxsigma_submit_urbs(dev, this_usbduxsub->urbOut,
1356 this_usbduxsub->numOfOutBuffers,
1359 up(&this_usbduxsub->sem);
1362 this_usbduxsub->ao_cmd_running = 1;
1363 s->async->inttrig = NULL;
1366 /* submit the urbs later */
1367 /* wait for an internal signal */
1368 s->async->inttrig = usbdux_ao_inttrig;
1371 up(&this_usbduxsub->sem);
1375 static int usbdux_dio_insn_config(struct comedi_device *dev,
1376 struct comedi_subdevice *s,
1377 struct comedi_insn *insn, unsigned int *data)
1379 int chan = CR_CHAN(insn->chanspec);
1381 /* The input or output configuration of each digital line is
1382 * configured by a special insn_config instruction. chanspec
1383 * contains the channel to be changed, and data[0] contains the
1384 * value COMEDI_INPUT or COMEDI_OUTPUT. */
1387 case INSN_CONFIG_DIO_OUTPUT:
1388 s->io_bits |= 1 << chan; /* 1 means Out */
1390 case INSN_CONFIG_DIO_INPUT:
1391 s->io_bits &= ~(1 << chan);
1393 case INSN_CONFIG_DIO_QUERY:
1395 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1401 /* we don't tell the firmware here as it would take 8 frames */
1402 /* to submit the information. We do it in the insn_bits. */
1406 static int usbdux_dio_insn_bits(struct comedi_device *dev,
1407 struct comedi_subdevice *s,
1408 struct comedi_insn *insn,
1411 struct usbduxsigma_private *this_usbduxsub = dev->private;
1414 if (!this_usbduxsub)
1417 down(&this_usbduxsub->sem);
1419 /* The insn data is a mask in data[0] and the new data
1420 * in data[1], each channel cooresponding to a bit. */
1421 s->state &= ~data[0];
1422 s->state |= data[0] & data[1];
1423 /* The commands are 8 bits wide */
1424 this_usbduxsub->dux_commands[1] = (s->io_bits) & 0x000000FF;
1425 this_usbduxsub->dux_commands[4] = (s->state) & 0x000000FF;
1426 this_usbduxsub->dux_commands[2] = ((s->io_bits) & 0x0000FF00) >> 8;
1427 this_usbduxsub->dux_commands[5] = ((s->state) & 0x0000FF00) >> 8;
1428 this_usbduxsub->dux_commands[3] = ((s->io_bits) & 0x00FF0000) >> 16;
1429 this_usbduxsub->dux_commands[6] = ((s->state) & 0x00FF0000) >> 16;
1431 /* This command also tells the firmware to return */
1432 /* the digital input lines */
1433 err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1435 up(&this_usbduxsub->sem);
1438 err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
1440 up(&this_usbduxsub->sem);
1444 data[1] = (((unsigned int)(this_usbduxsub->insnBuffer[1]))&0xff) |
1445 ((((unsigned int)(this_usbduxsub->insnBuffer[2]))&0xff) << 8) |
1446 ((((unsigned int)(this_usbduxsub->insnBuffer[3]))&0xff) << 16);
1450 up(&this_usbduxsub->sem);
1454 static void usbdux_pwm_stop(struct usbduxsigma_private *devpriv, int do_unlink)
1457 if (devpriv->urbPwm)
1458 usb_kill_urb(devpriv->urbPwm);
1461 devpriv->pwm_cmd_running = 0;
1464 static int usbdux_pwm_cancel(struct comedi_device *dev,
1465 struct comedi_subdevice *s)
1467 struct usbduxsigma_private *devpriv = dev->private;
1469 /* unlink only if it is really running */
1470 usbdux_pwm_stop(devpriv, devpriv->pwm_cmd_running);
1472 return send_dux_commands(devpriv, SENDPWMOFF);
1475 static void usbduxsub_pwm_irq(struct urb *urb)
1477 struct comedi_device *dev = urb->context;
1478 struct usbduxsigma_private *devpriv = dev->private;
1481 switch (urb->status) {
1490 /* happens after an unlink command */
1491 if (devpriv->pwm_cmd_running)
1492 usbdux_pwm_stop(devpriv, 0); /* w/o unlink */
1497 if (devpriv->pwm_cmd_running) {
1498 dev_err(dev->class_dev,
1499 "%s: non-zero urb status (%d)\n",
1500 __func__, urb->status);
1501 usbdux_pwm_stop(devpriv, 0); /* w/o unlink */
1506 if (!devpriv->pwm_cmd_running)
1509 urb->transfer_buffer_length = devpriv->sizePwmBuf;
1510 urb->dev = devpriv->usbdev;
1512 ret = usb_submit_urb(urb, GFP_ATOMIC);
1514 dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
1516 if (ret == EL2NSYNC)
1517 dev_err(dev->class_dev,
1518 "buggy USB host controller or bug in IRQ handler\n");
1519 usbdux_pwm_stop(devpriv, 0); /* w/o unlink */
1523 static int usbduxsub_submit_PwmURBs(struct usbduxsigma_private *usbduxsub)
1530 /* in case of a resubmission after an unlink... */
1531 usb_fill_bulk_urb(usbduxsub->urbPwm,
1533 usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
1534 usbduxsub->urbPwm->transfer_buffer,
1535 usbduxsub->sizePwmBuf, usbduxsub_pwm_irq,
1536 usbduxsub->comedidev);
1538 errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
1540 dev_err(&usbduxsub->interface->dev,
1541 "comedi_: usbduxsigma: pwm: usb_submit_urb error %d\n",
1548 static int usbdux_pwm_period(struct comedi_device *dev,
1549 struct comedi_subdevice *s, unsigned int period)
1551 struct usbduxsigma_private *this_usbduxsub = dev->private;
1554 if (period < MIN_PWM_PERIOD) {
1555 dev_err(&this_usbduxsub->interface->dev,
1556 "comedi%d: illegal period setting for pwm.\n",
1560 fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6;
1561 if (fx2delay > 255) {
1562 dev_err(&this_usbduxsub->interface->dev,
1563 "comedi%d: period %d for pwm is too low.\n",
1564 dev->minor, period);
1568 this_usbduxsub->pwmDelay = fx2delay;
1569 this_usbduxsub->pwmPeriod = period;
1573 /* is called from insn so there's no need to do all the sanity checks */
1574 static int usbdux_pwm_start(struct comedi_device *dev,
1575 struct comedi_subdevice *s)
1577 struct usbduxsigma_private *this_usbduxsub = dev->private;
1580 if (this_usbduxsub->pwm_cmd_running) {
1581 /* already running */
1585 this_usbduxsub->dux_commands[1] = ((uint8_t) this_usbduxsub->pwmDelay);
1586 ret = send_dux_commands(this_usbduxsub, SENDPWMON);
1590 /* initialise the buffer */
1591 for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
1592 ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
1594 this_usbduxsub->pwm_cmd_running = 1;
1595 ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
1597 this_usbduxsub->pwm_cmd_running = 0;
1603 /* generates the bit pattern for PWM with the optional sign bit */
1604 static int usbdux_pwm_pattern(struct comedi_device *dev,
1605 struct comedi_subdevice *s, int channel,
1606 unsigned int value, unsigned int sign)
1608 struct usbduxsigma_private *this_usbduxsub = dev->private;
1615 if (!this_usbduxsub)
1618 /* this is the DIO bit which carries the PWM data */
1619 pwm_mask = (1 << channel);
1620 /* this is the DIO bit which carries the optional direction bit */
1621 sgn_mask = (16 << channel);
1622 /* this is the buffer which will be filled with the with bit */
1623 /* pattern for one period */
1624 szbuf = this_usbduxsub->sizePwmBuf;
1625 pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
1626 for (i = 0; i < szbuf; i++) {
1629 c = c & (~pwm_mask);
1630 /* set the bit as long as the index is lower than the value */
1633 /* set the optional sign bit for a relay */
1635 /* positive value */
1636 c = c & (~sgn_mask);
1638 /* negative value */
1646 static int usbdux_pwm_write(struct comedi_device *dev,
1647 struct comedi_subdevice *s,
1648 struct comedi_insn *insn, unsigned int *data)
1650 struct usbduxsigma_private *this_usbduxsub = dev->private;
1652 if (!this_usbduxsub)
1655 if ((insn->n) != 1) {
1657 * doesn't make sense to have more than one value here because
1658 * it would just overwrite the PWM buffer a couple of times
1664 * the sign is set via a special INSN only, this gives us 8 bits for
1666 * relay sign 0 by default
1668 return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0);
1671 static int usbdux_pwm_read(struct comedi_device *x1,
1672 struct comedi_subdevice *x2, struct comedi_insn *x3,
1679 /* switches on/off PWM */
1680 static int usbdux_pwm_config(struct comedi_device *dev,
1681 struct comedi_subdevice *s,
1682 struct comedi_insn *insn, unsigned int *data)
1684 struct usbduxsigma_private *this_usbduxsub = dev->private;
1686 case INSN_CONFIG_ARM:
1689 * if not zero the PWM is limited to a certain time which is
1690 * not supported here
1694 return usbdux_pwm_start(dev, s);
1695 case INSN_CONFIG_DISARM:
1696 return usbdux_pwm_cancel(dev, s);
1697 case INSN_CONFIG_GET_PWM_STATUS:
1699 * to check if the USB transmission has failed or in case PWM
1700 * was limited to n cycles to check if it has terminated
1702 data[1] = this_usbduxsub->pwm_cmd_running;
1704 case INSN_CONFIG_PWM_SET_PERIOD:
1705 return usbdux_pwm_period(dev, s, data[1]);
1706 case INSN_CONFIG_PWM_GET_PERIOD:
1707 data[1] = this_usbduxsub->pwmPeriod;
1709 case INSN_CONFIG_PWM_SET_H_BRIDGE:
1710 /* value in the first byte and the sign in the second for a
1712 return usbdux_pwm_pattern(dev, s,
1713 /* the channel number */
1714 CR_CHAN(insn->chanspec),
1715 /* actual PWM data */
1719 case INSN_CONFIG_PWM_GET_H_BRIDGE:
1720 /* values are not kept in this driver, nothing to return */
1727 /*****************************************************************/
1729 static void tidy_up(struct usbduxsigma_private *usbduxsub_tmp)
1736 /* shows the usb subsystem that the driver is down */
1737 if (usbduxsub_tmp->interface)
1738 usb_set_intfdata(usbduxsub_tmp->interface, NULL);
1740 usbduxsub_tmp->probed = 0;
1742 if (usbduxsub_tmp->urbIn) {
1743 /* force unlink all urbs */
1744 usbdux_ai_stop(usbduxsub_tmp, 1);
1745 for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
1746 kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
1747 usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
1748 usb_free_urb(usbduxsub_tmp->urbIn[i]);
1749 usbduxsub_tmp->urbIn[i] = NULL;
1751 kfree(usbduxsub_tmp->urbIn);
1752 usbduxsub_tmp->urbIn = NULL;
1754 if (usbduxsub_tmp->urbOut) {
1755 /* force unlink all urbs */
1756 usbdux_ao_stop(usbduxsub_tmp, 1);
1757 for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
1758 if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
1759 kfree(usbduxsub_tmp->
1760 urbOut[i]->transfer_buffer);
1761 usbduxsub_tmp->urbOut[i]->transfer_buffer =
1764 if (usbduxsub_tmp->urbOut[i]) {
1765 usb_free_urb(usbduxsub_tmp->urbOut[i]);
1766 usbduxsub_tmp->urbOut[i] = NULL;
1769 kfree(usbduxsub_tmp->urbOut);
1770 usbduxsub_tmp->urbOut = NULL;
1772 if (usbduxsub_tmp->urbPwm) {
1773 /* force unlink urb */
1774 usbdux_pwm_stop(usbduxsub_tmp, 1);
1775 kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
1776 usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
1777 usb_free_urb(usbduxsub_tmp->urbPwm);
1778 usbduxsub_tmp->urbPwm = NULL;
1780 kfree(usbduxsub_tmp->inBuffer);
1781 usbduxsub_tmp->inBuffer = NULL;
1782 kfree(usbduxsub_tmp->insnBuffer);
1783 usbduxsub_tmp->insnBuffer = NULL;
1784 kfree(usbduxsub_tmp->outBuffer);
1785 usbduxsub_tmp->outBuffer = NULL;
1786 kfree(usbduxsub_tmp->dac_commands);
1787 usbduxsub_tmp->dac_commands = NULL;
1788 kfree(usbduxsub_tmp->dux_commands);
1789 usbduxsub_tmp->dux_commands = NULL;
1792 static int usbduxsigma_attach_common(struct comedi_device *dev,
1793 struct usbduxsigma_private *uds)
1796 struct comedi_subdevice *s;
1801 /* pointer back to the corresponding comedi device */
1802 uds->comedidev = dev;
1804 /* set number of subdevices */
1805 if (uds->high_speed)
1806 n_subdevs = 4; /* with pwm */
1808 n_subdevs = 3; /* without pwm */
1809 ret = comedi_alloc_subdevices(dev, n_subdevs);
1814 /* private structure is also simply the usb-structure */
1816 /* the first subdevice is the A/D converter */
1817 s = &dev->subdevices[SUBDEV_AD];
1818 /* the URBs get the comedi subdevice */
1819 /* which is responsible for reading */
1820 /* this is the subdevice which reads data */
1821 dev->read_subdev = s;
1822 /* the subdevice receives as private structure the */
1826 s->type = COMEDI_SUBD_AI;
1827 /* readable and ref is to ground, 32 bit wide data! */
1828 s->subdev_flags = SDF_READABLE | SDF_GROUND |
1829 SDF_CMD_READ | SDF_LSAMPL;
1830 /* 16 A/D channels */
1831 s->n_chan = NUMCHANNELS;
1832 /* length of the channellist */
1833 s->len_chanlist = NUMCHANNELS;
1834 /* callback functions */
1835 s->insn_read = usbdux_ai_insn_read;
1836 s->do_cmdtest = usbdux_ai_cmdtest;
1837 s->do_cmd = usbdux_ai_cmd;
1838 s->cancel = usbdux_ai_cancel;
1839 /* max value from the A/D converter (24bit) */
1840 s->maxdata = 0x00FFFFFF;
1841 /* range table to convert to physical units */
1842 s->range_table = (&range_usbdux_ai_range);
1843 /* analog output subdevice */
1844 s = &dev->subdevices[SUBDEV_DA];
1846 s->type = COMEDI_SUBD_AO;
1847 /* backward pointer */
1848 dev->write_subdev = s;
1849 /* the subdevice receives as private structure the */
1853 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1856 /* length of the channellist */
1857 s->len_chanlist = 4;
1858 /* 8 bit resolution */
1859 s->maxdata = 0x00ff;
1860 /* unipolar range */
1861 s->range_table = &range_unipolar2_5;
1863 s->do_cmdtest = usbdux_ao_cmdtest;
1864 s->do_cmd = usbdux_ao_cmd;
1865 s->cancel = usbdux_ao_cancel;
1866 s->insn_read = usbdux_ao_insn_read;
1867 s->insn_write = usbdux_ao_insn_write;
1868 /* digital I/O subdevice */
1869 s = &dev->subdevices[SUBDEV_DIO];
1870 s->type = COMEDI_SUBD_DIO;
1871 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1872 /* 8 external and 16 internal channels */
1875 s->range_table = (&range_digital);
1876 s->insn_bits = usbdux_dio_insn_bits;
1877 s->insn_config = usbdux_dio_insn_config;
1878 /* we don't use it */
1880 if (uds->high_speed) {
1881 /* timer / pwm subdevice */
1882 s = &dev->subdevices[SUBDEV_PWM];
1883 s->type = COMEDI_SUBD_PWM;
1884 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
1886 /* this defines the max duty cycle resolution */
1887 s->maxdata = uds->sizePwmBuf;
1888 s->insn_write = usbdux_pwm_write;
1889 s->insn_read = usbdux_pwm_read;
1890 s->insn_config = usbdux_pwm_config;
1891 usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1893 /* finally decide that it's attached */
1896 offset = usbdux_getstatusinfo(dev, 0);
1898 dev_err(&uds->interface->dev,
1899 "Communication to USBDUXSIGMA failed! Check firmware and cabling.");
1900 dev_info(&uds->interface->dev,
1901 "comedi%d: attached, ADC_zero = %x\n", dev->minor, offset);
1905 static int usbduxsigma_alloc_usb_buffers(struct usbduxsigma_private *devpriv)
1907 struct usb_device *usb = devpriv->usbdev;
1911 devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
1912 devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
1913 devpriv->inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1914 devpriv->insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1915 devpriv->outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1916 devpriv->urbIn = kcalloc(devpriv->numOfInBuffers, sizeof(*urb),
1918 devpriv->urbOut = kcalloc(devpriv->numOfOutBuffers, sizeof(*urb),
1920 if (!devpriv->dac_commands || !devpriv->dux_commands ||
1921 !devpriv->inBuffer || !devpriv->insnBuffer ||
1922 !devpriv->outBuffer || !devpriv->urbIn || !devpriv->urbOut)
1925 for (i = 0; i < devpriv->numOfInBuffers; i++) {
1926 /* one frame: 1ms */
1927 urb = usb_alloc_urb(1, GFP_KERNEL);
1930 devpriv->urbIn[i] = urb;
1932 /* will be filled later with a pointer to the comedi-device */
1933 /* and ONLY then the urb should be submitted */
1934 urb->context = NULL;
1935 urb->pipe = usb_rcvisocpipe(usb, ISOINEP);
1936 urb->transfer_flags = URB_ISO_ASAP;
1937 urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1938 if (!urb->transfer_buffer)
1940 urb->complete = usbduxsub_ai_IsocIrq;
1941 urb->number_of_packets = 1;
1942 urb->transfer_buffer_length = SIZEINBUF;
1943 urb->iso_frame_desc[0].offset = 0;
1944 urb->iso_frame_desc[0].length = SIZEINBUF;
1947 for (i = 0; i < devpriv->numOfOutBuffers; i++) {
1948 /* one frame: 1ms */
1949 urb = usb_alloc_urb(1, GFP_KERNEL);
1952 devpriv->urbOut[i] = urb;
1954 /* will be filled later with a pointer to the comedi-device */
1955 /* and ONLY then the urb should be submitted */
1956 urb->context = NULL;
1957 urb->pipe = usb_sndisocpipe(usb, ISOOUTEP);
1958 urb->transfer_flags = URB_ISO_ASAP;
1959 urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1960 if (!urb->transfer_buffer)
1962 urb->complete = usbduxsub_ao_IsocIrq;
1963 urb->number_of_packets = 1;
1964 urb->transfer_buffer_length = SIZEOUTBUF;
1965 urb->iso_frame_desc[0].offset = 0;
1966 urb->iso_frame_desc[0].length = SIZEOUTBUF;
1967 if (devpriv->high_speed)
1968 urb->interval = 8; /* uframes */
1970 urb->interval = 1; /* frames */
1973 if (devpriv->high_speed) {
1974 /* max bulk ep size in high speed */
1975 devpriv->sizePwmBuf = 512;
1976 urb = usb_alloc_urb(0, GFP_KERNEL);
1979 devpriv->urbPwm = urb;
1980 urb->transfer_buffer = kzalloc(devpriv->sizePwmBuf, GFP_KERNEL);
1981 if (!urb->transfer_buffer)
1984 devpriv->urbPwm = NULL;
1985 devpriv->sizePwmBuf = 0;
1991 static int usbduxsigma_auto_attach(struct comedi_device *dev,
1992 unsigned long context_unused)
1994 struct usb_interface *uinterf = comedi_to_usb_interface(dev);
1995 struct usbduxsigma_private *uds = usb_get_intfdata(uinterf);
1996 struct usb_device *usb = uds->usbdev;
1999 dev->private = uds; /* This is temporary... */
2000 ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
2001 usbduxsigma_firmware_upload, 0);
2003 dev->private = NULL;
2007 dev->private = NULL;
2009 down(&start_stop_sem);
2011 dev_err(dev->class_dev,
2012 "usbduxsigma: error: auto_attach failed, not connected\n");
2014 } else if (uds->attached) {
2015 dev_err(dev->class_dev,
2016 "usbduxsigma: error: auto_attach failed, already attached\n");
2019 ret = usbduxsigma_attach_common(dev, uds);
2020 up(&start_stop_sem);
2024 static void usbduxsigma_detach(struct comedi_device *dev)
2026 struct usbduxsigma_private *devpriv = dev->private;
2031 /* stop any running commands */
2032 usbdux_ai_stop(devpriv, devpriv->ai_cmd_running);
2033 usbdux_ao_stop(devpriv, devpriv->ao_cmd_running);
2035 down(&start_stop_sem);
2036 down(&devpriv->sem);
2037 dev->private = NULL;
2038 devpriv->attached = 0;
2039 devpriv->comedidev = NULL;
2042 up(&start_stop_sem);
2045 static struct comedi_driver usbduxsigma_driver = {
2046 .driver_name = "usbduxsigma",
2047 .module = THIS_MODULE,
2048 .auto_attach = usbduxsigma_auto_attach,
2049 .detach = usbduxsigma_detach,
2052 static int usbduxsigma_usb_probe(struct usb_interface *intf,
2053 const struct usb_device_id *id)
2055 struct usb_device *usb = interface_to_usbdev(intf);
2056 struct device *dev = &intf->dev;
2057 struct usbduxsigma_private *devpriv = NULL;
2061 down(&start_stop_sem);
2062 for (i = 0; i < NUMUSBDUX; i++) {
2063 if (!usbduxsub[i].probed) {
2064 devpriv = &usbduxsub[i];
2070 dev_err(dev, "Too many usbduxsigma-devices connected.\n");
2071 up(&start_stop_sem);
2075 sema_init(&devpriv->sem, 1);
2076 devpriv->usbdev = usb;
2077 devpriv->interface = intf;
2078 devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber;
2079 usb_set_intfdata(intf, devpriv);
2081 ret = usb_set_interface(usb, devpriv->ifnum, 3);
2084 "could not set alternate setting 3 in high speed\n");
2086 up(&start_stop_sem);
2090 /* test if it is high speed (USB 2.0) */
2091 devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
2092 if (devpriv->high_speed) {
2093 devpriv->numOfInBuffers = NUMOFINBUFFERSHIGH;
2094 devpriv->numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
2096 devpriv->numOfInBuffers = NUMOFINBUFFERSFULL;
2097 devpriv->numOfOutBuffers = NUMOFOUTBUFFERSFULL;
2100 ret = usbduxsigma_alloc_usb_buffers(devpriv);
2103 up(&start_stop_sem);
2107 devpriv->ai_cmd_running = 0;
2108 devpriv->ao_cmd_running = 0;
2109 devpriv->pwm_cmd_running = 0;
2111 /* we've reached the bottom of the function */
2112 devpriv->probed = 1;
2113 up(&start_stop_sem);
2115 return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);;
2118 static const struct usb_device_id usbduxsigma_usb_table[] = {
2119 { USB_DEVICE(0x13d8, 0x0020) },
2120 { USB_DEVICE(0x13d8, 0x0021) },
2121 { USB_DEVICE(0x13d8, 0x0022) },
2124 MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
2126 static struct usb_driver usbduxsigma_usb_driver = {
2127 .name = "usbduxsigma",
2128 .probe = usbduxsigma_usb_probe,
2129 .disconnect = comedi_usb_auto_unconfig,
2130 .id_table = usbduxsigma_usb_table,
2132 module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
2134 MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
2135 MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
2136 MODULE_LICENSE("GPL");
2137 MODULE_FIRMWARE(FIRMWARE);