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