1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2004-2019 Bernd Porr, mail@berndporr.me.uk
4 */
5
6/*
7 * Driver: usbduxfast
8 * Description: University of Stirling USB DAQ & INCITE Technology Limited
9 * Devices: [ITL] USB-DUX-FAST (usbduxfast)
10 * Author: Bernd Porr <mail@berndporr.me.uk>
11 * Updated: 16 Nov 2019
12 * Status: stable
13 */
14
15/*
16 * I must give credit here to Chris Baugher who
17 * wrote the driver for AT-MIO-16d. I used some parts of this
18 * driver. I also must give credits to David Brownell
19 * who supported me with the USB development.
20 *
21 * Bernd Porr
22 *
23 *
24 * Revision history:
25 * 1.0: Fixed a rounding error in usbduxfast_ai_cmdtest
26 * 0.9: Dropping the first data packet which seems to be from the last transfer.
27 * Buffer overflows in the FX2 are handed over to comedi.
28 * 0.92: Dropping now 4 packets. The quad buffer has to be emptied.
29 * Added insn command basically for testing. Sample rate is
30 * 1MHz/16ch=62.5kHz
31 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
32 * 0.99a: added external trigger.
33 * 1.00: added firmware kernel request to the driver which fixed
34 * udev coldplug problem
35 */
36
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/slab.h>
40#include <linux/input.h>
41#include <linux/fcntl.h>
42#include <linux/compiler.h>
43#include <linux/comedi/comedi_usb.h>
44
45/*
46 * timeout for the USB-transfer
47 */
48#define EZTIMEOUT 30
49
50/*
51 * constants for "firmware" upload and download
52 */
53#define FIRMWARE "usbduxfast_firmware.bin"
54#define FIRMWARE_MAX_LEN 0x2000
55#define USBDUXFASTSUB_FIRMWARE 0xA0
56#define VENDOR_DIR_IN 0xC0
57#define VENDOR_DIR_OUT 0x40
58
59/*
60 * internal addresses of the 8051 processor
61 */
62#define USBDUXFASTSUB_CPUCS 0xE600
63
64/*
65 * max length of the transfer-buffer for software upload
66 */
67#define TB_LEN 0x2000
68
69/*
70 * input endpoint number
71 */
72#define BULKINEP 6
73
74/*
75 * endpoint for the A/D channellist: bulk OUT
76 */
77#define CHANNELLISTEP 4
78
79/*
80 * number of channels
81 */
82#define NUMCHANNELS 32
83
84/*
85 * size of the waveform descriptor
86 */
87#define WAVESIZE 0x20
88
89/*
90 * size of one A/D value
91 */
92#define SIZEADIN (sizeof(s16))
93
94/*
95 * size of the input-buffer IN BYTES
96 */
97#define SIZEINBUF 512
98
99/*
100 * 16 bytes
101 */
102#define SIZEINSNBUF 512
103
104/*
105 * size of the buffer for the dux commands in bytes
106 */
107#define SIZEOFDUXBUF 256
108
109/*
110 * number of in-URBs which receive the data: min=5
111 */
112#define NUMOFINBUFFERSHIGH 10
113
114/*
115 * min delay steps for more than one channel
116 * basically when the mux gives up ;-)
117 *
118 * steps at 30MHz in the FX2
119 */
120#define MIN_SAMPLING_PERIOD 9
121
122/*
123 * max number of 1/30MHz delay steps
124 */
125#define MAX_SAMPLING_PERIOD 500
126
127/*
128 * number of received packets to ignore before we start handing data
129 * over to comedi, it's quad buffering and we have to ignore 4 packets
130 */
131#define PACKETS_TO_IGNORE 4
132
133/*
134 * comedi constants
135 */
136static const struct comedi_lrange range_usbduxfast_ai_range = {
137 2, {
138 BIP_RANGE(0.75),
139 BIP_RANGE(0.5)
140 }
141};
142
143/*
144 * private structure of one subdevice
145 *
146 * this is the structure which holds all the data of this driver
147 * one sub device just now: A/D
148 */
149struct usbduxfast_private {
150 struct urb *urb; /* BULK-transfer handling: urb */
151 u8 *duxbuf;
152 s8 *inbuf;
153 short int ai_cmd_running; /* asynchronous command is running */
154 int ignore; /* counter which ignores the first buffers */
155 struct mutex mut;
156};
157
158/*
159 * bulk transfers to usbduxfast
160 */
161#define SENDADCOMMANDS 0
162#define SENDINITEP6 1
163
164static int usbduxfast_send_cmd(struct comedi_device *dev, int cmd_type)
165{
166 struct usb_device *usb = comedi_to_usb_dev(dev);
167 struct usbduxfast_private *devpriv = dev->private;
168 int nsent;
169 int ret;
170
171 devpriv->duxbuf[0] = cmd_type;
172
173 ret = usb_bulk_msg(usb_dev: usb, usb_sndbulkpipe(usb, CHANNELLISTEP),
174 data: devpriv->duxbuf, SIZEOFDUXBUF,
175 actual_length: &nsent, timeout: 10000);
176 if (ret < 0)
177 dev_err(dev->class_dev,
178 "could not transmit command to the usb-device, err=%d\n",
179 ret);
180 return ret;
181}
182
183static void usbduxfast_cmd_data(struct comedi_device *dev, int index,
184 u8 len, u8 op, u8 out, u8 log)
185{
186 struct usbduxfast_private *devpriv = dev->private;
187
188 /* Set the GPIF bytes, the first byte is the command byte */
189 devpriv->duxbuf[1 + 0x00 + index] = len;
190 devpriv->duxbuf[1 + 0x08 + index] = op;
191 devpriv->duxbuf[1 + 0x10 + index] = out;
192 devpriv->duxbuf[1 + 0x18 + index] = log;
193}
194
195static int usbduxfast_ai_stop(struct comedi_device *dev, int do_unlink)
196{
197 struct usbduxfast_private *devpriv = dev->private;
198
199 /* stop aquistion */
200 devpriv->ai_cmd_running = 0;
201
202 if (do_unlink && devpriv->urb) {
203 /* kill the running transfer */
204 usb_kill_urb(urb: devpriv->urb);
205 }
206
207 return 0;
208}
209
210static int usbduxfast_ai_cancel(struct comedi_device *dev,
211 struct comedi_subdevice *s)
212{
213 struct usbduxfast_private *devpriv = dev->private;
214 int ret;
215
216 mutex_lock(&devpriv->mut);
217 ret = usbduxfast_ai_stop(dev, do_unlink: 1);
218 mutex_unlock(lock: &devpriv->mut);
219
220 return ret;
221}
222
223static void usbduxfast_ai_handle_urb(struct comedi_device *dev,
224 struct comedi_subdevice *s,
225 struct urb *urb)
226{
227 struct usbduxfast_private *devpriv = dev->private;
228 struct comedi_async *async = s->async;
229 struct comedi_cmd *cmd = &async->cmd;
230 int ret;
231
232 if (devpriv->ignore) {
233 devpriv->ignore--;
234 } else {
235 unsigned int nsamples;
236
237 nsamples = comedi_bytes_to_samples(s, nbytes: urb->actual_length);
238 nsamples = comedi_nsamples_left(s, nsamples);
239 comedi_buf_write_samples(s, data: urb->transfer_buffer, nsamples);
240
241 if (cmd->stop_src == TRIG_COUNT &&
242 async->scans_done >= cmd->stop_arg)
243 async->events |= COMEDI_CB_EOA;
244 }
245
246 /* if command is still running, resubmit urb for BULK transfer */
247 if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
248 urb->dev = comedi_to_usb_dev(dev);
249 urb->status = 0;
250 ret = usb_submit_urb(urb, GFP_ATOMIC);
251 if (ret < 0) {
252 dev_err(dev->class_dev, "urb resubm failed: %d", ret);
253 async->events |= COMEDI_CB_ERROR;
254 }
255 }
256}
257
258static void usbduxfast_ai_interrupt(struct urb *urb)
259{
260 struct comedi_device *dev = urb->context;
261 struct comedi_subdevice *s = dev->read_subdev;
262 struct comedi_async *async = s->async;
263 struct usbduxfast_private *devpriv = dev->private;
264
265 /* exit if not running a command, do not resubmit urb */
266 if (!devpriv->ai_cmd_running)
267 return;
268
269 switch (urb->status) {
270 case 0:
271 usbduxfast_ai_handle_urb(dev, s, urb);
272 break;
273
274 case -ECONNRESET:
275 case -ENOENT:
276 case -ESHUTDOWN:
277 case -ECONNABORTED:
278 /* after an unlink command, unplug, ... etc */
279 async->events |= COMEDI_CB_ERROR;
280 break;
281
282 default:
283 /* a real error */
284 dev_err(dev->class_dev,
285 "non-zero urb status received in ai intr context: %d\n",
286 urb->status);
287 async->events |= COMEDI_CB_ERROR;
288 break;
289 }
290
291 /*
292 * comedi_handle_events() cannot be used in this driver. The (*cancel)
293 * operation would unlink the urb.
294 */
295 if (async->events & COMEDI_CB_CANCEL_MASK)
296 usbduxfast_ai_stop(dev, do_unlink: 0);
297
298 comedi_event(dev, s);
299}
300
301static int usbduxfast_submit_urb(struct comedi_device *dev)
302{
303 struct usb_device *usb = comedi_to_usb_dev(dev);
304 struct usbduxfast_private *devpriv = dev->private;
305 int ret;
306
307 usb_fill_bulk_urb(urb: devpriv->urb, dev: usb, usb_rcvbulkpipe(usb, BULKINEP),
308 transfer_buffer: devpriv->inbuf, SIZEINBUF,
309 complete_fn: usbduxfast_ai_interrupt, context: dev);
310
311 ret = usb_submit_urb(urb: devpriv->urb, GFP_ATOMIC);
312 if (ret) {
313 dev_err(dev->class_dev, "usb_submit_urb error %d\n", ret);
314 return ret;
315 }
316 return 0;
317}
318
319static int usbduxfast_ai_check_chanlist(struct comedi_device *dev,
320 struct comedi_subdevice *s,
321 struct comedi_cmd *cmd)
322{
323 unsigned int gain0 = CR_RANGE(cmd->chanlist[0]);
324 int i;
325
326 if (cmd->chanlist_len > 3 && cmd->chanlist_len != 16) {
327 dev_err(dev->class_dev, "unsupported combination of channels\n");
328 return -EINVAL;
329 }
330
331 for (i = 0; i < cmd->chanlist_len; ++i) {
332 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
333 unsigned int gain = CR_RANGE(cmd->chanlist[i]);
334
335 if (chan != i) {
336 dev_err(dev->class_dev,
337 "channels are not consecutive\n");
338 return -EINVAL;
339 }
340 if (gain != gain0 && cmd->chanlist_len > 3) {
341 dev_err(dev->class_dev,
342 "gain must be the same for all channels\n");
343 return -EINVAL;
344 }
345 }
346 return 0;
347}
348
349static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
350 struct comedi_subdevice *s,
351 struct comedi_cmd *cmd)
352{
353 int err = 0;
354 int err2 = 0;
355 unsigned int steps;
356 unsigned int arg;
357
358 /* Step 1 : check if triggers are trivially valid */
359
360 err |= comedi_check_trigger_src(src: &cmd->start_src,
361 TRIG_NOW | TRIG_EXT | TRIG_INT);
362 err |= comedi_check_trigger_src(src: &cmd->scan_begin_src, TRIG_FOLLOW);
363 err |= comedi_check_trigger_src(src: &cmd->convert_src, TRIG_TIMER);
364 err |= comedi_check_trigger_src(src: &cmd->scan_end_src, TRIG_COUNT);
365 err |= comedi_check_trigger_src(src: &cmd->stop_src, TRIG_COUNT | TRIG_NONE);
366
367 if (err)
368 return 1;
369
370 /* Step 2a : make sure trigger sources are unique */
371
372 err |= comedi_check_trigger_is_unique(src: cmd->start_src);
373 err |= comedi_check_trigger_is_unique(src: cmd->stop_src);
374
375 /* Step 2b : and mutually compatible */
376
377 if (err)
378 return 2;
379
380 /* Step 3: check if arguments are trivially valid */
381
382 err |= comedi_check_trigger_arg_is(arg: &cmd->start_arg, val: 0);
383
384 if (!cmd->chanlist_len)
385 err |= -EINVAL;
386
387 /* external start trigger is only valid for 1 or 16 channels */
388 if (cmd->start_src == TRIG_EXT &&
389 cmd->chanlist_len != 1 && cmd->chanlist_len != 16)
390 err |= -EINVAL;
391
392 err |= comedi_check_trigger_arg_is(arg: &cmd->scan_end_arg,
393 val: cmd->chanlist_len);
394
395 /*
396 * Validate the conversion timing:
397 * for 1 channel the timing in 30MHz "steps" is:
398 * steps <= MAX_SAMPLING_PERIOD
399 * for all other chanlist_len it is:
400 * MIN_SAMPLING_PERIOD <= steps <= MAX_SAMPLING_PERIOD
401 */
402 steps = (cmd->convert_arg * 30) / 1000;
403 if (cmd->chanlist_len != 1)
404 err2 |= comedi_check_trigger_arg_min(arg: &steps,
405 MIN_SAMPLING_PERIOD);
406 else
407 err2 |= comedi_check_trigger_arg_min(arg: &steps, val: 1);
408 err2 |= comedi_check_trigger_arg_max(arg: &steps, MAX_SAMPLING_PERIOD);
409 if (err2) {
410 err |= err2;
411 arg = (steps * 1000) / 30;
412 err |= comedi_check_trigger_arg_is(arg: &cmd->convert_arg, val: arg);
413 }
414
415 if (cmd->stop_src == TRIG_COUNT)
416 err |= comedi_check_trigger_arg_min(arg: &cmd->stop_arg, val: 1);
417 else /* TRIG_NONE */
418 err |= comedi_check_trigger_arg_is(arg: &cmd->stop_arg, val: 0);
419
420 if (err)
421 return 3;
422
423 /* Step 4: fix up any arguments */
424
425 /* Step 5: check channel list if it exists */
426 if (cmd->chanlist && cmd->chanlist_len > 0)
427 err |= usbduxfast_ai_check_chanlist(dev, s, cmd);
428 if (err)
429 return 5;
430
431 return 0;
432}
433
434static int usbduxfast_ai_inttrig(struct comedi_device *dev,
435 struct comedi_subdevice *s,
436 unsigned int trig_num)
437{
438 struct usbduxfast_private *devpriv = dev->private;
439 struct comedi_cmd *cmd = &s->async->cmd;
440 int ret;
441
442 if (trig_num != cmd->start_arg)
443 return -EINVAL;
444
445 mutex_lock(&devpriv->mut);
446
447 if (!devpriv->ai_cmd_running) {
448 devpriv->ai_cmd_running = 1;
449 ret = usbduxfast_submit_urb(dev);
450 if (ret < 0) {
451 dev_err(dev->class_dev, "urbSubmit: err=%d\n", ret);
452 devpriv->ai_cmd_running = 0;
453 mutex_unlock(lock: &devpriv->mut);
454 return ret;
455 }
456 s->async->inttrig = NULL;
457 } else {
458 dev_err(dev->class_dev, "ai is already running\n");
459 }
460 mutex_unlock(lock: &devpriv->mut);
461 return 1;
462}
463
464static int usbduxfast_ai_cmd(struct comedi_device *dev,
465 struct comedi_subdevice *s)
466{
467 struct usbduxfast_private *devpriv = dev->private;
468 struct comedi_cmd *cmd = &s->async->cmd;
469 unsigned int rngmask = 0xff;
470 int j, ret;
471 long steps, steps_tmp;
472
473 mutex_lock(&devpriv->mut);
474 if (devpriv->ai_cmd_running) {
475 ret = -EBUSY;
476 goto cmd_exit;
477 }
478
479 /*
480 * ignore the first buffers from the device if there
481 * is an error condition
482 */
483 devpriv->ignore = PACKETS_TO_IGNORE;
484
485 steps = (cmd->convert_arg * 30) / 1000;
486
487 switch (cmd->chanlist_len) {
488 case 1:
489 /*
490 * one channel
491 */
492
493 if (CR_RANGE(cmd->chanlist[0]) > 0)
494 rngmask = 0xff - 0x04;
495 else
496 rngmask = 0xff;
497
498 /*
499 * for external trigger: looping in this state until
500 * the RDY0 pin becomes zero
501 */
502
503 /* we loop here until ready has been set */
504 if (cmd->start_src == TRIG_EXT) {
505 /* branch back to state 0 */
506 /* deceision state w/o data */
507 /* RDY0 = 0 */
508 usbduxfast_cmd_data(dev, index: 0, len: 0x01, op: 0x01, out: rngmask, log: 0x00);
509 } else { /* we just proceed to state 1 */
510 usbduxfast_cmd_data(dev, index: 0, len: 0x01, op: 0x00, out: rngmask, log: 0x00);
511 }
512
513 if (steps < MIN_SAMPLING_PERIOD) {
514 /* for fast single channel aqu without mux */
515 if (steps <= 1) {
516 /*
517 * we just stay here at state 1 and rexecute
518 * the same state this gives us 30MHz sampling
519 * rate
520 */
521
522 /* branch back to state 1 */
523 /* deceision state with data */
524 /* doesn't matter */
525 usbduxfast_cmd_data(dev, index: 1,
526 len: 0x89, op: 0x03, out: rngmask, log: 0xff);
527 } else {
528 /*
529 * we loop through two states: data and delay
530 * max rate is 15MHz
531 */
532 /* data */
533 /* doesn't matter */
534 usbduxfast_cmd_data(dev, index: 1, len: steps - 1,
535 op: 0x02, out: rngmask, log: 0x00);
536
537 /* branch back to state 1 */
538 /* deceision state w/o data */
539 /* doesn't matter */
540 usbduxfast_cmd_data(dev, index: 2,
541 len: 0x09, op: 0x01, out: rngmask, log: 0xff);
542 }
543 } else {
544 /*
545 * we loop through 3 states: 2x delay and 1x data
546 * this gives a min sampling rate of 60kHz
547 */
548
549 /* we have 1 state with duration 1 */
550 steps = steps - 1;
551
552 /* do the first part of the delay */
553 usbduxfast_cmd_data(dev, index: 1,
554 len: steps / 2, op: 0x00, out: rngmask, log: 0x00);
555
556 /* and the second part */
557 usbduxfast_cmd_data(dev, index: 2, len: steps - steps / 2,
558 op: 0x00, out: rngmask, log: 0x00);
559
560 /* get the data and branch back */
561
562 /* branch back to state 1 */
563 /* deceision state w data */
564 /* doesn't matter */
565 usbduxfast_cmd_data(dev, index: 3,
566 len: 0x09, op: 0x03, out: rngmask, log: 0xff);
567 }
568 break;
569
570 case 2:
571 /*
572 * two channels
573 * commit data to the FIFO
574 */
575
576 if (CR_RANGE(cmd->chanlist[0]) > 0)
577 rngmask = 0xff - 0x04;
578 else
579 rngmask = 0xff;
580
581 /* data */
582 usbduxfast_cmd_data(dev, index: 0, len: 0x01, op: 0x02, out: rngmask, log: 0x00);
583
584 /* we have 1 state with duration 1: state 0 */
585 steps_tmp = steps - 1;
586
587 if (CR_RANGE(cmd->chanlist[1]) > 0)
588 rngmask = 0xff - 0x04;
589 else
590 rngmask = 0xff;
591
592 /* do the first part of the delay */
593 /* count */
594 usbduxfast_cmd_data(dev, index: 1, len: steps_tmp / 2,
595 op: 0x00, out: 0xfe & rngmask, log: 0x00);
596
597 /* and the second part */
598 usbduxfast_cmd_data(dev, index: 2, len: steps_tmp - steps_tmp / 2,
599 op: 0x00, out: rngmask, log: 0x00);
600
601 /* data */
602 usbduxfast_cmd_data(dev, index: 3, len: 0x01, op: 0x02, out: rngmask, log: 0x00);
603
604 /*
605 * we have 2 states with duration 1: step 6 and
606 * the IDLE state
607 */
608 steps_tmp = steps - 2;
609
610 if (CR_RANGE(cmd->chanlist[0]) > 0)
611 rngmask = 0xff - 0x04;
612 else
613 rngmask = 0xff;
614
615 /* do the first part of the delay */
616 /* reset */
617 usbduxfast_cmd_data(dev, index: 4, len: steps_tmp / 2,
618 op: 0x00, out: (0xff - 0x02) & rngmask, log: 0x00);
619
620 /* and the second part */
621 usbduxfast_cmd_data(dev, index: 5, len: steps_tmp - steps_tmp / 2,
622 op: 0x00, out: rngmask, log: 0x00);
623
624 usbduxfast_cmd_data(dev, index: 6, len: 0x01, op: 0x00, out: rngmask, log: 0x00);
625 break;
626
627 case 3:
628 /*
629 * three channels
630 */
631 for (j = 0; j < 1; j++) {
632 int index = j * 2;
633
634 if (CR_RANGE(cmd->chanlist[j]) > 0)
635 rngmask = 0xff - 0x04;
636 else
637 rngmask = 0xff;
638 /*
639 * commit data to the FIFO and do the first part
640 * of the delay
641 */
642 /* data */
643 /* no change */
644 usbduxfast_cmd_data(dev, index, len: steps / 2,
645 op: 0x02, out: rngmask, log: 0x00);
646
647 if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
648 rngmask = 0xff - 0x04;
649 else
650 rngmask = 0xff;
651
652 /* do the second part of the delay */
653 /* no data */
654 /* count */
655 usbduxfast_cmd_data(dev, index: index + 1, len: steps - steps / 2,
656 op: 0x00, out: 0xfe & rngmask, log: 0x00);
657 }
658
659 /* 2 steps with duration 1: the idele step and step 6: */
660 steps_tmp = steps - 2;
661
662 /* commit data to the FIFO and do the first part of the delay */
663 /* data */
664 usbduxfast_cmd_data(dev, index: 4, len: steps_tmp / 2,
665 op: 0x02, out: rngmask, log: 0x00);
666
667 if (CR_RANGE(cmd->chanlist[0]) > 0)
668 rngmask = 0xff - 0x04;
669 else
670 rngmask = 0xff;
671
672 /* do the second part of the delay */
673 /* no data */
674 /* reset */
675 usbduxfast_cmd_data(dev, index: 5, len: steps_tmp - steps_tmp / 2,
676 op: 0x00, out: (0xff - 0x02) & rngmask, log: 0x00);
677
678 usbduxfast_cmd_data(dev, index: 6, len: 0x01, op: 0x00, out: rngmask, log: 0x00);
679 break;
680
681 case 16:
682 if (CR_RANGE(cmd->chanlist[0]) > 0)
683 rngmask = 0xff - 0x04;
684 else
685 rngmask = 0xff;
686
687 if (cmd->start_src == TRIG_EXT) {
688 /*
689 * we loop here until ready has been set
690 */
691
692 /* branch back to state 0 */
693 /* deceision state w/o data */
694 /* reset */
695 /* RDY0 = 0 */
696 usbduxfast_cmd_data(dev, index: 0, len: 0x01, op: 0x01,
697 out: (0xff - 0x02) & rngmask, log: 0x00);
698 } else {
699 /*
700 * we just proceed to state 1
701 */
702
703 /* 30us reset pulse */
704 /* reset */
705 usbduxfast_cmd_data(dev, index: 0, len: 0xff, op: 0x00,
706 out: (0xff - 0x02) & rngmask, log: 0x00);
707 }
708
709 /* commit data to the FIFO */
710 /* data */
711 usbduxfast_cmd_data(dev, index: 1, len: 0x01, op: 0x02, out: rngmask, log: 0x00);
712
713 /* we have 2 states with duration 1 */
714 steps = steps - 2;
715
716 /* do the first part of the delay */
717 usbduxfast_cmd_data(dev, index: 2, len: steps / 2,
718 op: 0x00, out: 0xfe & rngmask, log: 0x00);
719
720 /* and the second part */
721 usbduxfast_cmd_data(dev, index: 3, len: steps - steps / 2,
722 op: 0x00, out: rngmask, log: 0x00);
723
724 /* branch back to state 1 */
725 /* deceision state w/o data */
726 /* doesn't matter */
727 usbduxfast_cmd_data(dev, index: 4, len: 0x09, op: 0x01, out: rngmask, log: 0xff);
728
729 break;
730 }
731
732 /* 0 means that the AD commands are sent */
733 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
734 if (ret < 0)
735 goto cmd_exit;
736
737 if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
738 /* enable this acquisition operation */
739 devpriv->ai_cmd_running = 1;
740 ret = usbduxfast_submit_urb(dev);
741 if (ret < 0) {
742 devpriv->ai_cmd_running = 0;
743 /* fixme: unlink here?? */
744 goto cmd_exit;
745 }
746 s->async->inttrig = NULL;
747 } else { /* TRIG_INT */
748 s->async->inttrig = usbduxfast_ai_inttrig;
749 }
750
751cmd_exit:
752 mutex_unlock(lock: &devpriv->mut);
753
754 return ret;
755}
756
757/*
758 * Mode 0 is used to get a single conversion on demand.
759 */
760static int usbduxfast_ai_insn_read(struct comedi_device *dev,
761 struct comedi_subdevice *s,
762 struct comedi_insn *insn,
763 unsigned int *data)
764{
765 struct usb_device *usb = comedi_to_usb_dev(dev);
766 struct usbduxfast_private *devpriv = dev->private;
767 unsigned int chan = CR_CHAN(insn->chanspec);
768 unsigned int range = CR_RANGE(insn->chanspec);
769 u8 rngmask = range ? (0xff - 0x04) : 0xff;
770 int i, j, n, actual_length;
771 int ret;
772
773 mutex_lock(&devpriv->mut);
774
775 if (devpriv->ai_cmd_running) {
776 dev_err(dev->class_dev,
777 "ai_insn_read not possible, async cmd is running\n");
778 mutex_unlock(lock: &devpriv->mut);
779 return -EBUSY;
780 }
781
782 /* set command for the first channel */
783
784 /* commit data to the FIFO */
785 /* data */
786 usbduxfast_cmd_data(dev, index: 0, len: 0x01, op: 0x02, out: rngmask, log: 0x00);
787
788 /* do the first part of the delay */
789 usbduxfast_cmd_data(dev, index: 1, len: 0x0c, op: 0x00, out: 0xfe & rngmask, log: 0x00);
790 usbduxfast_cmd_data(dev, index: 2, len: 0x01, op: 0x00, out: 0xfe & rngmask, log: 0x00);
791 usbduxfast_cmd_data(dev, index: 3, len: 0x01, op: 0x00, out: 0xfe & rngmask, log: 0x00);
792 usbduxfast_cmd_data(dev, index: 4, len: 0x01, op: 0x00, out: 0xfe & rngmask, log: 0x00);
793
794 /* second part */
795 usbduxfast_cmd_data(dev, index: 5, len: 0x0c, op: 0x00, out: rngmask, log: 0x00);
796 usbduxfast_cmd_data(dev, index: 6, len: 0x01, op: 0x00, out: rngmask, log: 0x00);
797
798 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
799 if (ret < 0) {
800 mutex_unlock(lock: &devpriv->mut);
801 return ret;
802 }
803
804 for (i = 0; i < PACKETS_TO_IGNORE; i++) {
805 ret = usb_bulk_msg(usb_dev: usb, usb_rcvbulkpipe(usb, BULKINEP),
806 data: devpriv->inbuf, SIZEINBUF,
807 actual_length: &actual_length, timeout: 10000);
808 if (ret < 0) {
809 dev_err(dev->class_dev, "insn timeout, no data\n");
810 mutex_unlock(lock: &devpriv->mut);
811 return ret;
812 }
813 }
814
815 for (i = 0; i < insn->n;) {
816 ret = usb_bulk_msg(usb_dev: usb, usb_rcvbulkpipe(usb, BULKINEP),
817 data: devpriv->inbuf, SIZEINBUF,
818 actual_length: &actual_length, timeout: 10000);
819 if (ret < 0) {
820 dev_err(dev->class_dev, "insn data error: %d\n", ret);
821 mutex_unlock(lock: &devpriv->mut);
822 return ret;
823 }
824 n = actual_length / sizeof(u16);
825 if ((n % 16) != 0) {
826 dev_err(dev->class_dev, "insn data packet corrupted\n");
827 mutex_unlock(lock: &devpriv->mut);
828 return -EINVAL;
829 }
830 for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
831 data[i] = ((u16 *)(devpriv->inbuf))[j];
832 i++;
833 }
834 }
835
836 mutex_unlock(lock: &devpriv->mut);
837
838 return insn->n;
839}
840
841static int usbduxfast_upload_firmware(struct comedi_device *dev,
842 const u8 *data, size_t size,
843 unsigned long context)
844{
845 struct usb_device *usb = comedi_to_usb_dev(dev);
846 u8 *buf;
847 unsigned char *tmp;
848 int ret;
849
850 if (!data)
851 return 0;
852
853 if (size > FIRMWARE_MAX_LEN) {
854 dev_err(dev->class_dev, "firmware binary too large for FX2\n");
855 return -ENOMEM;
856 }
857
858 /* we generate a local buffer for the firmware */
859 buf = kmemdup(p: data, size, GFP_KERNEL);
860 if (!buf)
861 return -ENOMEM;
862
863 /* we need a malloc'ed buffer for usb_control_msg() */
864 tmp = kmalloc(size: 1, GFP_KERNEL);
865 if (!tmp) {
866 kfree(objp: buf);
867 return -ENOMEM;
868 }
869
870 /* stop the current firmware on the device */
871 *tmp = 1; /* 7f92 to one */
872 ret = usb_control_msg(dev: usb, usb_sndctrlpipe(usb, 0),
873 USBDUXFASTSUB_FIRMWARE,
874 VENDOR_DIR_OUT,
875 USBDUXFASTSUB_CPUCS, index: 0x0000,
876 data: tmp, size: 1,
877 EZTIMEOUT);
878 if (ret < 0) {
879 dev_err(dev->class_dev, "can not stop firmware\n");
880 goto done;
881 }
882
883 /* upload the new firmware to the device */
884 ret = usb_control_msg(dev: usb, usb_sndctrlpipe(usb, 0),
885 USBDUXFASTSUB_FIRMWARE,
886 VENDOR_DIR_OUT,
887 value: 0, index: 0x0000,
888 data: buf, size,
889 EZTIMEOUT);
890 if (ret < 0) {
891 dev_err(dev->class_dev, "firmware upload failed\n");
892 goto done;
893 }
894
895 /* start the new firmware on the device */
896 *tmp = 0; /* 7f92 to zero */
897 ret = usb_control_msg(dev: usb, usb_sndctrlpipe(usb, 0),
898 USBDUXFASTSUB_FIRMWARE,
899 VENDOR_DIR_OUT,
900 USBDUXFASTSUB_CPUCS, index: 0x0000,
901 data: tmp, size: 1,
902 EZTIMEOUT);
903 if (ret < 0)
904 dev_err(dev->class_dev, "can not start firmware\n");
905
906done:
907 kfree(objp: tmp);
908 kfree(objp: buf);
909 return ret;
910}
911
912static int usbduxfast_auto_attach(struct comedi_device *dev,
913 unsigned long context_unused)
914{
915 struct usb_interface *intf = comedi_to_usb_interface(dev);
916 struct usb_device *usb = comedi_to_usb_dev(dev);
917 struct usbduxfast_private *devpriv;
918 struct comedi_subdevice *s;
919 int ret;
920
921 if (usb->speed != USB_SPEED_HIGH) {
922 dev_err(dev->class_dev,
923 "This driver needs USB 2.0 to operate. Aborting...\n");
924 return -ENODEV;
925 }
926
927 devpriv = comedi_alloc_devpriv(dev, size: sizeof(*devpriv));
928 if (!devpriv)
929 return -ENOMEM;
930
931 mutex_init(&devpriv->mut);
932 usb_set_intfdata(intf, data: devpriv);
933
934 devpriv->duxbuf = kmalloc(SIZEOFDUXBUF, GFP_KERNEL);
935 if (!devpriv->duxbuf)
936 return -ENOMEM;
937
938 ret = usb_set_interface(dev: usb,
939 ifnum: intf->altsetting->desc.bInterfaceNumber, alternate: 1);
940 if (ret < 0) {
941 dev_err(dev->class_dev,
942 "could not switch to alternate setting 1\n");
943 return -ENODEV;
944 }
945
946 devpriv->urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL);
947 if (!devpriv->urb)
948 return -ENOMEM;
949
950 devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL);
951 if (!devpriv->inbuf)
952 return -ENOMEM;
953
954 ret = comedi_load_firmware(dev, hw_dev: &usb->dev, FIRMWARE,
955 cb: usbduxfast_upload_firmware, context: 0);
956 if (ret)
957 return ret;
958
959 ret = comedi_alloc_subdevices(dev, num_subdevices: 1);
960 if (ret)
961 return ret;
962
963 /* Analog Input subdevice */
964 s = &dev->subdevices[0];
965 dev->read_subdev = s;
966 s->type = COMEDI_SUBD_AI;
967 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
968 s->n_chan = 16;
969 s->maxdata = 0x1000; /* 12-bit + 1 overflow bit */
970 s->range_table = &range_usbduxfast_ai_range;
971 s->insn_read = usbduxfast_ai_insn_read;
972 s->len_chanlist = s->n_chan;
973 s->do_cmdtest = usbduxfast_ai_cmdtest;
974 s->do_cmd = usbduxfast_ai_cmd;
975 s->cancel = usbduxfast_ai_cancel;
976
977 return 0;
978}
979
980static void usbduxfast_detach(struct comedi_device *dev)
981{
982 struct usb_interface *intf = comedi_to_usb_interface(dev);
983 struct usbduxfast_private *devpriv = dev->private;
984
985 if (!devpriv)
986 return;
987
988 mutex_lock(&devpriv->mut);
989
990 usb_set_intfdata(intf, NULL);
991
992 if (devpriv->urb) {
993 /* waits until a running transfer is over */
994 usb_kill_urb(urb: devpriv->urb);
995
996 kfree(objp: devpriv->inbuf);
997 usb_free_urb(urb: devpriv->urb);
998 }
999
1000 kfree(objp: devpriv->duxbuf);
1001
1002 mutex_unlock(lock: &devpriv->mut);
1003
1004 mutex_destroy(lock: &devpriv->mut);
1005}
1006
1007static struct comedi_driver usbduxfast_driver = {
1008 .driver_name = "usbduxfast",
1009 .module = THIS_MODULE,
1010 .auto_attach = usbduxfast_auto_attach,
1011 .detach = usbduxfast_detach,
1012};
1013
1014static int usbduxfast_usb_probe(struct usb_interface *intf,
1015 const struct usb_device_id *id)
1016{
1017 return comedi_usb_auto_config(intf, driver: &usbduxfast_driver, context: 0);
1018}
1019
1020static const struct usb_device_id usbduxfast_usb_table[] = {
1021 /* { USB_DEVICE(0x4b4, 0x8613) }, testing */
1022 { USB_DEVICE(0x13d8, 0x0010) }, /* real ID */
1023 { USB_DEVICE(0x13d8, 0x0011) }, /* real ID */
1024 { }
1025};
1026MODULE_DEVICE_TABLE(usb, usbduxfast_usb_table);
1027
1028static struct usb_driver usbduxfast_usb_driver = {
1029 .name = "usbduxfast",
1030 .probe = usbduxfast_usb_probe,
1031 .disconnect = comedi_usb_auto_unconfig,
1032 .id_table = usbduxfast_usb_table,
1033};
1034module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver);
1035
1036MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1037MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com");
1038MODULE_LICENSE("GPL");
1039MODULE_FIRMWARE(FIRMWARE);
1040

source code of linux/drivers/comedi/drivers/usbduxfast.c