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