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

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