Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / comedi / drivers / usbduxfast.c
CommitLineData
f47c697d 1/*
533de0f8 2 * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk
4e8ad0dc
MK
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
4e8ad0dc 13 */
f47c697d 14
533de0f8
BP
15/*
16 * Driver: usbduxfast
17 * Description: University of Stirling USB DAQ & INCITE Technology Limited
504a1aa7 18 * Devices: [ITL] USB-DUX-FAST (usbduxfast)
533de0f8
BP
19 * Author: Bernd Porr <mail@berndporr.me.uk>
20 * Updated: 10 Oct 2014
21 * Status: stable
22 */
23
f47c697d
BP
24/*
25 * I must give credit here to Chris Baugher who
26 * wrote the driver for AT-MIO-16d. I used some parts of this
27 * driver. I also must give credits to David Brownell
28 * who supported me with the USB development.
29 *
30 * Bernd Porr
31 *
32 *
33 * Revision history:
34 * 0.9: Dropping the first data packet which seems to be from the last transfer.
35 * Buffer overflows in the FX2 are handed over to comedi.
36 * 0.92: Dropping now 4 packets. The quad buffer has to be emptied.
4e8ad0dc
MK
37 * Added insn command basically for testing. Sample rate is
38 * 1MHz/16ch=62.5kHz
f47c697d
BP
39 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
40 * 0.99a: added external trigger.
6742c0af
BP
41 * 1.00: added firmware kernel request to the driver which fixed
42 * udev coldplug problem
f47c697d
BP
43 */
44
45#include <linux/kernel.h>
46#include <linux/module.h>
f47c697d
BP
47#include <linux/slab.h>
48#include <linux/input.h>
f47c697d
BP
49#include <linux/fcntl.h>
50#include <linux/compiler.h>
d3f83952 51#include "../comedi_usb.h"
f47c697d 52
4e8ad0dc
MK
53/*
54 * timeout for the USB-transfer
55 */
56#define EZTIMEOUT 30
f47c697d 57
4e8ad0dc
MK
58/*
59 * constants for "firmware" upload and download
60 */
e74f7fc5 61#define FIRMWARE "usbduxfast_firmware.bin"
dcd29f56 62#define FIRMWARE_MAX_LEN 0x2000
4e8ad0dc
MK
63#define USBDUXFASTSUB_FIRMWARE 0xA0
64#define VENDOR_DIR_IN 0xC0
65#define VENDOR_DIR_OUT 0x40
f47c697d 66
4e8ad0dc 67/*
f69b0d64 68 * internal addresses of the 8051 processor
4e8ad0dc
MK
69 */
70#define USBDUXFASTSUB_CPUCS 0xE600
f47c697d 71
4e8ad0dc
MK
72/*
73 * max lenghth of the transfer-buffer for software upload
74 */
75#define TB_LEN 0x2000
f47c697d 76
4e8ad0dc
MK
77/*
78 * input endpoint number
79 */
80#define BULKINEP 6
f47c697d 81
4e8ad0dc
MK
82/*
83 * endpoint for the A/D channellist: bulk OUT
84 */
85#define CHANNELLISTEP 4
f47c697d 86
4e8ad0dc
MK
87/*
88 * number of channels
89 */
90#define NUMCHANNELS 32
f47c697d 91
4e8ad0dc
MK
92/*
93 * size of the waveform descriptor
94 */
95#define WAVESIZE 0x20
f47c697d 96
4e8ad0dc
MK
97/*
98 * size of one A/D value
99 */
26961546 100#define SIZEADIN (sizeof(s16))
f47c697d 101
4e8ad0dc
MK
102/*
103 * size of the input-buffer IN BYTES
104 */
105#define SIZEINBUF 512
f47c697d 106
4e8ad0dc
MK
107/*
108 * 16 bytes
109 */
110#define SIZEINSNBUF 512
f47c697d 111
4e8ad0dc
MK
112/*
113 * size of the buffer for the dux commands in bytes
114 */
5659e24a 115#define SIZEOFDUXBUF 256
f47c697d 116
4e8ad0dc
MK
117/*
118 * number of in-URBs which receive the data: min=5
119 */
120#define NUMOFINBUFFERSHIGH 10
f47c697d 121
4e8ad0dc
MK
122/*
123 * min delay steps for more than one channel
124 * basically when the mux gives up ;-)
125 *
126 * steps at 30MHz in the FX2
127 */
128#define MIN_SAMPLING_PERIOD 9
f47c697d 129
4e8ad0dc
MK
130/*
131 * max number of 1/30MHz delay steps
132 */
133#define MAX_SAMPLING_PERIOD 500
f47c697d 134
4e8ad0dc
MK
135/*
136 * number of received packets to ignore before we start handing data
137 * over to comedi, it's quad buffering and we have to ignore 4 packets
138 */
139#define PACKETS_TO_IGNORE 4
f47c697d 140
4e8ad0dc
MK
141/*
142 * comedi constants
143 */
9ced1de6 144static const struct comedi_lrange range_usbduxfast_ai_range = {
67b3b78f
HS
145 2, {
146 BIP_RANGE(0.75),
147 BIP_RANGE(0.5)
148 }
f47c697d
BP
149};
150
151/*
152 * private structure of one subdevice
4e8ad0dc
MK
153 *
154 * this is the structure which holds all the data of this driver
155 * one sub device just now: A/D
f47c697d 156 */
7aa41c3c 157struct usbduxfast_private {
da58c263 158 struct urb *urb; /* BULK-transfer handling: urb */
26961546
HS
159 u8 *duxbuf;
160 s8 *inbuf;
4e8ad0dc 161 short int ai_cmd_running; /* asynchronous command is running */
24b83783 162 int ignore; /* counter which ignores the first buffers */
27a90695 163 struct mutex mut;
4e8ad0dc 164};
f47c697d 165
4e8ad0dc
MK
166/*
167 * bulk transfers to usbduxfast
168 */
f47c697d
BP
169#define SENDADCOMMANDS 0
170#define SENDINITEP6 1
171
665ff8d3 172static int usbduxfast_send_cmd(struct comedi_device *dev, int cmd_type)
f47c697d 173{
0a92de24 174 struct usb_device *usb = comedi_to_usb_dev(dev);
da63c39c 175 struct usbduxfast_private *devpriv = dev->private;
665ff8d3
HS
176 int nsent;
177 int ret;
0a3b8b64 178
5659e24a 179 devpriv->duxbuf[0] = cmd_type;
0a3b8b64 180
665ff8d3 181 ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, CHANNELLISTEP),
5659e24a
HS
182 devpriv->duxbuf, SIZEOFDUXBUF,
183 &nsent, 10000);
665ff8d3 184 if (ret < 0)
106af997 185 dev_err(dev->class_dev,
5659e24a 186 "could not transmit command to the usb-device, err=%d\n",
665ff8d3
HS
187 ret);
188 return ret;
f47c697d
BP
189}
190
17fdeba0 191static void usbduxfast_cmd_data(struct comedi_device *dev, int index,
26961546 192 u8 len, u8 op, u8 out, u8 log)
17fdeba0
HS
193{
194 struct usbduxfast_private *devpriv = dev->private;
195
196 /* Set the GPIF bytes, the first byte is the command byte */
197 devpriv->duxbuf[1 + 0x00 + index] = len;
198 devpriv->duxbuf[1 + 0x08 + index] = op;
199 devpriv->duxbuf[1 + 0x10 + index] = out;
200 devpriv->duxbuf[1 + 0x18 + index] = log;
201}
202
32fa46b9 203static int usbduxfast_ai_stop(struct comedi_device *dev, int do_unlink)
f47c697d 204{
da63c39c 205 struct usbduxfast_private *devpriv = dev->private;
f47c697d 206
32fa46b9 207 /* stop aquistion */
7aa41c3c 208 devpriv->ai_cmd_running = 0;
f47c697d 209
32fa46b9
HS
210 if (do_unlink && devpriv->urb) {
211 /* kill the running transfer */
212 usb_kill_urb(devpriv->urb);
213 }
f47c697d 214
32fa46b9 215 return 0;
f47c697d
BP
216}
217
0a85b6f0
MT
218static int usbduxfast_ai_cancel(struct comedi_device *dev,
219 struct comedi_subdevice *s)
f47c697d 220{
7aa41c3c 221 struct usbduxfast_private *devpriv = dev->private;
4e8ad0dc 222 int ret;
f47c697d 223
27a90695 224 mutex_lock(&devpriv->mut);
da63c39c 225 ret = usbduxfast_ai_stop(dev, 1);
27a90695 226 mutex_unlock(&devpriv->mut);
f47c697d 227
4e8ad0dc 228 return ret;
f47c697d
BP
229}
230
7c88f9f4
HS
231static void usbduxfast_ai_handle_urb(struct comedi_device *dev,
232 struct comedi_subdevice *s,
233 struct urb *urb)
234{
235 struct usbduxfast_private *devpriv = dev->private;
236 struct comedi_async *async = s->async;
237 struct comedi_cmd *cmd = &async->cmd;
238 int ret;
239
240 if (devpriv->ignore) {
241 devpriv->ignore--;
242 } else {
c39e050d 243 unsigned int nsamples;
7c88f9f4 244
c39e050d 245 nsamples = comedi_bytes_to_samples(s, urb->actual_length);
979f9996 246 nsamples = comedi_nsamples_left(s, nsamples);
f81ac41b 247 comedi_buf_write_samples(s, urb->transfer_buffer, nsamples);
979f9996
HS
248
249 if (cmd->stop_src == TRIG_COUNT &&
250 async->scans_done >= cmd->stop_arg)
251 async->events |= COMEDI_CB_EOA;
7c88f9f4
HS
252 }
253
254 /* if command is still running, resubmit urb for BULK transfer */
255 if (!(async->events & COMEDI_CB_CANCEL_MASK)) {
256 urb->dev = comedi_to_usb_dev(dev);
257 urb->status = 0;
258 ret = usb_submit_urb(urb, GFP_ATOMIC);
259 if (ret < 0) {
260 dev_err(dev->class_dev, "urb resubm failed: %d", ret);
261 async->events |= COMEDI_CB_ERROR;
262 }
263 }
264}
265
f8eb27e0 266static void usbduxfast_ai_interrupt(struct urb *urb)
f47c697d 267{
f8eb27e0
HS
268 struct comedi_device *dev = urb->context;
269 struct comedi_subdevice *s = dev->read_subdev;
270 struct comedi_async *async = s->async;
271 struct usbduxfast_private *devpriv = dev->private;
7c88f9f4
HS
272
273 /* exit if not running a command, do not resubmit urb */
274 if (!devpriv->ai_cmd_running)
f47c697d 275 return;
f47c697d 276
f47c697d
BP
277 switch (urb->status) {
278 case 0:
7c88f9f4 279 usbduxfast_ai_handle_urb(dev, s, urb);
f47c697d
BP
280 break;
281
f47c697d
BP
282 case -ECONNRESET:
283 case -ENOENT:
284 case -ESHUTDOWN:
285 case -ECONNABORTED:
7c88f9f4 286 /* after an unlink command, unplug, ... etc */
f8eb27e0 287 async->events |= COMEDI_CB_ERROR;
7c88f9f4 288 break;
f47c697d
BP
289
290 default:
7c88f9f4 291 /* a real error */
42f4acdf
HS
292 dev_err(dev->class_dev,
293 "non-zero urb status received in ai intr context: %d\n",
294 urb->status);
f8eb27e0 295 async->events |= COMEDI_CB_ERROR;
7c88f9f4 296 break;
f47c697d
BP
297 }
298
4e8ad0dc 299 /*
7c88f9f4
HS
300 * comedi_handle_events() cannot be used in this driver. The (*cancel)
301 * operation would unlink the urb.
4e8ad0dc 302 */
7c88f9f4 303 if (async->events & COMEDI_CB_CANCEL_MASK)
da63c39c 304 usbduxfast_ai_stop(dev, 0);
7c88f9f4
HS
305
306 comedi_event(dev, s);
f47c697d
BP
307}
308
ebe9f1cf 309static int usbduxfast_submit_urb(struct comedi_device *dev)
f47c697d 310{
0a92de24 311 struct usb_device *usb = comedi_to_usb_dev(dev);
da63c39c 312 struct usbduxfast_private *devpriv = dev->private;
4e8ad0dc 313 int ret;
f47c697d 314
da58c263 315 usb_fill_bulk_urb(devpriv->urb, usb, usb_rcvbulkpipe(usb, BULKINEP),
ef8e0840 316 devpriv->inbuf, SIZEINBUF,
da63c39c 317 usbduxfast_ai_interrupt, dev);
f47c697d 318
da58c263 319 ret = usb_submit_urb(devpriv->urb, GFP_ATOMIC);
4e8ad0dc 320 if (ret) {
106af997 321 dev_err(dev->class_dev, "usb_submit_urb error %d\n", ret);
4e8ad0dc 322 return ret;
f47c697d
BP
323 }
324 return 0;
325}
326
99555fc2
HS
327static int usbduxfast_ai_check_chanlist(struct comedi_device *dev,
328 struct comedi_subdevice *s,
329 struct comedi_cmd *cmd)
330{
331 unsigned int gain0 = CR_RANGE(cmd->chanlist[0]);
332 int i;
333
db1876ff
HS
334 if (cmd->chanlist_len > 3 && cmd->chanlist_len != 16) {
335 dev_err(dev->class_dev, "unsupported combination of channels\n");
336 return -EINVAL;
337 }
338
99555fc2
HS
339 for (i = 0; i < cmd->chanlist_len; ++i) {
340 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
341 unsigned int gain = CR_RANGE(cmd->chanlist[i]);
342
343 if (chan != i) {
344 dev_err(dev->class_dev,
345 "channels are not consecutive\n");
346 return -EINVAL;
347 }
348 if (gain != gain0 && cmd->chanlist_len > 3) {
349 dev_err(dev->class_dev,
350 "gain must be the same for all channels\n");
351 return -EINVAL;
352 }
353 }
354 return 0;
355}
356
71b5f4f1 357static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
0a85b6f0
MT
358 struct comedi_subdevice *s,
359 struct comedi_cmd *cmd)
f47c697d 360{
27020ffe 361 int err = 0;
c748debc
HS
362 unsigned int steps;
363 unsigned int arg;
4e8ad0dc 364
27020ffe 365 /* Step 1 : check if triggers are trivially valid */
f47c697d 366
f53398eb 367 err |= comedi_check_trigger_src(&cmd->start_src,
27020ffe 368 TRIG_NOW | TRIG_EXT | TRIG_INT);
fe0d96bf
HS
369 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
370 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
f53398eb
IA
371 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
372 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
f47c697d
BP
373
374 if (err)
375 return 1;
376
27020ffe 377 /* Step 2a : make sure trigger sources are unique */
f47c697d 378
f53398eb 379 err |= comedi_check_trigger_is_unique(cmd->start_src);
f53398eb 380 err |= comedi_check_trigger_is_unique(cmd->stop_src);
27020ffe
HS
381
382 /* Step 2b : and mutually compatible */
f47c697d 383
f47c697d
BP
384 if (err)
385 return 2;
386
9309c477 387 /* Step 3: check if arguments are trivially valid */
f47c697d 388
f53398eb 389 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
f47c697d 390
4e8ad0dc 391 if (!cmd->chanlist_len)
9309c477 392 err |= -EINVAL;
4e8ad0dc 393
d636f87d
HS
394 /* external start trigger is only valid for 1 or 16 channels */
395 if (cmd->start_src == TRIG_EXT &&
396 cmd->chanlist_len != 1 && cmd->chanlist_len != 16)
397 err |= -EINVAL;
398
f53398eb
IA
399 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
400 cmd->chanlist_len);
f47c697d 401
c748debc
HS
402 /*
403 * Validate the conversion timing:
404 * for 1 channel the timing in 30MHz "steps" is:
405 * steps <= MAX_SAMPLING_PERIOD
406 * for all other chanlist_len it is:
407 * MIN_SAMPLING_PERIOD <= steps <= MAX_SAMPLING_PERIOD
408 */
409 steps = (cmd->convert_arg * 30) / 1000;
410 if (cmd->chanlist_len != 1)
411 err |= comedi_check_trigger_arg_min(&steps,
412 MIN_SAMPLING_PERIOD);
413 err |= comedi_check_trigger_arg_max(&steps, MAX_SAMPLING_PERIOD);
414 arg = (steps * 1000) / 30;
415 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
f47c697d 416
fe0d96bf 417 if (cmd->stop_src == TRIG_COUNT)
f53398eb 418 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
fe0d96bf 419 else /* TRIG_NONE */
f53398eb 420 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
f47c697d
BP
421
422 if (err)
423 return 3;
424
99555fc2
HS
425 /* Step 4: fix up any arguments */
426
427 /* Step 5: check channel list if it exists */
428 if (cmd->chanlist && cmd->chanlist_len > 0)
429 err |= usbduxfast_ai_check_chanlist(dev, s, cmd);
430 if (err)
431 return 5;
f47c697d
BP
432
433 return 0;
f47c697d
BP
434}
435
71b5f4f1 436static int usbduxfast_ai_inttrig(struct comedi_device *dev,
0a85b6f0 437 struct comedi_subdevice *s,
95194590 438 unsigned int trig_num)
f47c697d 439{
7aa41c3c 440 struct usbduxfast_private *devpriv = dev->private;
95194590 441 struct comedi_cmd *cmd = &s->async->cmd;
f47c697d 442 int ret;
4e8ad0dc 443
95194590
HS
444 if (trig_num != cmd->start_arg)
445 return -EINVAL;
446
27a90695 447 mutex_lock(&devpriv->mut);
f47c697d 448
7aa41c3c
HS
449 if (!devpriv->ai_cmd_running) {
450 devpriv->ai_cmd_running = 1;
ebe9f1cf 451 ret = usbduxfast_submit_urb(dev);
f47c697d 452 if (ret < 0) {
106af997 453 dev_err(dev->class_dev, "urbSubmit: err=%d\n", ret);
7aa41c3c 454 devpriv->ai_cmd_running = 0;
27a90695 455 mutex_unlock(&devpriv->mut);
f47c697d
BP
456 return ret;
457 }
458 s->async->inttrig = NULL;
459 } else {
106af997 460 dev_err(dev->class_dev, "ai is already running\n");
f47c697d 461 }
27a90695 462 mutex_unlock(&devpriv->mut);
f47c697d
BP
463 return 1;
464}
465
0a85b6f0
MT
466static int usbduxfast_ai_cmd(struct comedi_device *dev,
467 struct comedi_subdevice *s)
f47c697d 468{
7aa41c3c 469 struct usbduxfast_private *devpriv = dev->private;
ea6d0d4c 470 struct comedi_cmd *cmd = &s->async->cmd;
99555fc2
HS
471 unsigned int rngmask = 0xff;
472 int j, ret;
f47c697d
BP
473 long steps, steps_tmp;
474
27a90695 475 mutex_lock(&devpriv->mut);
7aa41c3c 476 if (devpriv->ai_cmd_running) {
7b0fc5ba
HS
477 ret = -EBUSY;
478 goto cmd_exit;
f47c697d 479 }
f47c697d 480
4e8ad0dc
MK
481 /*
482 * ignore the first buffers from the device if there
483 * is an error condition
484 */
7aa41c3c 485 devpriv->ignore = PACKETS_TO_IGNORE;
f47c697d 486
fe0d96bf 487 steps = (cmd->convert_arg * 30) / 1000;
4e8ad0dc 488
f47c697d 489 switch (cmd->chanlist_len) {
f47c697d 490 case 1:
4e8ad0dc
MK
491 /*
492 * one channel
493 */
494
f47c697d
BP
495 if (CR_RANGE(cmd->chanlist[0]) > 0)
496 rngmask = 0xff - 0x04;
497 else
498 rngmask = 0xff;
499
4e8ad0dc
MK
500 /*
501 * for external trigger: looping in this state until
502 * the RDY0 pin becomes zero
503 */
504
505 /* we loop here until ready has been set */
506 if (cmd->start_src == TRIG_EXT) {
507 /* branch back to state 0 */
4e8ad0dc 508 /* deceision state w/o data */
4e8ad0dc 509 /* RDY0 = 0 */
17fdeba0 510 usbduxfast_cmd_data(dev, 0, 0x01, 0x01, rngmask, 0x00);
4e8ad0dc 511 } else { /* we just proceed to state 1 */
17fdeba0 512 usbduxfast_cmd_data(dev, 0, 0x01, 0x00, rngmask, 0x00);
f47c697d
BP
513 }
514
515 if (steps < MIN_SAMPLING_PERIOD) {
4e8ad0dc 516 /* for fast single channel aqu without mux */
f47c697d 517 if (steps <= 1) {
4e8ad0dc
MK
518 /*
519 * we just stay here at state 1 and rexecute
520 * the same state this gives us 30MHz sampling
521 * rate
522 */
523
524 /* branch back to state 1 */
4e8ad0dc 525 /* deceision state with data */
4e8ad0dc 526 /* doesn't matter */
17fdeba0
HS
527 usbduxfast_cmd_data(dev, 1,
528 0x89, 0x03, rngmask, 0xff);
f47c697d 529 } else {
4e8ad0dc
MK
530 /*
531 * we loop through two states: data and delay
532 * max rate is 15MHz
533 */
4e8ad0dc 534 /* data */
4e8ad0dc 535 /* doesn't matter */
17fdeba0
HS
536 usbduxfast_cmd_data(dev, 1, steps - 1,
537 0x02, rngmask, 0x00);
538
4e8ad0dc 539 /* branch back to state 1 */
4e8ad0dc 540 /* deceision state w/o data */
4e8ad0dc 541 /* doesn't matter */
17fdeba0
HS
542 usbduxfast_cmd_data(dev, 2,
543 0x09, 0x01, rngmask, 0xff);
f47c697d
BP
544 }
545 } else {
4e8ad0dc
MK
546 /*
547 * we loop through 3 states: 2x delay and 1x data
548 * this gives a min sampling rate of 60kHz
549 */
f47c697d 550
4e8ad0dc 551 /* we have 1 state with duration 1 */
f47c697d
BP
552 steps = steps - 1;
553
4e8ad0dc 554 /* do the first part of the delay */
17fdeba0
HS
555 usbduxfast_cmd_data(dev, 1,
556 steps / 2, 0x00, rngmask, 0x00);
4e8ad0dc
MK
557
558 /* and the second part */
17fdeba0
HS
559 usbduxfast_cmd_data(dev, 2, steps - steps / 2,
560 0x00, rngmask, 0x00);
4e8ad0dc
MK
561
562 /* get the data and branch back */
563
564 /* branch back to state 1 */
4e8ad0dc 565 /* deceision state w data */
4e8ad0dc 566 /* doesn't matter */
17fdeba0
HS
567 usbduxfast_cmd_data(dev, 3,
568 0x09, 0x03, rngmask, 0xff);
f47c697d
BP
569 }
570 break;
571
572 case 2:
4e8ad0dc
MK
573 /*
574 * two channels
575 * commit data to the FIFO
576 */
577
f47c697d
BP
578 if (CR_RANGE(cmd->chanlist[0]) > 0)
579 rngmask = 0xff - 0x04;
580 else
581 rngmask = 0xff;
f47c697d 582
4e8ad0dc 583 /* data */
17fdeba0 584 usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
4e8ad0dc
MK
585
586 /* we have 1 state with duration 1: state 0 */
f47c697d
BP
587 steps_tmp = steps - 1;
588
589 if (CR_RANGE(cmd->chanlist[1]) > 0)
590 rngmask = 0xff - 0x04;
591 else
592 rngmask = 0xff;
4e8ad0dc
MK
593
594 /* do the first part of the delay */
4e8ad0dc 595 /* count */
17fdeba0
HS
596 usbduxfast_cmd_data(dev, 1, steps_tmp / 2,
597 0x00, 0xfe & rngmask, 0x00);
4e8ad0dc
MK
598
599 /* and the second part */
17fdeba0
HS
600 usbduxfast_cmd_data(dev, 2, steps_tmp - steps_tmp / 2,
601 0x00, rngmask, 0x00);
4e8ad0dc 602
4e8ad0dc 603 /* data */
17fdeba0 604 usbduxfast_cmd_data(dev, 3, 0x01, 0x02, rngmask, 0x00);
4e8ad0dc
MK
605
606 /*
607 * we have 2 states with duration 1: step 6 and
608 * the IDLE state
609 */
f47c697d
BP
610 steps_tmp = steps - 2;
611
612 if (CR_RANGE(cmd->chanlist[0]) > 0)
613 rngmask = 0xff - 0x04;
614 else
615 rngmask = 0xff;
4e8ad0dc
MK
616
617 /* do the first part of the delay */
4e8ad0dc 618 /* reset */
17fdeba0
HS
619 usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
620 0x00, (0xff - 0x02) & rngmask, 0x00);
4e8ad0dc
MK
621
622 /* and the second part */
17fdeba0
HS
623 usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
624 0x00, rngmask, 0x00);
625
626 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
f47c697d
BP
627 break;
628
629 case 3:
4e8ad0dc
MK
630 /*
631 * three channels
632 */
f47c697d 633 for (j = 0; j < 1; j++) {
17fdeba0
HS
634 int index = j * 2;
635
f47c697d
BP
636 if (CR_RANGE(cmd->chanlist[j]) > 0)
637 rngmask = 0xff - 0x04;
638 else
639 rngmask = 0xff;
4e8ad0dc
MK
640 /*
641 * commit data to the FIFO and do the first part
642 * of the delay
643 */
4e8ad0dc 644 /* data */
4e8ad0dc 645 /* no change */
17fdeba0
HS
646 usbduxfast_cmd_data(dev, index, steps / 2,
647 0x02, rngmask, 0x00);
f47c697d
BP
648
649 if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
650 rngmask = 0xff - 0x04;
651 else
652 rngmask = 0xff;
4e8ad0dc
MK
653
654 /* do the second part of the delay */
4e8ad0dc 655 /* no data */
4e8ad0dc 656 /* count */
17fdeba0
HS
657 usbduxfast_cmd_data(dev, index + 1, steps - steps / 2,
658 0x00, 0xfe & rngmask, 0x00);
f47c697d
BP
659 }
660
4e8ad0dc 661 /* 2 steps with duration 1: the idele step and step 6: */
f47c697d 662 steps_tmp = steps - 2;
4e8ad0dc
MK
663
664 /* commit data to the FIFO and do the first part of the delay */
4e8ad0dc 665 /* data */
17fdeba0
HS
666 usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
667 0x02, rngmask, 0x00);
f47c697d
BP
668
669 if (CR_RANGE(cmd->chanlist[0]) > 0)
670 rngmask = 0xff - 0x04;
671 else
672 rngmask = 0xff;
4e8ad0dc
MK
673
674 /* do the second part of the delay */
4e8ad0dc 675 /* no data */
4e8ad0dc 676 /* reset */
17fdeba0
HS
677 usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
678 0x00, (0xff - 0x02) & rngmask, 0x00);
4e8ad0dc 679
17fdeba0 680 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
99284f25 681 break;
f47c697d
BP
682
683 case 16:
684 if (CR_RANGE(cmd->chanlist[0]) > 0)
685 rngmask = 0xff - 0x04;
686 else
687 rngmask = 0xff;
4e8ad0dc
MK
688
689 if (cmd->start_src == TRIG_EXT) {
690 /*
691 * we loop here until ready has been set
692 */
693
694 /* branch back to state 0 */
4e8ad0dc 695 /* deceision state w/o data */
4e8ad0dc 696 /* reset */
4e8ad0dc 697 /* RDY0 = 0 */
17fdeba0
HS
698 usbduxfast_cmd_data(dev, 0, 0x01, 0x01,
699 (0xff - 0x02) & rngmask, 0x00);
4e8ad0dc
MK
700 } else {
701 /*
702 * we just proceed to state 1
703 */
704
705 /* 30us reset pulse */
4e8ad0dc 706 /* reset */
17fdeba0
HS
707 usbduxfast_cmd_data(dev, 0, 0xff, 0x00,
708 (0xff - 0x02) & rngmask, 0x00);
f47c697d
BP
709 }
710
4e8ad0dc 711 /* commit data to the FIFO */
4e8ad0dc 712 /* data */
17fdeba0 713 usbduxfast_cmd_data(dev, 1, 0x01, 0x02, rngmask, 0x00);
f47c697d 714
4e8ad0dc 715 /* we have 2 states with duration 1 */
f47c697d
BP
716 steps = steps - 2;
717
4e8ad0dc 718 /* do the first part of the delay */
17fdeba0
HS
719 usbduxfast_cmd_data(dev, 2, steps / 2,
720 0x00, 0xfe & rngmask, 0x00);
4e8ad0dc
MK
721
722 /* and the second part */
17fdeba0
HS
723 usbduxfast_cmd_data(dev, 3, steps - steps / 2,
724 0x00, rngmask, 0x00);
4e8ad0dc
MK
725
726 /* branch back to state 1 */
4e8ad0dc 727 /* deceision state w/o data */
4e8ad0dc 728 /* doesn't matter */
17fdeba0 729 usbduxfast_cmd_data(dev, 4, 0x09, 0x01, rngmask, 0xff);
f47c697d
BP
730
731 break;
f47c697d
BP
732 }
733
4e8ad0dc 734 /* 0 means that the AD commands are sent */
7b0fc5ba
HS
735 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
736 if (ret < 0)
737 goto cmd_exit;
71cf2b4a 738
f47c697d 739 if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
4e8ad0dc 740 /* enable this acquisition operation */
7aa41c3c 741 devpriv->ai_cmd_running = 1;
ebe9f1cf 742 ret = usbduxfast_submit_urb(dev);
f47c697d 743 if (ret < 0) {
7aa41c3c 744 devpriv->ai_cmd_running = 0;
4e8ad0dc 745 /* fixme: unlink here?? */
7b0fc5ba 746 goto cmd_exit;
f47c697d
BP
747 }
748 s->async->inttrig = NULL;
95194590 749 } else { /* TRIG_INT */
f47c697d
BP
750 s->async->inttrig = usbduxfast_ai_inttrig;
751 }
7b0fc5ba
HS
752
753cmd_exit:
27a90695 754 mutex_unlock(&devpriv->mut);
f47c697d 755
7b0fc5ba 756 return ret;
f47c697d
BP
757}
758
4e8ad0dc
MK
759/*
760 * Mode 0 is used to get a single conversion on demand.
761 */
71b5f4f1 762static int usbduxfast_ai_insn_read(struct comedi_device *dev,
0a85b6f0 763 struct comedi_subdevice *s,
dabf2aa3
HS
764 struct comedi_insn *insn,
765 unsigned int *data)
f47c697d 766{
0a92de24 767 struct usb_device *usb = comedi_to_usb_dev(dev);
7aa41c3c 768 struct usbduxfast_private *devpriv = dev->private;
dabf2aa3
HS
769 unsigned int chan = CR_CHAN(insn->chanspec);
770 unsigned int range = CR_RANGE(insn->chanspec);
26961546 771 u8 rngmask = range ? (0xff - 0x04) : 0xff;
f47c697d 772 int i, j, n, actual_length;
dabf2aa3 773 int ret;
ba6205d6 774
27a90695 775 mutex_lock(&devpriv->mut);
dabf2aa3 776
7aa41c3c 777 if (devpriv->ai_cmd_running) {
0a00ab99 778 dev_err(dev->class_dev,
106af997 779 "ai_insn_read not possible, async cmd is running\n");
27a90695 780 mutex_unlock(&devpriv->mut);
f47c697d
BP
781 return -EBUSY;
782 }
f47c697d 783
dabf2aa3 784 /* set command for the first channel */
4e8ad0dc
MK
785
786 /* commit data to the FIFO */
4e8ad0dc 787 /* data */
17fdeba0 788 usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
4e8ad0dc
MK
789
790 /* do the first part of the delay */
17fdeba0
HS
791 usbduxfast_cmd_data(dev, 1, 0x0c, 0x00, 0xfe & rngmask, 0x00);
792 usbduxfast_cmd_data(dev, 2, 0x01, 0x00, 0xfe & rngmask, 0x00);
793 usbduxfast_cmd_data(dev, 3, 0x01, 0x00, 0xfe & rngmask, 0x00);
794 usbduxfast_cmd_data(dev, 4, 0x01, 0x00, 0xfe & rngmask, 0x00);
4e8ad0dc
MK
795
796 /* second part */
17fdeba0
HS
797 usbduxfast_cmd_data(dev, 5, 0x0c, 0x00, rngmask, 0x00);
798 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
f47c697d 799
dabf2aa3
HS
800 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
801 if (ret < 0) {
27a90695 802 mutex_unlock(&devpriv->mut);
dabf2aa3 803 return ret;
f47c697d 804 }
ba6205d6 805
f47c697d 806 for (i = 0; i < PACKETS_TO_IGNORE; i++) {
dabf2aa3 807 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
ef8e0840 808 devpriv->inbuf, SIZEINBUF,
88676359 809 &actual_length, 10000);
dabf2aa3 810 if (ret < 0) {
106af997 811 dev_err(dev->class_dev, "insn timeout, no data\n");
27a90695 812 mutex_unlock(&devpriv->mut);
dabf2aa3 813 return ret;
f47c697d
BP
814 }
815 }
dabf2aa3 816
f47c697d 817 for (i = 0; i < insn->n;) {
dabf2aa3 818 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
ef8e0840 819 devpriv->inbuf, SIZEINBUF,
88676359 820 &actual_length, 10000);
dabf2aa3
HS
821 if (ret < 0) {
822 dev_err(dev->class_dev, "insn data error: %d\n", ret);
27a90695 823 mutex_unlock(&devpriv->mut);
dabf2aa3 824 return ret;
f47c697d 825 }
26961546 826 n = actual_length / sizeof(u16);
f47c697d 827 if ((n % 16) != 0) {
106af997 828 dev_err(dev->class_dev, "insn data packet corrupted\n");
27a90695 829 mutex_unlock(&devpriv->mut);
f47c697d
BP
830 return -EINVAL;
831 }
832 for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
26961546 833 data[i] = ((u16 *)(devpriv->inbuf))[j];
f47c697d
BP
834 i++;
835 }
836 }
dabf2aa3 837
27a90695 838 mutex_unlock(&devpriv->mut);
dabf2aa3
HS
839
840 return insn->n;
f47c697d
BP
841}
842
1b4997e6 843static int usbduxfast_upload_firmware(struct comedi_device *dev,
f9eb8a3b
HS
844 const u8 *data, size_t size,
845 unsigned long context)
f47c697d 846{
0a92de24 847 struct usb_device *usb = comedi_to_usb_dev(dev);
26961546 848 u8 *buf;
fbe38a8b 849 unsigned char *tmp;
106af997 850 int ret;
f47c697d 851
f9eb8a3b 852 if (!data)
81874ff7 853 return 0;
f47c697d 854
f9eb8a3b 855 if (size > FIRMWARE_MAX_LEN) {
106af997 856 dev_err(dev->class_dev, "firmware binary too large for FX2\n");
81874ff7
BP
857 return -ENOMEM;
858 }
4e8ad0dc 859
81874ff7 860 /* we generate a local buffer for the firmware */
f9eb8a3b 861 buf = kmemdup(data, size, GFP_KERNEL);
1b4997e6 862 if (!buf)
81874ff7 863 return -ENOMEM;
f47c697d 864
fbe38a8b
HS
865 /* we need a malloc'ed buffer for usb_control_msg() */
866 tmp = kmalloc(1, GFP_KERNEL);
867 if (!tmp) {
868 kfree(buf);
869 return -ENOMEM;
870 }
871
872 /* stop the current firmware on the device */
873 *tmp = 1; /* 7f92 to one */
874 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
875 USBDUXFASTSUB_FIRMWARE,
876 VENDOR_DIR_OUT,
877 USBDUXFASTSUB_CPUCS, 0x0000,
878 tmp, 1,
879 EZTIMEOUT);
81874ff7 880 if (ret < 0) {
106af997 881 dev_err(dev->class_dev, "can not stop firmware\n");
1b4997e6 882 goto done;
81874ff7 883 }
f47c697d 884
fbe38a8b
HS
885 /* upload the new firmware to the device */
886 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
887 USBDUXFASTSUB_FIRMWARE,
888 VENDOR_DIR_OUT,
889 0, 0x0000,
f9eb8a3b 890 buf, size,
fbe38a8b 891 EZTIMEOUT);
81874ff7 892 if (ret < 0) {
106af997 893 dev_err(dev->class_dev, "firmware upload failed\n");
1b4997e6 894 goto done;
f47c697d 895 }
fbe38a8b
HS
896
897 /* start the new firmware on the device */
898 *tmp = 0; /* 7f92 to zero */
899 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
900 USBDUXFASTSUB_FIRMWARE,
901 VENDOR_DIR_OUT,
902 USBDUXFASTSUB_CPUCS, 0x0000,
903 tmp, 1,
904 EZTIMEOUT);
1b4997e6 905 if (ret < 0)
106af997 906 dev_err(dev->class_dev, "can not start firmware\n");
1b4997e6
HS
907
908done:
fbe38a8b 909 kfree(tmp);
1b4997e6
HS
910 kfree(buf);
911 return ret;
f47c697d
BP
912}
913
2d719c9c
HS
914static int usbduxfast_auto_attach(struct comedi_device *dev,
915 unsigned long context_unused)
f47c697d 916{
2d719c9c 917 struct usb_interface *intf = comedi_to_usb_interface(dev);
0a92de24 918 struct usb_device *usb = comedi_to_usb_dev(dev);
2d719c9c 919 struct usbduxfast_private *devpriv;
42293db0 920 struct comedi_subdevice *s;
6742c0af 921 int ret;
f47c697d 922
e4a8ecc0 923 if (usb->speed != USB_SPEED_HIGH) {
106af997 924 dev_err(dev->class_dev,
0a00ab99 925 "This driver needs USB 2.0 to operate. Aborting...\n");
88676359 926 return -ENODEV;
f47c697d 927 }
64bf88bf 928
0bdab509 929 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2d719c9c
HS
930 if (!devpriv)
931 return -ENOMEM;
f47c697d 932
27a90695 933 mutex_init(&devpriv->mut);
a35fd8a1 934 usb_set_intfdata(intf, devpriv);
f47c697d 935
5659e24a
HS
936 devpriv->duxbuf = kmalloc(SIZEOFDUXBUF, GFP_KERNEL);
937 if (!devpriv->duxbuf)
88676359 938 return -ENOMEM;
ca88c09f 939
a4f2e0f9 940 ret = usb_set_interface(usb,
01245e7a 941 intf->altsetting->desc.bInterfaceNumber, 1);
2d719c9c 942 if (ret < 0) {
106af997 943 dev_err(dev->class_dev,
ca88c09f 944 "could not switch to alternate setting 1\n");
88676359 945 return -ENODEV;
f47c697d 946 }
ca88c09f 947
da58c263 948 devpriv->urb = usb_alloc_urb(0, GFP_KERNEL);
1a55f38d 949 if (!devpriv->urb)
88676359 950 return -ENOMEM;
ca88c09f 951
ef8e0840
HS
952 devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL);
953 if (!devpriv->inbuf)
88676359 954 return -ENOMEM;
ca88c09f 955
f9eb8a3b
HS
956 ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
957 usbduxfast_upload_firmware, 0);
958 if (ret)
6742c0af 959 return ret;
6742c0af 960
42293db0
HS
961 ret = comedi_alloc_subdevices(dev, 1);
962 if (ret)
963 return ret;
964
965 /* Analog Input subdevice */
966 s = &dev->subdevices[0];
967 dev->read_subdev = s;
968 s->type = COMEDI_SUBD_AI;
969 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
970 s->n_chan = 16;
971 s->maxdata = 0x1000; /* 12-bit + 1 overflow bit */
972 s->range_table = &range_usbduxfast_ai_range;
973 s->insn_read = usbduxfast_ai_insn_read;
974 s->len_chanlist = s->n_chan;
975 s->do_cmdtest = usbduxfast_ai_cmdtest;
976 s->do_cmd = usbduxfast_ai_cmd;
977 s->cancel = usbduxfast_ai_cancel;
978
979 return 0;
2d719c9c
HS
980}
981
982static void usbduxfast_detach(struct comedi_device *dev)
983{
a71a65b1 984 struct usb_interface *intf = comedi_to_usb_interface(dev);
2d719c9c
HS
985 struct usbduxfast_private *devpriv = dev->private;
986
38bf7ba8
HS
987 if (!devpriv)
988 return;
989
27a90695 990 mutex_lock(&devpriv->mut);
38bf7ba8 991
a71a65b1 992 usb_set_intfdata(intf, NULL);
38bf7ba8 993
da58c263 994 if (devpriv->urb) {
38bf7ba8 995 /* waits until a running transfer is over */
da58c263 996 usb_kill_urb(devpriv->urb);
38bf7ba8 997
ef8e0840 998 kfree(devpriv->inbuf);
da58c263 999 usb_free_urb(devpriv->urb);
2d719c9c 1000 }
38bf7ba8 1001
5659e24a 1002 kfree(devpriv->duxbuf);
38bf7ba8 1003
27a90695 1004 mutex_unlock(&devpriv->mut);
2d719c9c
HS
1005}
1006
1007static struct comedi_driver usbduxfast_driver = {
1008 .driver_name = "usbduxfast",
1009 .module = THIS_MODULE,
1010 .auto_attach = usbduxfast_auto_attach,
1011 .detach = usbduxfast_detach,
1012};
1013
1014static int usbduxfast_usb_probe(struct usb_interface *intf,
1015 const struct usb_device_id *id)
1016{
a35fd8a1 1017 return comedi_usb_auto_config(intf, &usbduxfast_driver, 0);
f47c697d
BP
1018}
1019
4c8ba916 1020static const struct usb_device_id usbduxfast_usb_table[] = {
4e8ad0dc 1021 /* { USB_DEVICE(0x4b4, 0x8613) }, testing */
4c8ba916
HS
1022 { USB_DEVICE(0x13d8, 0x0010) }, /* real ID */
1023 { USB_DEVICE(0x13d8, 0x0011) }, /* real ID */
1024 { }
f47c697d 1025};
4c8ba916 1026MODULE_DEVICE_TABLE(usb, usbduxfast_usb_table);
f47c697d 1027
cb9513ad 1028static struct usb_driver usbduxfast_usb_driver = {
4c8ba916
HS
1029 .name = "usbduxfast",
1030 .probe = usbduxfast_usb_probe,
0c4ab671 1031 .disconnect = comedi_usb_auto_unconfig,
4c8ba916 1032 .id_table = usbduxfast_usb_table,
f47c697d 1033};
cb9513ad 1034module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver);
f47c697d 1035
4c8ba916
HS
1036MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1037MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com");
f47c697d 1038MODULE_LICENSE("GPL");
e74f7fc5 1039MODULE_FIRMWARE(FIRMWARE);
This page took 0.962761 seconds and 5 git commands to generate.