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