blob: 10f94ec345360681ec11316d5fda6c48581afde8 [file] [log] [blame]
Bernd Porrf47c6972008-11-14 14:49:34 -08001/*
Bernd Porr533de0f2014-10-10 20:35:11 +01002 * Copyright (C) 2004-2014 Bernd Porr, mail@berndporr.me.uk
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +01003 *
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.
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010013 */
Bernd Porrf47c6972008-11-14 14:49:34 -080014
15/*
Bernd Porr533de0f2014-10-10 20:35:11 +010016 * Driver: usbduxfast
17 * Description: University of Stirling USB DAQ & INCITE Technology Limited
Ian Abbott504a1aa2015-01-05 17:55:11 +000018 * Devices: [ITL] USB-DUX-FAST (usbduxfast)
Bernd Porr533de0f2014-10-10 20:35:11 +010019 * Author: Bernd Porr <mail@berndporr.me.uk>
20 * Updated: 10 Oct 2014
21 * Status: stable
22 */
23
24/*
Bernd Porrf47c6972008-11-14 14:49:34 -080025 * 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.
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010037 * Added insn command basically for testing. Sample rate is
38 * 1MHz/16ch=62.5kHz
Bernd Porrf47c6972008-11-14 14:49:34 -080039 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
40 * 0.99a: added external trigger.
Bernd Porr6742c0a2008-12-08 23:30:13 +000041 * 1.00: added firmware kernel request to the driver which fixed
42 * udev coldplug problem
Bernd Porrf47c6972008-11-14 14:49:34 -080043 */
44
45#include <linux/kernel.h>
46#include <linux/module.h>
Bernd Porrf47c6972008-11-14 14:49:34 -080047#include <linux/slab.h>
48#include <linux/input.h>
Bernd Porrf47c6972008-11-14 14:49:34 -080049#include <linux/fcntl.h>
50#include <linux/compiler.h>
Ian Abbottd3f83952015-01-27 17:49:06 +000051#include "../comedi_usb.h"
Bernd Porrf47c6972008-11-14 14:49:34 -080052
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010053/*
54 * timeout for the USB-transfer
55 */
56#define EZTIMEOUT 30
Bernd Porrf47c6972008-11-14 14:49:34 -080057
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010058/*
59 * constants for "firmware" upload and download
60 */
Tim Gardnere74f7fc2012-08-16 11:09:28 -060061#define FIRMWARE "usbduxfast_firmware.bin"
H Hartley Sweetendcd29f52013-05-14 13:40:02 -070062#define FIRMWARE_MAX_LEN 0x2000
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010063#define USBDUXFASTSUB_FIRMWARE 0xA0
64#define VENDOR_DIR_IN 0xC0
65#define VENDOR_DIR_OUT 0x40
Bernd Porrf47c6972008-11-14 14:49:34 -080066
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010067/*
Uwe Kleine-Königf69b0d62010-07-12 17:15:46 +020068 * internal addresses of the 8051 processor
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010069 */
70#define USBDUXFASTSUB_CPUCS 0xE600
Bernd Porrf47c6972008-11-14 14:49:34 -080071
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010072/*
73 * max lenghth of the transfer-buffer for software upload
74 */
75#define TB_LEN 0x2000
Bernd Porrf47c6972008-11-14 14:49:34 -080076
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010077/*
78 * input endpoint number
79 */
80#define BULKINEP 6
Bernd Porrf47c6972008-11-14 14:49:34 -080081
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010082/*
83 * endpoint for the A/D channellist: bulk OUT
84 */
85#define CHANNELLISTEP 4
Bernd Porrf47c6972008-11-14 14:49:34 -080086
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010087/*
88 * number of channels
89 */
90#define NUMCHANNELS 32
Bernd Porrf47c6972008-11-14 14:49:34 -080091
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010092/*
93 * size of the waveform descriptor
94 */
95#define WAVESIZE 0x20
Bernd Porrf47c6972008-11-14 14:49:34 -080096
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +010097/*
98 * size of one A/D value
99 */
H Hartley Sweeten26961542015-08-24 10:13:57 -0700100#define SIZEADIN (sizeof(s16))
Bernd Porrf47c6972008-11-14 14:49:34 -0800101
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100102/*
103 * size of the input-buffer IN BYTES
104 */
105#define SIZEINBUF 512
Bernd Porrf47c6972008-11-14 14:49:34 -0800106
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100107/*
108 * 16 bytes
109 */
110#define SIZEINSNBUF 512
Bernd Porrf47c6972008-11-14 14:49:34 -0800111
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100112/*
113 * size of the buffer for the dux commands in bytes
114 */
H Hartley Sweeten5659e242013-05-14 13:36:47 -0700115#define SIZEOFDUXBUF 256
Bernd Porrf47c6972008-11-14 14:49:34 -0800116
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100117/*
118 * number of in-URBs which receive the data: min=5
119 */
120#define NUMOFINBUFFERSHIGH 10
Bernd Porrf47c6972008-11-14 14:49:34 -0800121
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100122/*
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100123 * 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
Bernd Porrf47c6972008-11-14 14:49:34 -0800129
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100130/*
131 * max number of 1/30MHz delay steps
132 */
133#define MAX_SAMPLING_PERIOD 500
Bernd Porrf47c6972008-11-14 14:49:34 -0800134
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100135/*
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
Bernd Porrf47c6972008-11-14 14:49:34 -0800140
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100141/*
142 * comedi constants
143 */
Bill Pemberton9ced1de2009-03-16 22:05:31 -0400144static const struct comedi_lrange range_usbduxfast_ai_range = {
H Hartley Sweeten67b3b782013-12-09 17:31:25 -0700145 2, {
146 BIP_RANGE(0.75),
147 BIP_RANGE(0.5)
148 }
Bernd Porrf47c6972008-11-14 14:49:34 -0800149};
150
151/*
152 * private structure of one subdevice
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100153 *
154 * this is the structure which holds all the data of this driver
155 * one sub device just now: A/D
Bernd Porrf47c6972008-11-14 14:49:34 -0800156 */
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700157struct usbduxfast_private {
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700158 struct urb *urb; /* BULK-transfer handling: urb */
H Hartley Sweeten26961542015-08-24 10:13:57 -0700159 u8 *duxbuf;
160 s8 *inbuf;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100161 short int ai_cmd_running; /* asynchronous command is running */
H Hartley Sweeten24b83782015-08-24 10:13:58 -0700162 int ignore; /* counter which ignores the first buffers */
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200163 struct mutex mut;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100164};
Bernd Porrf47c6972008-11-14 14:49:34 -0800165
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100166/*
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100167 * bulk transfers to usbduxfast
168 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800169#define SENDADCOMMANDS 0
170#define SENDINITEP6 1
171
H Hartley Sweeten665ff8d2013-05-14 13:37:38 -0700172static int usbduxfast_send_cmd(struct comedi_device *dev, int cmd_type)
Bernd Porrf47c6972008-11-14 14:49:34 -0800173{
H Hartley Sweeten0a92de22013-05-20 14:20:30 -0700174 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700175 struct usbduxfast_private *devpriv = dev->private;
H Hartley Sweeten665ff8d2013-05-14 13:37:38 -0700176 int nsent;
177 int ret;
Mariusz Kozlowski0a3b8b62009-02-16 21:31:27 +0100178
H Hartley Sweeten5659e242013-05-14 13:36:47 -0700179 devpriv->duxbuf[0] = cmd_type;
Mariusz Kozlowski0a3b8b62009-02-16 21:31:27 +0100180
H Hartley Sweeten665ff8d2013-05-14 13:37:38 -0700181 ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, CHANNELLISTEP),
H Hartley Sweeten5659e242013-05-14 13:36:47 -0700182 devpriv->duxbuf, SIZEOFDUXBUF,
183 &nsent, 10000);
H Hartley Sweeten665ff8d2013-05-14 13:37:38 -0700184 if (ret < 0)
H Hartley Sweeten106af992013-05-14 13:34:31 -0700185 dev_err(dev->class_dev,
H Hartley Sweeten5659e242013-05-14 13:36:47 -0700186 "could not transmit command to the usb-device, err=%d\n",
H Hartley Sweeten665ff8d2013-05-14 13:37:38 -0700187 ret);
188 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800189}
190
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700191static void usbduxfast_cmd_data(struct comedi_device *dev, int index,
H Hartley Sweeten26961542015-08-24 10:13:57 -0700192 u8 len, u8 op, u8 out, u8 log)
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700193{
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
H Hartley Sweeten32fa46b2013-05-14 13:38:21 -0700203static int usbduxfast_ai_stop(struct comedi_device *dev, int do_unlink)
Bernd Porrf47c6972008-11-14 14:49:34 -0800204{
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700205 struct usbduxfast_private *devpriv = dev->private;
Bernd Porrf47c6972008-11-14 14:49:34 -0800206
H Hartley Sweeten32fa46b2013-05-14 13:38:21 -0700207 /* stop aquistion */
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700208 devpriv->ai_cmd_running = 0;
Bernd Porrf47c6972008-11-14 14:49:34 -0800209
H Hartley Sweeten32fa46b2013-05-14 13:38:21 -0700210 if (do_unlink && devpriv->urb) {
211 /* kill the running transfer */
212 usb_kill_urb(devpriv->urb);
213 }
Bernd Porrf47c6972008-11-14 14:49:34 -0800214
H Hartley Sweeten32fa46b2013-05-14 13:38:21 -0700215 return 0;
Bernd Porrf47c6972008-11-14 14:49:34 -0800216}
217
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530218static int usbduxfast_ai_cancel(struct comedi_device *dev,
219 struct comedi_subdevice *s)
Bernd Porrf47c6972008-11-14 14:49:34 -0800220{
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700221 struct usbduxfast_private *devpriv = dev->private;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100222 int ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800223
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200224 mutex_lock(&devpriv->mut);
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700225 ret = usbduxfast_ai_stop(dev, 1);
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200226 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800227
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100228 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800229}
230
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700231static 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 {
H Hartley Sweetenc39e0502014-10-31 12:04:28 -0700243 unsigned int nsamples;
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700244
H Hartley Sweetenc39e0502014-10-31 12:04:28 -0700245 nsamples = comedi_bytes_to_samples(s, urb->actual_length);
H Hartley Sweeten979f9992014-11-05 10:31:35 -0700246 nsamples = comedi_nsamples_left(s, nsamples);
H Hartley Sweetenf81ac412014-10-22 15:36:45 -0700247 comedi_buf_write_samples(s, urb->transfer_buffer, nsamples);
H Hartley Sweeten979f9992014-11-05 10:31:35 -0700248
249 if (cmd->stop_src == TRIG_COUNT &&
250 async->scans_done >= cmd->stop_arg)
251 async->events |= COMEDI_CB_EOA;
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700252 }
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
H Hartley Sweetenf8eb27e2013-05-14 13:29:09 -0700266static void usbduxfast_ai_interrupt(struct urb *urb)
Bernd Porrf47c6972008-11-14 14:49:34 -0800267{
H Hartley Sweetenf8eb27e2013-05-14 13:29:09 -0700268 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;
Bernd Porrf47c6972008-11-14 14:49:34 -0800272
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700273 /* exit if not running a command, do not resubmit urb */
274 if (!devpriv->ai_cmd_running)
Bernd Porrf47c6972008-11-14 14:49:34 -0800275 return;
Bernd Porrf47c6972008-11-14 14:49:34 -0800276
Bernd Porrf47c6972008-11-14 14:49:34 -0800277 switch (urb->status) {
278 case 0:
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700279 usbduxfast_ai_handle_urb(dev, s, urb);
Bernd Porrf47c6972008-11-14 14:49:34 -0800280 break;
281
Bernd Porrf47c6972008-11-14 14:49:34 -0800282 case -ECONNRESET:
283 case -ENOENT:
284 case -ESHUTDOWN:
285 case -ECONNABORTED:
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700286 /* after an unlink command, unplug, ... etc */
H Hartley Sweetenf8eb27e2013-05-14 13:29:09 -0700287 async->events |= COMEDI_CB_ERROR;
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700288 break;
Bernd Porrf47c6972008-11-14 14:49:34 -0800289
290 default:
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700291 /* a real error */
H Hartley Sweeten42f4acd2014-07-17 12:27:28 -0700292 dev_err(dev->class_dev,
293 "non-zero urb status received in ai intr context: %d\n",
294 urb->status);
H Hartley Sweetenf8eb27e2013-05-14 13:29:09 -0700295 async->events |= COMEDI_CB_ERROR;
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700296 break;
Bernd Porrf47c6972008-11-14 14:49:34 -0800297 }
298
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100299 /*
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700300 * comedi_handle_events() cannot be used in this driver. The (*cancel)
301 * operation would unlink the urb.
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100302 */
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700303 if (async->events & COMEDI_CB_CANCEL_MASK)
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700304 usbduxfast_ai_stop(dev, 0);
H Hartley Sweeten7c88f9f2014-10-14 12:14:39 -0700305
306 comedi_event(dev, s);
Bernd Porrf47c6972008-11-14 14:49:34 -0800307}
308
H Hartley Sweetenebe9f1c2013-05-14 13:41:07 -0700309static int usbduxfast_submit_urb(struct comedi_device *dev)
Bernd Porrf47c6972008-11-14 14:49:34 -0800310{
H Hartley Sweeten0a92de22013-05-20 14:20:30 -0700311 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700312 struct usbduxfast_private *devpriv = dev->private;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100313 int ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800314
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700315 usb_fill_bulk_urb(devpriv->urb, usb, usb_rcvbulkpipe(usb, BULKINEP),
H Hartley Sweetenef8e0842013-05-14 13:36:23 -0700316 devpriv->inbuf, SIZEINBUF,
H Hartley Sweetenda63c392013-05-14 13:33:13 -0700317 usbduxfast_ai_interrupt, dev);
Bernd Porrf47c6972008-11-14 14:49:34 -0800318
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700319 ret = usb_submit_urb(devpriv->urb, GFP_ATOMIC);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100320 if (ret) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700321 dev_err(dev->class_dev, "usb_submit_urb error %d\n", ret);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100322 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800323 }
324 return 0;
325}
326
H Hartley Sweeten99555fc2015-08-24 10:13:54 -0700327static 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
H Hartley Sweetendb1876f2015-08-24 10:13:55 -0700334 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
H Hartley Sweeten99555fc2015-08-24 10:13:54 -0700339 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
Bill Pemberton71b5f4f2009-03-16 22:05:08 -0400357static int usbduxfast_ai_cmdtest(struct comedi_device *dev,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530358 struct comedi_subdevice *s,
359 struct comedi_cmd *cmd)
Bernd Porrf47c6972008-11-14 14:49:34 -0800360{
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700361 int err = 0;
H Hartley Sweetenc748deb2015-08-24 10:14:01 -0700362 unsigned int steps;
363 unsigned int arg;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100364
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700365 /* Step 1 : check if triggers are trivially valid */
Bernd Porrf47c6972008-11-14 14:49:34 -0800366
Ian Abbottf53398e2015-03-27 19:14:38 +0000367 err |= comedi_check_trigger_src(&cmd->start_src,
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700368 TRIG_NOW | TRIG_EXT | TRIG_INT);
H Hartley Sweetenfe0d96b2015-08-24 10:14:00 -0700369 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
370 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
Ian Abbottf53398e2015-03-27 19:14:38 +0000371 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
372 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
Bernd Porrf47c6972008-11-14 14:49:34 -0800373
374 if (err)
375 return 1;
376
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700377 /* Step 2a : make sure trigger sources are unique */
Bernd Porrf47c6972008-11-14 14:49:34 -0800378
Ian Abbottf53398e2015-03-27 19:14:38 +0000379 err |= comedi_check_trigger_is_unique(cmd->start_src);
Ian Abbottf53398e2015-03-27 19:14:38 +0000380 err |= comedi_check_trigger_is_unique(cmd->stop_src);
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700381
382 /* Step 2b : and mutually compatible */
Bernd Porrf47c6972008-11-14 14:49:34 -0800383
Bernd Porrf47c6972008-11-14 14:49:34 -0800384 if (err)
385 return 2;
386
H Hartley Sweeten9309c472012-11-13 18:00:06 -0700387 /* Step 3: check if arguments are trivially valid */
Bernd Porrf47c6972008-11-14 14:49:34 -0800388
Ian Abbottf53398e2015-03-27 19:14:38 +0000389 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
Bernd Porrf47c6972008-11-14 14:49:34 -0800390
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100391 if (!cmd->chanlist_len)
H Hartley Sweeten9309c472012-11-13 18:00:06 -0700392 err |= -EINVAL;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100393
H Hartley Sweetend636f872015-08-24 10:13:59 -0700394 /* 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
Ian Abbottf53398e2015-03-27 19:14:38 +0000399 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
400 cmd->chanlist_len);
Bernd Porrf47c6972008-11-14 14:49:34 -0800401
H Hartley Sweetenc748deb2015-08-24 10:14:01 -0700402 /*
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);
Bernd Porrf47c6972008-11-14 14:49:34 -0800416
H Hartley Sweetenfe0d96b2015-08-24 10:14:00 -0700417 if (cmd->stop_src == TRIG_COUNT)
Ian Abbottf53398e2015-03-27 19:14:38 +0000418 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
H Hartley Sweetenfe0d96b2015-08-24 10:14:00 -0700419 else /* TRIG_NONE */
Ian Abbottf53398e2015-03-27 19:14:38 +0000420 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
Bernd Porrf47c6972008-11-14 14:49:34 -0800421
422 if (err)
423 return 3;
424
H Hartley Sweeten99555fc2015-08-24 10:13:54 -0700425 /* 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;
Bernd Porrf47c6972008-11-14 14:49:34 -0800432
433 return 0;
Bernd Porrf47c6972008-11-14 14:49:34 -0800434}
435
Bill Pemberton71b5f4f2009-03-16 22:05:08 -0400436static int usbduxfast_ai_inttrig(struct comedi_device *dev,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530437 struct comedi_subdevice *s,
H Hartley Sweeten95194592014-04-17 10:08:09 -0700438 unsigned int trig_num)
Bernd Porrf47c6972008-11-14 14:49:34 -0800439{
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700440 struct usbduxfast_private *devpriv = dev->private;
H Hartley Sweeten95194592014-04-17 10:08:09 -0700441 struct comedi_cmd *cmd = &s->async->cmd;
Bernd Porrf47c6972008-11-14 14:49:34 -0800442 int ret;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100443
H Hartley Sweeten95194592014-04-17 10:08:09 -0700444 if (trig_num != cmd->start_arg)
445 return -EINVAL;
446
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200447 mutex_lock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800448
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700449 if (!devpriv->ai_cmd_running) {
450 devpriv->ai_cmd_running = 1;
H Hartley Sweetenebe9f1c2013-05-14 13:41:07 -0700451 ret = usbduxfast_submit_urb(dev);
Bernd Porrf47c6972008-11-14 14:49:34 -0800452 if (ret < 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700453 dev_err(dev->class_dev, "urbSubmit: err=%d\n", ret);
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700454 devpriv->ai_cmd_running = 0;
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200455 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800456 return ret;
457 }
458 s->async->inttrig = NULL;
459 } else {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700460 dev_err(dev->class_dev, "ai is already running\n");
Bernd Porrf47c6972008-11-14 14:49:34 -0800461 }
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200462 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800463 return 1;
464}
465
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530466static int usbduxfast_ai_cmd(struct comedi_device *dev,
467 struct comedi_subdevice *s)
Bernd Porrf47c6972008-11-14 14:49:34 -0800468{
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700469 struct usbduxfast_private *devpriv = dev->private;
Bill Pembertonea6d0d42009-03-16 22:05:47 -0400470 struct comedi_cmd *cmd = &s->async->cmd;
H Hartley Sweeten99555fc2015-08-24 10:13:54 -0700471 unsigned int rngmask = 0xff;
472 int j, ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800473 long steps, steps_tmp;
474
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200475 mutex_lock(&devpriv->mut);
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700476 if (devpriv->ai_cmd_running) {
H Hartley Sweeten7b0fc5b2015-08-24 10:14:02 -0700477 ret = -EBUSY;
478 goto cmd_exit;
Bernd Porrf47c6972008-11-14 14:49:34 -0800479 }
Bernd Porrf47c6972008-11-14 14:49:34 -0800480
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100481 /*
482 * ignore the first buffers from the device if there
483 * is an error condition
484 */
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700485 devpriv->ignore = PACKETS_TO_IGNORE;
Bernd Porrf47c6972008-11-14 14:49:34 -0800486
H Hartley Sweetenfe0d96b2015-08-24 10:14:00 -0700487 steps = (cmd->convert_arg * 30) / 1000;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100488
Bernd Porrf47c6972008-11-14 14:49:34 -0800489 switch (cmd->chanlist_len) {
Bernd Porrf47c6972008-11-14 14:49:34 -0800490 case 1:
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100491 /*
492 * one channel
493 */
494
Bernd Porrf47c6972008-11-14 14:49:34 -0800495 if (CR_RANGE(cmd->chanlist[0]) > 0)
496 rngmask = 0xff - 0x04;
497 else
498 rngmask = 0xff;
499
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100500 /*
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 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100508 /* deceision state w/o data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100509 /* RDY0 = 0 */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700510 usbduxfast_cmd_data(dev, 0, 0x01, 0x01, rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100511 } else { /* we just proceed to state 1 */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700512 usbduxfast_cmd_data(dev, 0, 0x01, 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800513 }
514
515 if (steps < MIN_SAMPLING_PERIOD) {
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100516 /* for fast single channel aqu without mux */
Bernd Porrf47c6972008-11-14 14:49:34 -0800517 if (steps <= 1) {
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100518 /*
519 * we just stay here at state 1 and rexecute
520 * the same state this gives us 30MHz sampling
521 * rate
522 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800523
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100524 /* branch back to state 1 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100525 /* deceision state with data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100526 /* doesn't matter */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700527 usbduxfast_cmd_data(dev, 1,
528 0x89, 0x03, rngmask, 0xff);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100529 } else {
530 /*
531 * we loop through two states: data and delay
532 * max rate is 15MHz
533 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100534 /* data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100535 /* doesn't matter */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700536 usbduxfast_cmd_data(dev, 1, steps - 1,
537 0x02, rngmask, 0x00);
538
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100539 /* branch back to state 1 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100540 /* deceision state w/o data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100541 /* doesn't matter */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700542 usbduxfast_cmd_data(dev, 2,
543 0x09, 0x01, rngmask, 0xff);
Bernd Porrf47c6972008-11-14 14:49:34 -0800544 }
545 } else {
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100546 /*
547 * we loop through 3 states: 2x delay and 1x data
548 * this gives a min sampling rate of 60kHz
549 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800550
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100551 /* we have 1 state with duration 1 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800552 steps = steps - 1;
553
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100554 /* do the first part of the delay */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700555 usbduxfast_cmd_data(dev, 1,
556 steps / 2, 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800557
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100558 /* and the second part */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700559 usbduxfast_cmd_data(dev, 2, steps - steps / 2,
560 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800561
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100562 /* get the data and branch back */
563
564 /* branch back to state 1 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100565 /* deceision state w data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100566 /* doesn't matter */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700567 usbduxfast_cmd_data(dev, 3,
568 0x09, 0x03, rngmask, 0xff);
Bernd Porrf47c6972008-11-14 14:49:34 -0800569 }
570 break;
571
572 case 2:
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100573 /*
574 * two channels
575 * commit data to the FIFO
576 */
577
Bernd Porrf47c6972008-11-14 14:49:34 -0800578 if (CR_RANGE(cmd->chanlist[0]) > 0)
579 rngmask = 0xff - 0x04;
580 else
581 rngmask = 0xff;
Bernd Porrf47c6972008-11-14 14:49:34 -0800582
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100583 /* data */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700584 usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100585
586 /* we have 1 state with duration 1: state 0 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800587 steps_tmp = steps - 1;
588
589 if (CR_RANGE(cmd->chanlist[1]) > 0)
590 rngmask = 0xff - 0x04;
591 else
592 rngmask = 0xff;
Bernd Porrf47c6972008-11-14 14:49:34 -0800593
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100594 /* do the first part of the delay */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100595 /* count */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700596 usbduxfast_cmd_data(dev, 1, steps_tmp / 2,
597 0x00, 0xfe & rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800598
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100599 /* and the second part */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700600 usbduxfast_cmd_data(dev, 2, steps_tmp - steps_tmp / 2,
601 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800602
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100603 /* data */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700604 usbduxfast_cmd_data(dev, 3, 0x01, 0x02, rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100605
606 /*
607 * we have 2 states with duration 1: step 6 and
608 * the IDLE state
609 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800610 steps_tmp = steps - 2;
611
612 if (CR_RANGE(cmd->chanlist[0]) > 0)
613 rngmask = 0xff - 0x04;
614 else
615 rngmask = 0xff;
Bernd Porrf47c6972008-11-14 14:49:34 -0800616
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100617 /* do the first part of the delay */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100618 /* reset */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700619 usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
620 0x00, (0xff - 0x02) & rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800621
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100622 /* and the second part */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700623 usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
624 0x00, rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100625
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700626 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800627 break;
628
629 case 3:
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100630 /*
631 * three channels
632 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800633 for (j = 0; j < 1; j++) {
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700634 int index = j * 2;
635
Bernd Porrf47c6972008-11-14 14:49:34 -0800636 if (CR_RANGE(cmd->chanlist[j]) > 0)
637 rngmask = 0xff - 0x04;
638 else
639 rngmask = 0xff;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100640 /*
641 * commit data to the FIFO and do the first part
642 * of the delay
643 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100644 /* data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100645 /* no change */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700646 usbduxfast_cmd_data(dev, index, steps / 2,
647 0x02, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800648
649 if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
650 rngmask = 0xff - 0x04;
651 else
652 rngmask = 0xff;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100653
654 /* do the second part of the delay */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100655 /* no data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100656 /* count */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700657 usbduxfast_cmd_data(dev, index + 1, steps - steps / 2,
658 0x00, 0xfe & rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800659 }
660
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100661 /* 2 steps with duration 1: the idele step and step 6: */
Bernd Porrf47c6972008-11-14 14:49:34 -0800662 steps_tmp = steps - 2;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100663
664 /* commit data to the FIFO and do the first part of the delay */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100665 /* data */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700666 usbduxfast_cmd_data(dev, 4, steps_tmp / 2,
667 0x02, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800668
669 if (CR_RANGE(cmd->chanlist[0]) > 0)
670 rngmask = 0xff - 0x04;
671 else
672 rngmask = 0xff;
Bernd Porrf47c6972008-11-14 14:49:34 -0800673
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100674 /* do the second part of the delay */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100675 /* no data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100676 /* reset */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700677 usbduxfast_cmd_data(dev, 5, steps_tmp - steps_tmp / 2,
678 0x00, (0xff - 0x02) & rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100679
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700680 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
Bernd Porr99284f22014-07-24 14:34:32 +0100681 break;
Bernd Porrf47c6972008-11-14 14:49:34 -0800682
683 case 16:
684 if (CR_RANGE(cmd->chanlist[0]) > 0)
685 rngmask = 0xff - 0x04;
686 else
687 rngmask = 0xff;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100688
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 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100695 /* deceision state w/o data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100696 /* reset */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100697 /* RDY0 = 0 */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700698 usbduxfast_cmd_data(dev, 0, 0x01, 0x01,
699 (0xff - 0x02) & rngmask, 0x00);
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100700 } else {
701 /*
702 * we just proceed to state 1
703 */
704
705 /* 30us reset pulse */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100706 /* reset */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700707 usbduxfast_cmd_data(dev, 0, 0xff, 0x00,
708 (0xff - 0x02) & rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800709 }
710
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100711 /* commit data to the FIFO */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100712 /* data */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700713 usbduxfast_cmd_data(dev, 1, 0x01, 0x02, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800714
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100715 /* we have 2 states with duration 1 */
Bernd Porrf47c6972008-11-14 14:49:34 -0800716 steps = steps - 2;
717
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100718 /* do the first part of the delay */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700719 usbduxfast_cmd_data(dev, 2, steps / 2,
720 0x00, 0xfe & rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800721
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100722 /* and the second part */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700723 usbduxfast_cmd_data(dev, 3, steps - steps / 2,
724 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800725
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100726 /* branch back to state 1 */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100727 /* deceision state w/o data */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100728 /* doesn't matter */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700729 usbduxfast_cmd_data(dev, 4, 0x09, 0x01, rngmask, 0xff);
Bernd Porrf47c6972008-11-14 14:49:34 -0800730
731 break;
Bernd Porrf47c6972008-11-14 14:49:34 -0800732 }
733
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100734 /* 0 means that the AD commands are sent */
H Hartley Sweeten7b0fc5b2015-08-24 10:14:02 -0700735 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
736 if (ret < 0)
737 goto cmd_exit;
H Hartley Sweeten71cf2b42014-05-27 10:31:13 -0700738
Bernd Porrf47c6972008-11-14 14:49:34 -0800739 if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100740 /* enable this acquisition operation */
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700741 devpriv->ai_cmd_running = 1;
H Hartley Sweetenebe9f1c2013-05-14 13:41:07 -0700742 ret = usbduxfast_submit_urb(dev);
Bernd Porrf47c6972008-11-14 14:49:34 -0800743 if (ret < 0) {
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700744 devpriv->ai_cmd_running = 0;
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100745 /* fixme: unlink here?? */
H Hartley Sweeten7b0fc5b2015-08-24 10:14:02 -0700746 goto cmd_exit;
Bernd Porrf47c6972008-11-14 14:49:34 -0800747 }
748 s->async->inttrig = NULL;
H Hartley Sweeten95194592014-04-17 10:08:09 -0700749 } else { /* TRIG_INT */
Bernd Porrf47c6972008-11-14 14:49:34 -0800750 s->async->inttrig = usbduxfast_ai_inttrig;
751 }
H Hartley Sweeten7b0fc5b2015-08-24 10:14:02 -0700752
753cmd_exit:
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200754 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800755
H Hartley Sweeten7b0fc5b2015-08-24 10:14:02 -0700756 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800757}
758
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100759/*
760 * Mode 0 is used to get a single conversion on demand.
761 */
Bill Pemberton71b5f4f2009-03-16 22:05:08 -0400762static int usbduxfast_ai_insn_read(struct comedi_device *dev,
Mithlesh Thukral0a85b6f2009-06-08 21:04:41 +0530763 struct comedi_subdevice *s,
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700764 struct comedi_insn *insn,
765 unsigned int *data)
Bernd Porrf47c6972008-11-14 14:49:34 -0800766{
H Hartley Sweeten0a92de22013-05-20 14:20:30 -0700767 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700768 struct usbduxfast_private *devpriv = dev->private;
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700769 unsigned int chan = CR_CHAN(insn->chanspec);
770 unsigned int range = CR_RANGE(insn->chanspec);
H Hartley Sweeten26961542015-08-24 10:13:57 -0700771 u8 rngmask = range ? (0xff - 0x04) : 0xff;
Bernd Porrf47c6972008-11-14 14:49:34 -0800772 int i, j, n, actual_length;
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700773 int ret;
H Hartley Sweetenba6205d2013-05-14 13:28:48 -0700774
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200775 mutex_lock(&devpriv->mut);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700776
H Hartley Sweeten7aa41c32013-05-14 13:27:37 -0700777 if (devpriv->ai_cmd_running) {
YAMANE Toshiaki0a00ab92012-10-24 15:14:46 +0900778 dev_err(dev->class_dev,
H Hartley Sweeten106af992013-05-14 13:34:31 -0700779 "ai_insn_read not possible, async cmd is running\n");
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200780 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800781 return -EBUSY;
782 }
Bernd Porrf47c6972008-11-14 14:49:34 -0800783
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700784 /* set command for the first channel */
Bernd Porrf47c6972008-11-14 14:49:34 -0800785
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100786 /* commit data to the FIFO */
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100787 /* data */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700788 usbduxfast_cmd_data(dev, 0, 0x01, 0x02, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800789
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100790 /* do the first part of the delay */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700791 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);
Bernd Porrf47c6972008-11-14 14:49:34 -0800795
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +0100796 /* second part */
H Hartley Sweeten17fdeba2013-05-14 13:41:30 -0700797 usbduxfast_cmd_data(dev, 5, 0x0c, 0x00, rngmask, 0x00);
798 usbduxfast_cmd_data(dev, 6, 0x01, 0x00, rngmask, 0x00);
Bernd Porrf47c6972008-11-14 14:49:34 -0800799
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700800 ret = usbduxfast_send_cmd(dev, SENDADCOMMANDS);
801 if (ret < 0) {
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200802 mutex_unlock(&devpriv->mut);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700803 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800804 }
H Hartley Sweetenba6205d2013-05-14 13:28:48 -0700805
Bernd Porrf47c6972008-11-14 14:49:34 -0800806 for (i = 0; i < PACKETS_TO_IGNORE; i++) {
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700807 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
H Hartley Sweetenef8e0842013-05-14 13:36:23 -0700808 devpriv->inbuf, SIZEINBUF,
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800809 &actual_length, 10000);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700810 if (ret < 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700811 dev_err(dev->class_dev, "insn timeout, no data\n");
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200812 mutex_unlock(&devpriv->mut);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700813 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800814 }
815 }
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700816
Bernd Porrf47c6972008-11-14 14:49:34 -0800817 for (i = 0; i < insn->n;) {
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700818 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, BULKINEP),
H Hartley Sweetenef8e0842013-05-14 13:36:23 -0700819 devpriv->inbuf, SIZEINBUF,
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800820 &actual_length, 10000);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700821 if (ret < 0) {
822 dev_err(dev->class_dev, "insn data error: %d\n", ret);
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200823 mutex_unlock(&devpriv->mut);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700824 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800825 }
H Hartley Sweeten26961542015-08-24 10:13:57 -0700826 n = actual_length / sizeof(u16);
Bernd Porrf47c6972008-11-14 14:49:34 -0800827 if ((n % 16) != 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700828 dev_err(dev->class_dev, "insn data packet corrupted\n");
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200829 mutex_unlock(&devpriv->mut);
Bernd Porrf47c6972008-11-14 14:49:34 -0800830 return -EINVAL;
831 }
832 for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
H Hartley Sweeten26961542015-08-24 10:13:57 -0700833 data[i] = ((u16 *)(devpriv->inbuf))[j];
Bernd Porrf47c6972008-11-14 14:49:34 -0800834 i++;
835 }
836 }
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700837
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200838 mutex_unlock(&devpriv->mut);
H Hartley Sweetendabf2aa2013-05-14 13:41:51 -0700839
840 return insn->n;
Bernd Porrf47c6972008-11-14 14:49:34 -0800841}
842
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700843static int usbduxfast_upload_firmware(struct comedi_device *dev,
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700844 const u8 *data, size_t size,
845 unsigned long context)
Bernd Porrf47c6972008-11-14 14:49:34 -0800846{
H Hartley Sweeten0a92de22013-05-20 14:20:30 -0700847 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweeten26961542015-08-24 10:13:57 -0700848 u8 *buf;
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700849 unsigned char *tmp;
H Hartley Sweeten106af992013-05-14 13:34:31 -0700850 int ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800851
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700852 if (!data)
Bernd Porr81874ff2009-04-17 21:21:46 +0100853 return 0;
854
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700855 if (size > FIRMWARE_MAX_LEN) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700856 dev_err(dev->class_dev, "firmware binary too large for FX2\n");
Bernd Porrf47c6972008-11-14 14:49:34 -0800857 return -ENOMEM;
858 }
859
Bernd Porr81874ff2009-04-17 21:21:46 +0100860 /* we generate a local buffer for the firmware */
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700861 buf = kmemdup(data, size, GFP_KERNEL);
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700862 if (!buf)
Bernd Porr81874ff2009-04-17 21:21:46 +0100863 return -ENOMEM;
Bernd Porr81874ff2009-04-17 21:21:46 +0100864
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700865 /* 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);
Bernd Porr81874ff2009-04-17 21:21:46 +0100880 if (ret < 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700881 dev_err(dev->class_dev, "can not stop firmware\n");
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700882 goto done;
Bernd Porr81874ff2009-04-17 21:21:46 +0100883 }
884
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700885 /* 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,
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700890 buf, size,
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700891 EZTIMEOUT);
Bernd Porr81874ff2009-04-17 21:21:46 +0100892 if (ret < 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700893 dev_err(dev->class_dev, "firmware upload failed\n");
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700894 goto done;
Bernd Porr81874ff2009-04-17 21:21:46 +0100895 }
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700896
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);
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700905 if (ret < 0)
H Hartley Sweeten106af992013-05-14 13:34:31 -0700906 dev_err(dev->class_dev, "can not start firmware\n");
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700907
908done:
H Hartley Sweetenfbe38a8b2013-05-14 13:40:24 -0700909 kfree(tmp);
H Hartley Sweeten1b4997e2013-05-14 13:39:34 -0700910 kfree(buf);
911 return ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800912}
913
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700914static int usbduxfast_auto_attach(struct comedi_device *dev,
915 unsigned long context_unused)
Bernd Porrf47c6972008-11-14 14:49:34 -0800916{
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700917 struct usb_interface *intf = comedi_to_usb_interface(dev);
H Hartley Sweeten0a92de22013-05-20 14:20:30 -0700918 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700919 struct usbduxfast_private *devpriv;
H Hartley Sweeten42293db2015-08-24 10:14:05 -0700920 struct comedi_subdevice *s;
Bernd Porr6742c0a2008-12-08 23:30:13 +0000921 int ret;
Bernd Porrf47c6972008-11-14 14:49:34 -0800922
H Hartley Sweetene4a8ecc2013-05-14 13:26:38 -0700923 if (usb->speed != USB_SPEED_HIGH) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700924 dev_err(dev->class_dev,
YAMANE Toshiaki0a00ab92012-10-24 15:14:46 +0900925 "This driver needs USB 2.0 to operate. Aborting...\n");
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800926 return -ENODEV;
Bernd Porrf47c6972008-11-14 14:49:34 -0800927 }
H Hartley Sweeten64bf88bf2013-05-14 13:24:41 -0700928
H Hartley Sweeten0bdab502013-06-24 16:55:44 -0700929 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700930 if (!devpriv)
931 return -ENOMEM;
Bernd Porrf47c6972008-11-14 14:49:34 -0800932
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200933 mutex_init(&devpriv->mut);
H Hartley Sweetena35fd8a2013-05-14 13:25:56 -0700934 usb_set_intfdata(intf, devpriv);
Bernd Porrf47c6972008-11-14 14:49:34 -0800935
H Hartley Sweeten5659e242013-05-14 13:36:47 -0700936 devpriv->duxbuf = kmalloc(SIZEOFDUXBUF, GFP_KERNEL);
937 if (!devpriv->duxbuf)
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800938 return -ENOMEM;
H Hartley Sweetenca88c092013-05-14 13:25:22 -0700939
H Hartley Sweetena4f2e0f2013-05-14 13:35:15 -0700940 ret = usb_set_interface(usb,
H Hartley Sweeten01245e72013-05-14 13:32:53 -0700941 intf->altsetting->desc.bInterfaceNumber, 1);
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700942 if (ret < 0) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700943 dev_err(dev->class_dev,
H Hartley Sweetenca88c092013-05-14 13:25:22 -0700944 "could not switch to alternate setting 1\n");
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800945 return -ENODEV;
Bernd Porrf47c6972008-11-14 14:49:34 -0800946 }
H Hartley Sweetenca88c092013-05-14 13:25:22 -0700947
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700948 devpriv->urb = usb_alloc_urb(0, GFP_KERNEL);
949 if (!devpriv->urb) {
H Hartley Sweeten106af992013-05-14 13:34:31 -0700950 dev_err(dev->class_dev, "Could not alloc. urb\n");
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800951 return -ENOMEM;
Bernd Porrf47c6972008-11-14 14:49:34 -0800952 }
H Hartley Sweetenca88c092013-05-14 13:25:22 -0700953
H Hartley Sweetenef8e0842013-05-14 13:36:23 -0700954 devpriv->inbuf = kmalloc(SIZEINBUF, GFP_KERNEL);
955 if (!devpriv->inbuf)
Greg Kroah-Hartman88676352008-11-18 17:09:23 -0800956 return -ENOMEM;
H Hartley Sweetenca88c092013-05-14 13:25:22 -0700957
H Hartley Sweetenf9eb8a32013-05-20 14:28:29 -0700958 ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
959 usbduxfast_upload_firmware, 0);
960 if (ret)
Bernd Porr6742c0a2008-12-08 23:30:13 +0000961 return ret;
Bernd Porr6742c0a2008-12-08 23:30:13 +0000962
H Hartley Sweeten42293db2015-08-24 10:14:05 -0700963 ret = comedi_alloc_subdevices(dev, 1);
964 if (ret)
965 return ret;
966
967 /* Analog Input subdevice */
968 s = &dev->subdevices[0];
969 dev->read_subdev = s;
970 s->type = COMEDI_SUBD_AI;
971 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
972 s->n_chan = 16;
973 s->maxdata = 0x1000; /* 12-bit + 1 overflow bit */
974 s->range_table = &range_usbduxfast_ai_range;
975 s->insn_read = usbduxfast_ai_insn_read;
976 s->len_chanlist = s->n_chan;
977 s->do_cmdtest = usbduxfast_ai_cmdtest;
978 s->do_cmd = usbduxfast_ai_cmd;
979 s->cancel = usbduxfast_ai_cancel;
980
981 return 0;
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700982}
983
984static void usbduxfast_detach(struct comedi_device *dev)
985{
H Hartley Sweetena71a65b2013-05-14 13:34:54 -0700986 struct usb_interface *intf = comedi_to_usb_interface(dev);
H Hartley Sweeten2d719c92013-05-14 13:30:09 -0700987 struct usbduxfast_private *devpriv = dev->private;
988
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -0700989 if (!devpriv)
990 return;
991
Ksenija Stanojevic27a90692015-10-02 22:07:54 +0200992 mutex_lock(&devpriv->mut);
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -0700993
H Hartley Sweetena71a65b2013-05-14 13:34:54 -0700994 usb_set_intfdata(intf, NULL);
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -0700995
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700996 if (devpriv->urb) {
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -0700997 /* waits until a running transfer is over */
H Hartley Sweetenda58c262013-05-14 13:35:40 -0700998 usb_kill_urb(devpriv->urb);
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -0700999
H Hartley Sweetenef8e0842013-05-14 13:36:23 -07001000 kfree(devpriv->inbuf);
H Hartley Sweetenda58c262013-05-14 13:35:40 -07001001 usb_free_urb(devpriv->urb);
H Hartley Sweeten2d719c92013-05-14 13:30:09 -07001002 }
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -07001003
H Hartley Sweeten5659e242013-05-14 13:36:47 -07001004 kfree(devpriv->duxbuf);
H Hartley Sweeten38bf7ba2013-05-14 13:30:52 -07001005
Ksenija Stanojevic27a90692015-10-02 22:07:54 +02001006 mutex_unlock(&devpriv->mut);
H Hartley Sweeten2d719c92013-05-14 13:30:09 -07001007}
1008
1009static struct comedi_driver usbduxfast_driver = {
1010 .driver_name = "usbduxfast",
1011 .module = THIS_MODULE,
1012 .auto_attach = usbduxfast_auto_attach,
1013 .detach = usbduxfast_detach,
1014};
1015
1016static int usbduxfast_usb_probe(struct usb_interface *intf,
1017 const struct usb_device_id *id)
1018{
H Hartley Sweetena35fd8a2013-05-14 13:25:56 -07001019 return comedi_usb_auto_config(intf, &usbduxfast_driver, 0);
Bernd Porrf47c6972008-11-14 14:49:34 -08001020}
1021
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001022static const struct usb_device_id usbduxfast_usb_table[] = {
Mariusz Kozlowski4e8ad0d2009-02-16 21:31:28 +01001023 /* { USB_DEVICE(0x4b4, 0x8613) }, testing */
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001024 { USB_DEVICE(0x13d8, 0x0010) }, /* real ID */
1025 { USB_DEVICE(0x13d8, 0x0011) }, /* real ID */
1026 { }
Bernd Porrf47c6972008-11-14 14:49:34 -08001027};
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001028MODULE_DEVICE_TABLE(usb, usbduxfast_usb_table);
Bernd Porrf47c6972008-11-14 14:49:34 -08001029
H Hartley Sweetencb9513a2012-06-20 12:01:14 -07001030static struct usb_driver usbduxfast_usb_driver = {
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001031 .name = "usbduxfast",
1032 .probe = usbduxfast_usb_probe,
H Hartley Sweeten0c4ab672013-05-14 13:29:35 -07001033 .disconnect = comedi_usb_auto_unconfig,
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001034 .id_table = usbduxfast_usb_table,
Bernd Porrf47c6972008-11-14 14:49:34 -08001035};
H Hartley Sweetencb9513a2012-06-20 12:01:14 -07001036module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver);
Bernd Porrf47c6972008-11-14 14:49:34 -08001037
H Hartley Sweeten4c8ba912012-06-20 12:02:28 -07001038MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1039MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com");
Bernd Porrf47c6972008-11-14 14:49:34 -08001040MODULE_LICENSE("GPL");
Tim Gardnere74f7fc2012-08-16 11:09:28 -06001041MODULE_FIRMWARE(FIRMWARE);