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