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