2 comedi/drivers/usbdux.c
3 Copyright (C) 2003-2007 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 (usbdux.o)
19 Author: Bernd Porr <BerndPorr@f2s.com>
22 Configuration options:
23 You have to upload firmware with the -i option. The
24 firmware is usually installed under /usr/share/usb or
25 /usr/local/share/usb or /lib/firmware.
27 Connection scheme for the counter at the digital port:
28 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
29 The sampling rate of the counter is approximately 500Hz.
31 Please note that under USB2.0 the length of the channel list determines
32 the max sampling rate. If you sample only one channel you get 8kHz
33 sampling rate. If you sample two channels you get 4kHz and so on.
36 * I must give credit here to Chris Baugher who
37 * wrote the driver for AT-MIO-16d. I used some parts of this
38 * driver. I also must give credits to David Brownell
39 * who supported me with the USB development.
45 * 0.94: D/A output should work now with any channel list combinations
46 * 0.95: .owner commented out for kernel vers below 2.4.19
47 * sanity checks in ai/ao_cmd
48 * 0.96: trying to get it working with 2.6, moved all memory alloc to comedi's
49 * attach final USB IDs
50 * moved memory allocation completely to the corresponding comedi
51 * functions firmware upload is by fxload and no longer by comedi (due to
53 * 0.97: USB IDs received, adjusted table
54 * 0.98: SMP, locking, memory alloc: moved all usb memory alloc
55 * to the usb subsystem and moved all comedi related memory
57 * | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
58 * 0.99: USB 2.0: changed protocol to isochronous transfer
59 * IRQ transfer is too buggy and too risky in 2.0
60 * for the high speed ISO transfer is now a working version
62 * 0.99b: Increased the iso transfer buffer for high sp.to 10 buffers. Some VIA
63 * chipsets miss out IRQs. Deeper buffering is needed.
64 * 1.00: full USB 2.0 support for the A/D converter. Now: max 8kHz sampling
66 * Firmware vers 1.00 is needed for this.
67 * Two 16 bit up/down/reset counter with a sampling rate of 1kHz
68 * And loads of cleaning up, in particular streamlining the
70 * 1.1: moved EP4 transfers to EP1 to make space for a PWM output on EP4
71 * 1.2: added PWM support via EP4
72 * 2.0: PWM seems to be stable and is not interfering with the other functions
73 * 2.1: changed PWM API
74 * 2.2: added firmware kernel request to fix an udev problem
75 * 2.3: corrected a bug in bulk timeouts which were far too short
76 * 2.4: fixed a bug which causes the driver to hang when it ran out of data.
77 * Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
81 #include <linux/kernel.h>
82 #include <linux/module.h>
83 #include <linux/slab.h>
84 #include <linux/input.h>
85 #include <linux/usb.h>
86 #include <linux/fcntl.h>
87 #include <linux/compiler.h>
89 #include "../comedidev.h"
91 #include "comedi_fc.h"
93 /* constants for firmware upload and download */
94 #define USBDUX_FIRMWARE "usbdux_firmware.bin"
95 #define USBDUX_FIRMWARE_MAX_LEN 0x2000
96 #define USBDUX_FIRMWARE_CMD 0xa0
97 #define VENDOR_DIR_IN 0xc0
98 #define VENDOR_DIR_OUT 0x40
99 #define USBDUX_CPU_CS 0xe600
101 /* usbdux bulk transfer commands */
102 #define USBDUX_CMD_MULT_AI 0
103 #define USBDUX_CMD_AO 1
104 #define USBDUX_CMD_DIO_CFG 2
105 #define USBDUX_CMD_DIO_BITS 3
106 #define USBDUX_CMD_SINGLE_AI 4
107 #define USBDUX_CMD_TIMER_RD 5
108 #define USBDUX_CMD_TIMER_WR 6
109 #define USBDUX_CMD_PWM_ON 7
110 #define USBDUX_CMD_PWM_OFF 8
112 #define USBDUX_NUM_AO_CHAN 4
114 /* timeout for the USB-transfer in ms */
115 #define BULK_TIMEOUT 1000
117 /* 300Hz max frequ under PWM */
118 #define MIN_PWM_PERIOD ((long)(1E9/300))
120 /* Default PWM frequency */
121 #define PWM_DEFAULT_PERIOD ((long)(1E9/100))
123 /* Size of one A/D value */
124 #define SIZEADIN ((sizeof(uint16_t)))
127 * Size of the input-buffer IN BYTES
128 * Always multiple of 8 for 8 microframes which is needed in the highspeed mode
130 #define SIZEINBUF ((8*SIZEADIN))
133 #define SIZEINSNBUF 16
135 /* size of one value for the D/A converter: channel and value */
136 #define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t)))
139 * Size of the output-buffer in bytes
140 * Actually only the first 4 triplets are used but for the
141 * high speed mode we need to pad it to 8 (microframes).
143 #define SIZEOUTBUF ((8*SIZEDAOUT))
146 * Size of the buffer for the dux commands: just now max size is determined
147 * by the analogue out + command byte + panic bytes...
149 #define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2))
151 /* Number of in-URBs which receive the data: min=2 */
152 #define NUMOFINBUFFERSFULL 5
154 /* Number of out-URBs which send the data: min=2 */
155 #define NUMOFOUTBUFFERSFULL 5
157 /* Number of in-URBs which receive the data: min=5 */
158 /* must have more buffers due to buggy USB ctr */
159 #define NUMOFINBUFFERSHIGH 10
161 /* Number of out-URBs which send the data: min=5 */
162 /* must have more buffers due to buggy USB ctr */
163 #define NUMOFOUTBUFFERSHIGH 10
165 /* number of retries to get the right dux command */
168 static const struct comedi_lrange range_usbdux_ai_range = {
171 BIP_RANGE(4.096 / 2),
177 static const struct comedi_lrange range_usbdux_ao_range = {
184 struct usbdux_private {
185 /* actual number of in-buffers */
187 /* actual number of out-buffers */
189 /* ISO-transfer handling: buffers */
190 struct urb **ai_urbs;
191 struct urb **ao_urbs;
192 /* pwm-transfer handling */
195 unsigned int pwm_period;
196 /* PWM internal delay for the GPIF in the FX2 */
198 /* size of the PWM buffer which holds the bit pattern */
200 /* input buffer for the ISO-transfer */
202 /* input buffer for single insn */
205 unsigned int ao_readback[USBDUX_NUM_AO_CHAN];
207 unsigned int high_speed:1;
208 unsigned int ai_cmd_running:1;
209 unsigned int ao_cmd_running:1;
210 unsigned int pwm_cmd_running:1;
212 /* number of samples to acquire */
215 /* time between samples in units of the timer */
216 unsigned int ai_timer;
217 unsigned int ao_timer;
218 /* counter between aquisitions */
219 unsigned int ai_counter;
220 unsigned int ao_counter;
221 /* interval in frames/uframes */
222 unsigned int ai_interval;
224 uint8_t *dux_commands;
225 struct semaphore sem;
228 static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs)
232 for (i = 0; i < num_urbs; i++)
233 usb_kill_urb(urbs[i]);
236 static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink)
238 struct usbdux_private *devpriv = dev->private;
240 if (do_unlink && devpriv->ai_urbs)
241 usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
243 devpriv->ai_cmd_running = 0;
246 static int usbdux_ai_cancel(struct comedi_device *dev,
247 struct comedi_subdevice *s)
249 struct usbdux_private *devpriv = dev->private;
251 /* prevent other CPUs from submitting new commands just now */
253 /* unlink only if the urb really has been submitted */
254 usbdux_ai_stop(dev, devpriv->ai_cmd_running);
260 /* analogue IN - interrupt service routine */
261 static void usbduxsub_ai_isoc_irq(struct urb *urb)
263 struct comedi_device *dev = urb->context;
264 struct comedi_subdevice *s = dev->read_subdev;
265 struct usbdux_private *devpriv = dev->private;
266 struct comedi_cmd *cmd = &s->async->cmd;
269 /* first we test if something unusual has just happened */
270 switch (urb->status) {
272 /* copy the result in the transfer buffer */
273 memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
276 /* error in the ISOchronous data */
277 /* we don't copy the data into the transfer buffer */
278 /* and recycle the last data byte */
279 dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
286 /* happens after an unlink command */
287 if (devpriv->ai_cmd_running) {
288 s->async->events |= COMEDI_CB_EOA;
289 s->async->events |= COMEDI_CB_ERROR;
290 comedi_event(dev, s);
291 /* stop the transfer w/o unlink */
292 usbdux_ai_stop(dev, 0);
297 /* a real error on the bus */
298 /* pass error to comedi if we are really running a command */
299 if (devpriv->ai_cmd_running) {
300 dev_err(dev->class_dev,
301 "Non-zero urb status received in ai intr context: %d\n",
303 s->async->events |= COMEDI_CB_EOA;
304 s->async->events |= COMEDI_CB_ERROR;
305 comedi_event(dev, s);
306 /* don't do an unlink here */
307 usbdux_ai_stop(dev, 0);
313 * at this point we are reasonably sure that nothing dodgy has happened
314 * are we running a command?
316 if (unlikely(!devpriv->ai_cmd_running)) {
318 * not running a command, do not continue execution if no
319 * asynchronous command is running in particular not resubmit
324 urb->dev = comedi_to_usb_dev(dev);
326 /* resubmit the urb */
327 err = usb_submit_urb(urb, GFP_ATOMIC);
328 if (unlikely(err < 0)) {
329 dev_err(dev->class_dev,
330 "urb resubmit failed in int-context! err=%d\n", err);
331 if (err == -EL2NSYNC)
332 dev_err(dev->class_dev,
333 "buggy USB host controller or bug in IRQ handler!\n");
334 s->async->events |= COMEDI_CB_EOA;
335 s->async->events |= COMEDI_CB_ERROR;
336 comedi_event(dev, s);
337 /* don't do an unlink here */
338 usbdux_ai_stop(dev, 0);
342 devpriv->ai_counter--;
343 if (likely(devpriv->ai_counter > 0))
346 /* timer zero, transfer measurements to comedi */
347 devpriv->ai_counter = devpriv->ai_timer;
349 /* test, if we transmit only a fixed number of samples */
350 if (cmd->stop_src == TRIG_COUNT) {
351 /* not continuous, fixed number of samples */
352 devpriv->ai_sample_count--;
353 /* all samples received? */
354 if (devpriv->ai_sample_count < 0) {
355 /* prevent a resubmit next time */
356 usbdux_ai_stop(dev, 0);
357 /* say comedi that the acquistion is over */
358 s->async->events |= COMEDI_CB_EOA;
359 comedi_event(dev, s);
363 /* get the data from the USB bus and hand it over to comedi */
364 for (i = 0; i < cmd->chanlist_len; i++) {
365 unsigned int range = CR_RANGE(cmd->chanlist[i]);
366 uint16_t val = le16_to_cpu(devpriv->in_buf[i]);
368 /* bipolar data is two's-complement */
369 if (comedi_range_is_bipolar(s, range))
370 val ^= ((s->maxdata + 1) >> 1);
373 err = comedi_buf_put(s, val);
374 if (unlikely(err == 0)) {
375 /* buffer overflow */
376 usbdux_ai_stop(dev, 0);
380 /* tell comedi that data is there */
381 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
382 comedi_event(dev, s);
385 static void usbdux_ao_stop(struct comedi_device *dev, int do_unlink)
387 struct usbdux_private *devpriv = dev->private;
389 if (do_unlink && devpriv->ao_urbs)
390 usbdux_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
392 devpriv->ao_cmd_running = 0;
395 static int usbdux_ao_cancel(struct comedi_device *dev,
396 struct comedi_subdevice *s)
398 struct usbdux_private *devpriv = dev->private;
400 /* prevent other CPUs from submitting a command just now */
402 /* unlink only if it is really running */
403 usbdux_ao_stop(dev, devpriv->ao_cmd_running);
409 static void usbduxsub_ao_isoc_irq(struct urb *urb)
411 struct comedi_device *dev = urb->context;
412 struct comedi_subdevice *s = dev->write_subdev;
413 struct usbdux_private *devpriv = dev->private;
414 struct comedi_cmd *cmd = &s->async->cmd;
419 switch (urb->status) {
428 /* after an unlink command, unplug, ... etc */
429 /* no unlink needed here. Already shutting down. */
430 if (devpriv->ao_cmd_running) {
431 s->async->events |= COMEDI_CB_EOA;
432 comedi_event(dev, s);
433 usbdux_ao_stop(dev, 0);
439 if (devpriv->ao_cmd_running) {
440 dev_err(dev->class_dev,
441 "Non-zero urb status received in ao intr context: %d\n",
443 s->async->events |= COMEDI_CB_ERROR;
444 s->async->events |= COMEDI_CB_EOA;
445 comedi_event(dev, s);
446 /* we do an unlink if we are in the high speed mode */
447 usbdux_ao_stop(dev, 0);
452 /* are we actually running? */
453 if (!devpriv->ao_cmd_running)
456 /* normal operation: executing a command in this subdevice */
457 devpriv->ao_counter--;
458 if ((int)devpriv->ao_counter <= 0) {
460 devpriv->ao_counter = devpriv->ao_timer;
462 /* handle non continous acquisition */
463 if (cmd->stop_src == TRIG_COUNT) {
464 /* fixed number of samples */
465 devpriv->ao_sample_count--;
466 if (devpriv->ao_sample_count < 0) {
467 /* all samples transmitted */
468 usbdux_ao_stop(dev, 0);
469 s->async->events |= COMEDI_CB_EOA;
470 comedi_event(dev, s);
471 /* no resubmit of the urb */
476 /* transmit data to the USB bus */
477 datap = urb->transfer_buffer;
478 *datap++ = cmd->chanlist_len;
479 for (i = 0; i < cmd->chanlist_len; i++) {
480 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
483 ret = comedi_buf_get(s, &val);
485 dev_err(dev->class_dev, "buffer underflow\n");
486 s->async->events |= (COMEDI_CB_EOA |
489 /* pointer to the DA */
490 *datap++ = val & 0xff;
491 *datap++ = (val >> 8) & 0xff;
492 *datap++ = chan << 6;
493 devpriv->ao_readback[chan] = val;
495 s->async->events |= COMEDI_CB_BLOCK;
496 comedi_event(dev, s);
499 urb->transfer_buffer_length = SIZEOUTBUF;
500 urb->dev = comedi_to_usb_dev(dev);
502 if (devpriv->ao_cmd_running) {
503 if (devpriv->high_speed)
504 urb->interval = 8; /* uframes */
506 urb->interval = 1; /* frames */
507 urb->number_of_packets = 1;
508 urb->iso_frame_desc[0].offset = 0;
509 urb->iso_frame_desc[0].length = SIZEOUTBUF;
510 urb->iso_frame_desc[0].status = 0;
511 ret = usb_submit_urb(urb, GFP_ATOMIC);
513 dev_err(dev->class_dev,
514 "ao urb resubm failed in int-cont. ret=%d",
517 dev_err(dev->class_dev,
518 "buggy USB host controller or bug in IRQ handling!\n");
520 s->async->events |= COMEDI_CB_EOA;
521 s->async->events |= COMEDI_CB_ERROR;
522 comedi_event(dev, s);
523 /* don't do an unlink here */
524 usbdux_ao_stop(dev, 0);
529 static int usbdux_submit_urbs(struct comedi_device *dev,
530 struct urb **urbs, int num_urbs,
533 struct usb_device *usb = comedi_to_usb_dev(dev);
534 struct usbdux_private *devpriv = dev->private;
539 /* Submit all URBs and start the transfer on the bus */
540 for (i = 0; i < num_urbs; i++) {
543 /* in case of a resubmission after an unlink... */
545 urb->interval = devpriv->ai_interval;
549 urb->transfer_flags = URB_ISO_ASAP;
551 ret = usb_submit_urb(urb, GFP_ATOMIC);
558 static int usbdux_ai_cmdtest(struct comedi_device *dev,
559 struct comedi_subdevice *s, struct comedi_cmd *cmd)
561 struct usbdux_private *this_usbduxsub = dev->private;
563 unsigned int tmp_timer;
565 /* Step 1 : check if triggers are trivially valid */
567 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
568 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
569 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
570 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
571 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
576 /* Step 2a : make sure trigger sources are unique */
578 err |= cfc_check_trigger_is_unique(cmd->start_src);
579 err |= cfc_check_trigger_is_unique(cmd->stop_src);
581 /* Step 2b : and mutually compatible */
586 /* Step 3: check if arguments are trivially valid */
588 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
590 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
591 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
593 if (cmd->scan_begin_src == TRIG_TIMER) {
594 if (this_usbduxsub->high_speed) {
596 * In high speed mode microframes are possible.
597 * However, during one microframe we can roughly
598 * sample one channel. Thus, the more channels
599 * are in the channel list the more time we need.
602 /* find a power of 2 for the number of channels */
603 while (i < (cmd->chanlist_len))
606 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
608 /* now calc the real sampling rate with all the
611 ((unsigned int)(cmd->scan_begin_arg / 125000)) *
615 /* 1kHz scans every USB frame */
616 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
619 * calc the real sampling rate with the rounding errors
621 tmp_timer = ((unsigned int)(cmd->scan_begin_arg /
624 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg,
628 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
630 if (cmd->stop_src == TRIG_COUNT) {
631 /* any count is allowed */
634 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
644 * creates the ADC command for the MAX1271
645 * range is the range value from comedi
647 static uint8_t create_adc_command(unsigned int chan, unsigned int range)
649 uint8_t p = (range <= 1);
650 uint8_t r = ((range % 2) == 0);
652 return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
655 static int send_dux_commands(struct comedi_device *dev, unsigned int cmd_type)
657 struct usb_device *usb = comedi_to_usb_dev(dev);
658 struct usbdux_private *devpriv = dev->private;
661 devpriv->dux_commands[0] = cmd_type;
663 return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
664 devpriv->dux_commands, SIZEOFDUXBUFFER,
665 &nsent, BULK_TIMEOUT);
668 static int receive_dux_commands(struct comedi_device *dev, unsigned int command)
670 struct usb_device *usb = comedi_to_usb_dev(dev);
671 struct usbdux_private *devpriv = dev->private;
676 for (i = 0; i < RETRIES; i++) {
677 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
678 devpriv->insn_buf, SIZEINSNBUF,
679 &nrec, BULK_TIMEOUT);
682 if (le16_to_cpu(devpriv->insn_buf[0]) == command)
685 /* command not received */
689 static int usbdux_ai_inttrig(struct comedi_device *dev,
690 struct comedi_subdevice *s,
691 unsigned int trig_num)
693 struct usbdux_private *devpriv = dev->private;
694 struct comedi_cmd *cmd = &s->async->cmd;
697 if (trig_num != cmd->start_arg)
702 if (!devpriv->ai_cmd_running) {
703 devpriv->ai_cmd_running = 1;
704 ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
705 devpriv->n_ai_urbs, 1);
707 devpriv->ai_cmd_running = 0;
710 s->async->inttrig = NULL;
720 static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
722 struct usbdux_private *devpriv = dev->private;
723 struct comedi_cmd *cmd = &s->async->cmd;
724 int len = cmd->chanlist_len;
728 /* block other CPUs from starting an ai_cmd */
731 if (devpriv->ai_cmd_running)
734 /* set current channel of the running acquisition to zero */
735 s->async->cur_chan = 0;
737 devpriv->dux_commands[1] = len;
738 for (i = 0; i < len; ++i) {
739 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
740 unsigned int range = CR_RANGE(cmd->chanlist[i]);
742 devpriv->dux_commands[i + 2] = create_adc_command(chan, range);
745 ret = send_dux_commands(dev, USBDUX_CMD_MULT_AI);
749 if (devpriv->high_speed) {
751 * every channel gets a time window of 125us. Thus, if we
752 * sample all 8 channels we need 1ms. If we sample only one
753 * channel we need only 125us
755 devpriv->ai_interval = 1;
756 /* find a power of 2 for the interval */
757 while (devpriv->ai_interval < len)
758 devpriv->ai_interval *= 2;
760 devpriv->ai_timer = cmd->scan_begin_arg /
761 (125000 * devpriv->ai_interval);
763 /* interval always 1ms */
764 devpriv->ai_interval = 1;
765 devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
767 if (devpriv->ai_timer < 1) {
772 devpriv->ai_counter = devpriv->ai_timer;
774 if (cmd->stop_src == TRIG_COUNT) {
775 /* data arrives as one packet */
776 devpriv->ai_sample_count = cmd->stop_arg;
778 /* continous acquisition */
779 devpriv->ai_sample_count = 0;
782 if (cmd->start_src == TRIG_NOW) {
783 /* enable this acquisition operation */
784 devpriv->ai_cmd_running = 1;
785 ret = usbdux_submit_urbs(dev, devpriv->ai_urbs,
786 devpriv->n_ai_urbs, 1);
788 devpriv->ai_cmd_running = 0;
789 /* fixme: unlink here?? */
792 s->async->inttrig = NULL;
795 /* don't enable the acquision operation */
796 /* wait for an internal signal */
797 s->async->inttrig = usbdux_ai_inttrig;
806 /* Mode 0 is used to get a single conversion on demand */
807 static int usbdux_ai_insn_read(struct comedi_device *dev,
808 struct comedi_subdevice *s,
809 struct comedi_insn *insn,
812 struct usbdux_private *devpriv = dev->private;
813 unsigned int chan = CR_CHAN(insn->chanspec);
814 unsigned int range = CR_RANGE(insn->chanspec);
821 if (devpriv->ai_cmd_running)
824 /* set command for the first channel */
825 devpriv->dux_commands[1] = create_adc_command(chan, range);
828 ret = send_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
832 for (i = 0; i < insn->n; i++) {
833 ret = receive_dux_commands(dev, USBDUX_CMD_SINGLE_AI);
837 val = le16_to_cpu(devpriv->insn_buf[1]);
839 /* bipolar data is two's-complement */
840 if (comedi_range_is_bipolar(s, range))
841 val ^= ((s->maxdata + 1) >> 1);
849 return ret ? ret : insn->n;
852 static int usbdux_ao_insn_read(struct comedi_device *dev,
853 struct comedi_subdevice *s,
854 struct comedi_insn *insn,
857 struct usbdux_private *devpriv = dev->private;
858 unsigned int chan = CR_CHAN(insn->chanspec);
862 for (i = 0; i < insn->n; i++)
863 data[i] = devpriv->ao_readback[chan];
869 static int usbdux_ao_insn_write(struct comedi_device *dev,
870 struct comedi_subdevice *s,
871 struct comedi_insn *insn,
874 struct usbdux_private *devpriv = dev->private;
875 unsigned int chan = CR_CHAN(insn->chanspec);
876 unsigned int val = devpriv->ao_readback[chan];
877 uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
883 if (devpriv->ao_cmd_running)
886 /* number of channels: 1 */
887 devpriv->dux_commands[1] = 1;
889 devpriv->dux_commands[4] = chan << 6;
891 for (i = 0; i < insn->n; i++) {
894 /* one 16 bit value */
895 *p = cpu_to_le16(val);
897 ret = send_dux_commands(dev, USBDUX_CMD_AO);
901 devpriv->ao_readback[chan] = val;
906 return ret ? ret : insn->n;
909 static int usbdux_ao_inttrig(struct comedi_device *dev,
910 struct comedi_subdevice *s,
911 unsigned int trig_num)
913 struct usbdux_private *devpriv = dev->private;
914 struct comedi_cmd *cmd = &s->async->cmd;
917 if (trig_num != cmd->start_arg)
922 if (!devpriv->ao_cmd_running) {
923 devpriv->ao_cmd_running = 1;
924 ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
925 devpriv->n_ao_urbs, 0);
927 devpriv->ao_cmd_running = 0;
930 s->async->inttrig = NULL;
940 static int usbdux_ao_cmdtest(struct comedi_device *dev,
941 struct comedi_subdevice *s, struct comedi_cmd *cmd)
943 struct usbdux_private *this_usbduxsub = dev->private;
950 /* Step 1 : check if triggers are trivially valid */
952 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
954 if (0) { /* (this_usbduxsub->high_speed) */
955 /* the sampling rate is set by the coversion rate */
958 /* start a new scan (output at once) with a timer */
961 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
963 if (0) { /* (this_usbduxsub->high_speed) */
965 * in usb-2.0 only one conversion it transmitted
971 * all conversion events happen simultaneously with
976 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
978 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
979 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
984 /* Step 2a : make sure trigger sources are unique */
986 err |= cfc_check_trigger_is_unique(cmd->start_src);
987 err |= cfc_check_trigger_is_unique(cmd->stop_src);
989 /* Step 2b : and mutually compatible */
994 /* Step 3: check if arguments are trivially valid */
996 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
998 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
999 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1001 if (cmd->scan_begin_src == TRIG_TIMER)
1002 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1005 /* not used now, is for later use */
1006 if (cmd->convert_src == TRIG_TIMER)
1007 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
1009 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1011 if (cmd->stop_src == TRIG_COUNT) {
1012 /* any count is allowed */
1015 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1024 static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1026 struct usbdux_private *devpriv = dev->private;
1027 struct comedi_cmd *cmd = &s->async->cmd;
1030 down(&devpriv->sem);
1032 if (devpriv->ao_cmd_running)
1035 /* set current channel of the running acquisition to zero */
1036 s->async->cur_chan = 0;
1038 /* we count in steps of 1ms (125us) */
1039 /* 125us mode not used yet */
1040 if (0) { /* (devpriv->high_speed) */
1042 /* timing of the conversion itself: every 125 us */
1043 devpriv->ao_timer = cmd->convert_arg / 125000;
1046 /* timing of the scan: we get all channels at once */
1047 devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
1048 if (devpriv->ao_timer < 1) {
1054 devpriv->ao_counter = devpriv->ao_timer;
1056 if (cmd->stop_src == TRIG_COUNT) {
1057 /* not continuous */
1059 /* high speed also scans everything at once */
1060 if (0) { /* (devpriv->high_speed) */
1061 devpriv->ao_sample_count = cmd->stop_arg *
1064 /* there's no scan as the scan has been */
1065 /* perf inside the FX2 */
1066 /* data arrives as one packet */
1067 devpriv->ao_sample_count = cmd->stop_arg;
1070 /* continous acquisition */
1071 devpriv->ao_sample_count = 0;
1074 if (cmd->start_src == TRIG_NOW) {
1075 /* enable this acquisition operation */
1076 devpriv->ao_cmd_running = 1;
1077 ret = usbdux_submit_urbs(dev, devpriv->ao_urbs,
1078 devpriv->n_ao_urbs, 0);
1080 devpriv->ao_cmd_running = 0;
1081 /* fixme: unlink here?? */
1084 s->async->inttrig = NULL;
1087 /* submit the urbs later */
1088 /* wait for an internal signal */
1089 s->async->inttrig = usbdux_ao_inttrig;
1098 static int usbdux_dio_insn_config(struct comedi_device *dev,
1099 struct comedi_subdevice *s,
1100 struct comedi_insn *insn,
1105 ret = comedi_dio_insn_config(dev, s, insn, data, 0);
1110 * We don't tell the firmware here as it would take 8 frames
1111 * to submit the information. We do it in the insn_bits.
1116 static int usbdux_dio_insn_bits(struct comedi_device *dev,
1117 struct comedi_subdevice *s,
1118 struct comedi_insn *insn,
1122 struct usbdux_private *devpriv = dev->private;
1125 down(&devpriv->sem);
1127 comedi_dio_update_state(s, data);
1129 /* Always update the hardware. See the (*insn_config). */
1130 devpriv->dux_commands[1] = s->io_bits;
1131 devpriv->dux_commands[2] = s->state;
1134 * This command also tells the firmware to return
1135 * the digital input lines.
1137 ret = send_dux_commands(dev, USBDUX_CMD_DIO_BITS);
1140 ret = receive_dux_commands(dev, USBDUX_CMD_DIO_BITS);
1144 data[1] = le16_to_cpu(devpriv->insn_buf[1]);
1149 return ret ? ret : insn->n;
1152 static int usbdux_counter_read(struct comedi_device *dev,
1153 struct comedi_subdevice *s,
1154 struct comedi_insn *insn,
1157 struct usbdux_private *devpriv = dev->private;
1158 unsigned int chan = CR_CHAN(insn->chanspec);
1162 down(&devpriv->sem);
1164 for (i = 0; i < insn->n; i++) {
1165 ret = send_dux_commands(dev, USBDUX_CMD_TIMER_RD);
1167 goto counter_read_exit;
1168 ret = receive_dux_commands(dev, USBDUX_CMD_TIMER_RD);
1170 goto counter_read_exit;
1172 data[i] = le16_to_cpu(devpriv->insn_buf[chan + 1]);
1178 return ret ? ret : insn->n;
1181 static int usbdux_counter_write(struct comedi_device *dev,
1182 struct comedi_subdevice *s,
1183 struct comedi_insn *insn,
1186 struct usbdux_private *devpriv = dev->private;
1187 unsigned int chan = CR_CHAN(insn->chanspec);
1188 uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
1192 down(&devpriv->sem);
1194 devpriv->dux_commands[1] = chan;
1196 for (i = 0; i < insn->n; i++) {
1197 *p = cpu_to_le16(data[i]);
1199 ret = send_dux_commands(dev, USBDUX_CMD_TIMER_WR);
1206 return ret ? ret : insn->n;
1209 static int usbdux_counter_config(struct comedi_device *dev,
1210 struct comedi_subdevice *s,
1211 struct comedi_insn *insn, unsigned int *data)
1213 /* nothing to do so far */
1217 static void usbduxsub_unlink_pwm_urbs(struct comedi_device *dev)
1219 struct usbdux_private *devpriv = dev->private;
1221 usb_kill_urb(devpriv->pwm_urb);
1224 static void usbdux_pwm_stop(struct comedi_device *dev, int do_unlink)
1226 struct usbdux_private *devpriv = dev->private;
1229 usbduxsub_unlink_pwm_urbs(dev);
1231 devpriv->pwm_cmd_running = 0;
1234 static int usbdux_pwm_cancel(struct comedi_device *dev,
1235 struct comedi_subdevice *s)
1237 struct usbdux_private *devpriv = dev->private;
1240 down(&devpriv->sem);
1241 /* unlink only if it is really running */
1242 usbdux_pwm_stop(dev, devpriv->pwm_cmd_running);
1243 ret = send_dux_commands(dev, USBDUX_CMD_PWM_OFF);
1249 static void usbduxsub_pwm_irq(struct urb *urb)
1251 struct comedi_device *dev = urb->context;
1252 struct usbdux_private *devpriv = dev->private;
1255 switch (urb->status) {
1265 * after an unlink command, unplug, ... etc
1266 * no unlink needed here. Already shutting down.
1268 if (devpriv->pwm_cmd_running)
1269 usbdux_pwm_stop(dev, 0);
1275 if (devpriv->pwm_cmd_running) {
1276 dev_err(dev->class_dev,
1277 "Non-zero urb status received in pwm intr context: %d\n",
1279 usbdux_pwm_stop(dev, 0);
1284 /* are we actually running? */
1285 if (!devpriv->pwm_cmd_running)
1288 urb->transfer_buffer_length = devpriv->pwm_buf_sz;
1289 urb->dev = comedi_to_usb_dev(dev);
1291 if (devpriv->pwm_cmd_running) {
1292 ret = usb_submit_urb(urb, GFP_ATOMIC);
1294 dev_err(dev->class_dev,
1295 "pwm urb resubm failed in int-cont. ret=%d",
1297 if (ret == EL2NSYNC)
1298 dev_err(dev->class_dev,
1299 "buggy USB host controller or bug in IRQ handling!\n");
1301 /* don't do an unlink here */
1302 usbdux_pwm_stop(dev, 0);
1307 static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev)
1309 struct usb_device *usb = comedi_to_usb_dev(dev);
1310 struct usbdux_private *devpriv = dev->private;
1311 struct urb *urb = devpriv->pwm_urb;
1313 /* in case of a resubmission after an unlink... */
1314 usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
1315 urb->transfer_buffer,
1316 devpriv->pwm_buf_sz,
1320 return usb_submit_urb(urb, GFP_ATOMIC);
1323 static int usbdux_pwm_period(struct comedi_device *dev,
1324 struct comedi_subdevice *s,
1325 unsigned int period)
1327 struct usbdux_private *devpriv = dev->private;
1330 if (period < MIN_PWM_PERIOD) {
1333 fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
1337 devpriv->pwm_delay = fx2delay;
1338 devpriv->pwm_period = period;
1343 static int usbdux_pwm_start(struct comedi_device *dev,
1344 struct comedi_subdevice *s)
1346 struct usbdux_private *devpriv = dev->private;
1349 down(&devpriv->sem);
1351 if (devpriv->pwm_cmd_running)
1352 goto pwm_start_exit;
1354 devpriv->dux_commands[1] = devpriv->pwm_delay;
1355 ret = send_dux_commands(dev, USBDUX_CMD_PWM_ON);
1357 goto pwm_start_exit;
1359 /* initialise the buffer */
1360 memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
1362 devpriv->pwm_cmd_running = 1;
1363 ret = usbduxsub_submit_pwm_urbs(dev);
1365 devpriv->pwm_cmd_running = 0;
1373 static void usbdux_pwm_pattern(struct comedi_device *dev,
1374 struct comedi_subdevice *s,
1379 struct usbdux_private *devpriv = dev->private;
1380 char pwm_mask = (1 << chan); /* DIO bit for the PWM data */
1381 char sgn_mask = (16 << chan); /* DIO bit for the sign */
1382 char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
1383 int szbuf = devpriv->pwm_buf_sz;
1386 for (i = 0; i < szbuf; i++) {
1400 static int usbdux_pwm_write(struct comedi_device *dev,
1401 struct comedi_subdevice *s,
1402 struct comedi_insn *insn,
1405 unsigned int chan = CR_CHAN(insn->chanspec);
1408 * It doesn't make sense to support more than one value here
1409 * because it would just overwrite the PWM buffer.
1415 * The sign is set via a special INSN only, this gives us 8 bits
1416 * for normal operation, sign is 0 by default.
1418 usbdux_pwm_pattern(dev, s, chan, data[0], 0);
1423 static int usbdux_pwm_config(struct comedi_device *dev,
1424 struct comedi_subdevice *s,
1425 struct comedi_insn *insn,
1428 struct usbdux_private *devpriv = dev->private;
1429 unsigned int chan = CR_CHAN(insn->chanspec);
1432 case INSN_CONFIG_ARM:
1434 * if not zero the PWM is limited to a certain time which is
1435 * not supported here
1439 return usbdux_pwm_start(dev, s);
1440 case INSN_CONFIG_DISARM:
1441 return usbdux_pwm_cancel(dev, s);
1442 case INSN_CONFIG_GET_PWM_STATUS:
1443 data[1] = devpriv->pwm_cmd_running;
1445 case INSN_CONFIG_PWM_SET_PERIOD:
1446 return usbdux_pwm_period(dev, s, data[1]);
1447 case INSN_CONFIG_PWM_GET_PERIOD:
1448 data[1] = devpriv->pwm_period;
1450 case INSN_CONFIG_PWM_SET_H_BRIDGE:
1453 * data[2] = sign (for a relay)
1455 usbdux_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
1457 case INSN_CONFIG_PWM_GET_H_BRIDGE:
1458 /* values are not kept in this driver, nothing to return here */
1464 static int usbdux_firmware_upload(struct comedi_device *dev,
1465 const u8 *data, size_t size,
1466 unsigned long context)
1468 struct usb_device *usb = comedi_to_usb_dev(dev);
1476 if (size > USBDUX_FIRMWARE_MAX_LEN) {
1477 dev_err(dev->class_dev,
1478 "usbdux firmware binary it too large for FX2.\n");
1482 /* we generate a local buffer for the firmware */
1483 buf = kmemdup(data, size, GFP_KERNEL);
1487 /* we need a malloc'ed buffer for usb_control_msg() */
1488 tmp = kmalloc(1, GFP_KERNEL);
1494 /* stop the current firmware on the device */
1495 *tmp = 1; /* 7f92 to one */
1496 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1497 USBDUX_FIRMWARE_CMD,
1499 USBDUX_CPU_CS, 0x0000,
1503 dev_err(dev->class_dev, "can not stop firmware\n");
1507 /* upload the new firmware to the device */
1508 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1509 USBDUX_FIRMWARE_CMD,
1515 dev_err(dev->class_dev, "firmware upload failed\n");
1519 /* start the new firmware on the device */
1520 *tmp = 0; /* 7f92 to zero */
1521 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1522 USBDUX_FIRMWARE_CMD,
1524 USBDUX_CPU_CS, 0x0000,
1528 dev_err(dev->class_dev, "can not start firmware\n");
1536 static int usbdux_alloc_usb_buffers(struct comedi_device *dev)
1538 struct usb_device *usb = comedi_to_usb_dev(dev);
1539 struct usbdux_private *devpriv = dev->private;
1543 devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
1544 devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
1545 devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1546 devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(void *),
1548 devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(void *),
1550 if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
1551 !devpriv->ai_urbs || !devpriv->ao_urbs)
1554 for (i = 0; i < devpriv->n_ai_urbs; i++) {
1555 /* one frame: 1ms */
1556 urb = usb_alloc_urb(1, GFP_KERNEL);
1559 devpriv->ai_urbs[i] = urb;
1563 urb->pipe = usb_rcvisocpipe(usb, 6);
1564 urb->transfer_flags = URB_ISO_ASAP;
1565 urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1566 if (!urb->transfer_buffer)
1569 urb->complete = usbduxsub_ai_isoc_irq;
1570 urb->number_of_packets = 1;
1571 urb->transfer_buffer_length = SIZEINBUF;
1572 urb->iso_frame_desc[0].offset = 0;
1573 urb->iso_frame_desc[0].length = SIZEINBUF;
1576 for (i = 0; i < devpriv->n_ao_urbs; i++) {
1577 /* one frame: 1ms */
1578 urb = usb_alloc_urb(1, GFP_KERNEL);
1581 devpriv->ao_urbs[i] = urb;
1585 urb->pipe = usb_sndisocpipe(usb, 2);
1586 urb->transfer_flags = URB_ISO_ASAP;
1587 urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1588 if (!urb->transfer_buffer)
1591 urb->complete = usbduxsub_ao_isoc_irq;
1592 urb->number_of_packets = 1;
1593 urb->transfer_buffer_length = SIZEOUTBUF;
1594 urb->iso_frame_desc[0].offset = 0;
1595 urb->iso_frame_desc[0].length = SIZEOUTBUF;
1596 if (devpriv->high_speed)
1597 urb->interval = 8; /* uframes */
1599 urb->interval = 1; /* frames */
1603 if (devpriv->pwm_buf_sz) {
1604 urb = usb_alloc_urb(0, GFP_KERNEL);
1607 devpriv->pwm_urb = urb;
1609 /* max bulk ep size in high speed */
1610 urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
1612 if (!urb->transfer_buffer)
1619 static void usbdux_free_usb_buffers(struct comedi_device *dev)
1621 struct usbdux_private *devpriv = dev->private;
1625 urb = devpriv->pwm_urb;
1627 kfree(urb->transfer_buffer);
1630 if (devpriv->ao_urbs) {
1631 for (i = 0; i < devpriv->n_ao_urbs; i++) {
1632 urb = devpriv->ao_urbs[i];
1634 kfree(urb->transfer_buffer);
1638 kfree(devpriv->ao_urbs);
1640 if (devpriv->ai_urbs) {
1641 for (i = 0; i < devpriv->n_ai_urbs; i++) {
1642 urb = devpriv->ai_urbs[i];
1644 kfree(urb->transfer_buffer);
1648 kfree(devpriv->ai_urbs);
1650 kfree(devpriv->insn_buf);
1651 kfree(devpriv->in_buf);
1652 kfree(devpriv->dux_commands);
1655 static int usbdux_auto_attach(struct comedi_device *dev,
1656 unsigned long context_unused)
1658 struct usb_interface *intf = comedi_to_usb_interface(dev);
1659 struct usb_device *usb = comedi_to_usb_dev(dev);
1660 struct usbdux_private *devpriv;
1661 struct comedi_subdevice *s;
1664 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1668 sema_init(&devpriv->sem, 1);
1670 usb_set_intfdata(intf, devpriv);
1672 devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
1673 if (devpriv->high_speed) {
1674 devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
1675 devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
1676 devpriv->pwm_buf_sz = 512;
1678 devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
1679 devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
1682 ret = usbdux_alloc_usb_buffers(dev);
1686 /* setting to alternate setting 3: enabling iso ep and bulk ep. */
1687 ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
1690 dev_err(dev->class_dev,
1691 "could not set alternate setting 3 in high speed\n");
1695 ret = comedi_load_firmware(dev, &usb->dev, USBDUX_FIRMWARE,
1696 usbdux_firmware_upload, 0);
1700 ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4);
1704 /* Analog Input subdevice */
1705 s = &dev->subdevices[0];
1706 dev->read_subdev = s;
1707 s->type = COMEDI_SUBD_AI;
1708 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
1710 s->maxdata = 0x0fff;
1711 s->len_chanlist = 8;
1712 s->range_table = &range_usbdux_ai_range;
1713 s->insn_read = usbdux_ai_insn_read;
1714 s->do_cmdtest = usbdux_ai_cmdtest;
1715 s->do_cmd = usbdux_ai_cmd;
1716 s->cancel = usbdux_ai_cancel;
1718 /* Analog Output subdevice */
1719 s = &dev->subdevices[1];
1720 dev->write_subdev = s;
1721 s->type = COMEDI_SUBD_AO;
1722 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1723 s->n_chan = USBDUX_NUM_AO_CHAN;
1724 s->maxdata = 0x0fff;
1725 s->len_chanlist = s->n_chan;
1726 s->range_table = &range_usbdux_ao_range;
1727 s->do_cmdtest = usbdux_ao_cmdtest;
1728 s->do_cmd = usbdux_ao_cmd;
1729 s->cancel = usbdux_ao_cancel;
1730 s->insn_read = usbdux_ao_insn_read;
1731 s->insn_write = usbdux_ao_insn_write;
1733 /* Digital I/O subdevice */
1734 s = &dev->subdevices[2];
1735 s->type = COMEDI_SUBD_DIO;
1736 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1739 s->range_table = &range_digital;
1740 s->insn_bits = usbdux_dio_insn_bits;
1741 s->insn_config = usbdux_dio_insn_config;
1743 /* Counter subdevice */
1744 s = &dev->subdevices[3];
1745 s->type = COMEDI_SUBD_COUNTER;
1746 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1748 s->maxdata = 0xffff;
1749 s->insn_read = usbdux_counter_read;
1750 s->insn_write = usbdux_counter_write;
1751 s->insn_config = usbdux_counter_config;
1753 if (devpriv->high_speed) {
1755 s = &dev->subdevices[4];
1756 s->type = COMEDI_SUBD_PWM;
1757 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
1759 s->maxdata = devpriv->pwm_buf_sz;
1760 s->insn_write = usbdux_pwm_write;
1761 s->insn_config = usbdux_pwm_config;
1763 usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1769 static void usbdux_detach(struct comedi_device *dev)
1771 struct usb_interface *intf = comedi_to_usb_interface(dev);
1772 struct usbdux_private *devpriv = dev->private;
1774 usb_set_intfdata(intf, NULL);
1779 down(&devpriv->sem);
1781 /* force unlink all urbs */
1782 usbdux_pwm_stop(dev, 1);
1783 usbdux_ao_stop(dev, 1);
1784 usbdux_ai_stop(dev, 1);
1786 usbdux_free_usb_buffers(dev);
1791 static struct comedi_driver usbdux_driver = {
1792 .driver_name = "usbdux",
1793 .module = THIS_MODULE,
1794 .auto_attach = usbdux_auto_attach,
1795 .detach = usbdux_detach,
1798 static int usbdux_usb_probe(struct usb_interface *intf,
1799 const struct usb_device_id *id)
1801 return comedi_usb_auto_config(intf, &usbdux_driver, 0);
1804 static const struct usb_device_id usbdux_usb_table[] = {
1805 { USB_DEVICE(0x13d8, 0x0001) },
1806 { USB_DEVICE(0x13d8, 0x0002) },
1809 MODULE_DEVICE_TABLE(usb, usbdux_usb_table);
1811 static struct usb_driver usbdux_usb_driver = {
1813 .probe = usbdux_usb_probe,
1814 .disconnect = comedi_usb_auto_unconfig,
1815 .id_table = usbdux_usb_table,
1817 module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);
1819 MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1820 MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");
1821 MODULE_LICENSE("GPL");
1822 MODULE_FIRMWARE(USBDUX_FIRMWARE);