blob: a5363ded3668329f60353b0462487195e842ff8f [file] [log] [blame]
Bernd Porrdd89e202011-07-30 11:15:02 +01001/*
H Hartley Sweeten31de28a2013-05-23 13:09:45 -07002 * usbduxsigma.c
3 * Copyright (C) 2011 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.
Bernd Porrdd89e202011-07-30 11:15:02 +010014 */
H Hartley Sweeten31de28a2013-05-23 13:09:45 -070015
Bernd Porrdd89e202011-07-30 11:15:02 +010016/*
H Hartley Sweeten31de28a2013-05-23 13:09:45 -070017 * Driver: usbduxsigma
18 * Description: University of Stirling USB DAQ & INCITE Technology Limited
19 * Devices: (ITL) USB-DUX [usbduxsigma]
20 * Author: Bernd Porr <BerndPorr@f2s.com>
21 * Updated: 8 Nov 2011
22 * Status: testing
23 */
24
Bernd Porrdd89e202011-07-30 11:15:02 +010025/*
26 * I must give credit here to Chris Baugher who
27 * wrote the driver for AT-MIO-16d. I used some parts of this
28 * driver. I also must give credits to David Brownell
29 * who supported me with the USB development.
30 *
31 * Note: the raw data from the A/D converter is 24 bit big endian
32 * anything else is little endian to/from the dux board
33 *
34 *
35 * Revision history:
Alexandru Guduleasa3ee02062012-03-09 22:29:01 +020036 * 0.1: initial version
Bernd Porrdd89e202011-07-30 11:15:02 +010037 * 0.2: all basic functions implemented, digital I/O only for one port
38 * 0.3: proper vendor ID and driver name
39 * 0.4: fixed D/A voltage range
40 * 0.5: various bug fixes, health check at startup
Bernd Porr8b786072011-11-08 21:21:37 +000041 * 0.6: corrected wrong input range
Bernd Porrdd89e202011-07-30 11:15:02 +010042 */
43
Bernd Porrdd89e202011-07-30 11:15:02 +010044#include <linux/kernel.h>
45#include <linux/module.h>
46#include <linux/init.h>
47#include <linux/slab.h>
48#include <linux/input.h>
49#include <linux/usb.h>
50#include <linux/fcntl.h>
51#include <linux/compiler.h>
H Hartley Sweetenfb62a3f2013-05-20 14:32:29 -070052
Bernd Porrdd89e202011-07-30 11:15:02 +010053#include "comedi_fc.h"
54#include "../comedidev.h"
55
Bernd Porrdd89e202011-07-30 11:15:02 +010056/* timeout for the USB-transfer in ms*/
57#define BULK_TIMEOUT 1000
58
59/* constants for "firmware" upload and download */
H Hartley Sweeten46c87802013-05-23 12:57:25 -070060#define FIRMWARE "usbduxsigma_firmware.bin"
61#define FIRMWARE_MAX_LEN 0x4000
62#define USBDUXSUB_FIRMWARE 0xa0
63#define VENDOR_DIR_IN 0xc0
64#define VENDOR_DIR_OUT 0x40
Bernd Porrdd89e202011-07-30 11:15:02 +010065
66/* internal addresses of the 8051 processor */
67#define USBDUXSUB_CPUCS 0xE600
68
Bernd Porrdd89e202011-07-30 11:15:02 +010069/* 300Hz max frequ under PWM */
70#define MIN_PWM_PERIOD ((long)(1E9/300))
71
72/* Default PWM frequency */
73#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
74
75/* Number of channels (16 AD and offset)*/
76#define NUMCHANNELS 16
77
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -070078#define USBDUXSIGMA_NUM_AO_CHAN 4
79
Bernd Porrdd89e202011-07-30 11:15:02 +010080/* Size of one A/D value */
Ian Abbottf1d376b2013-10-16 14:40:38 +010081#define SIZEADIN ((sizeof(uint32_t)))
Bernd Porrdd89e202011-07-30 11:15:02 +010082
83/*
84 * Size of the async input-buffer IN BYTES, the DIO state is transmitted
85 * as the first byte.
86 */
87#define SIZEINBUF (((NUMCHANNELS+1)*SIZEADIN))
88
89/* 16 bytes. */
90#define SIZEINSNBUF 16
91
92/* Number of DA channels */
93#define NUMOUTCHANNELS 8
94
95/* size of one value for the D/A converter: channel and value */
Ian Abbottf1d376b2013-10-16 14:40:38 +010096#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t)))
Bernd Porrdd89e202011-07-30 11:15:02 +010097
98/*
99 * Size of the output-buffer in bytes
100 * Actually only the first 4 triplets are used but for the
101 * high speed mode we need to pad it to 8 (microframes).
102 */
103#define SIZEOUTBUF ((8*SIZEDAOUT))
104
105/*
106 * Size of the buffer for the dux commands: just now max size is determined
107 * by the analogue out + command byte + panic bytes...
108 */
109#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2))
110
111/* Number of in-URBs which receive the data: min=2 */
112#define NUMOFINBUFFERSFULL 5
113
114/* Number of out-URBs which send the data: min=2 */
115#define NUMOFOUTBUFFERSFULL 5
116
117/* Number of in-URBs which receive the data: min=5 */
118/* must have more buffers due to buggy USB ctr */
119#define NUMOFINBUFFERSHIGH 10
120
121/* Number of out-URBs which send the data: min=5 */
122/* must have more buffers due to buggy USB ctr */
123#define NUMOFOUTBUFFERSHIGH 10
124
Bernd Porrdd89e202011-07-30 11:15:02 +0100125/* number of retries to get the right dux command */
126#define RETRIES 10
127
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700128/* bulk transfer commands to usbduxsigma */
129#define USBBUXSIGMA_AD_CMD 0
130#define USBDUXSIGMA_DA_CMD 1
131#define USBDUXSIGMA_DIO_CFG_CMD 2
132#define USBDUXSIGMA_DIO_BITS_CMD 3
133#define USBDUXSIGMA_SINGLE_AD_CMD 4
134#define USBDUXSIGMA_PWM_ON_CMD 7
135#define USBDUXSIGMA_PWM_OFF_CMD 8
136
H Hartley Sweetenc2cf0cd2013-05-23 13:07:35 -0700137static const struct comedi_lrange usbduxsigma_ai_range = {
138 1, {
139 BIP_RANGE(2.65 / 2.0)
140 }
Bernd Porrdd89e202011-07-30 11:15:02 +0100141};
142
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700143struct usbduxsigma_private {
Bernd Porrdd89e202011-07-30 11:15:02 +0100144 /* actual number of in-buffers */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700145 int n_ai_urbs;
Bernd Porrdd89e202011-07-30 11:15:02 +0100146 /* actual number of out-buffers */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700147 int n_ao_urbs;
Bernd Porrdd89e202011-07-30 11:15:02 +0100148 /* ISO-transfer handling: buffers */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700149 struct urb **ai_urbs;
150 struct urb **ao_urbs;
Bernd Porrdd89e202011-07-30 11:15:02 +0100151 /* pwm-transfer handling */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700152 struct urb *pwm_urb;
Bernd Porrdd89e202011-07-30 11:15:02 +0100153 /* PWM period */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700154 unsigned int pwm_period;
Bernd Porrdd89e202011-07-30 11:15:02 +0100155 /* PWM internal delay for the GPIF in the FX2 */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700156 uint8_t pwm_delay;
Bernd Porrdd89e202011-07-30 11:15:02 +0100157 /* size of the PWM buffer which holds the bit pattern */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700158 int pwm_buf_sz;
Bernd Porrdd89e202011-07-30 11:15:02 +0100159 /* input buffer for the ISO-transfer */
Ian Abbottf1d376b2013-10-16 14:40:38 +0100160 uint32_t *in_buf;
Bernd Porrdd89e202011-07-30 11:15:02 +0100161 /* input buffer for single insn */
Ian Abbottf1d376b2013-10-16 14:40:38 +0100162 uint8_t *insn_buf;
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -0700163
Ian Abbottf1d376b2013-10-16 14:40:38 +0100164 uint8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN];
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -0700165 unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN];
H Hartley Sweetencf9b46342013-05-23 13:02:25 -0700166
167 unsigned high_speed:1;
168 unsigned ai_cmd_running:1;
169 unsigned ai_continuous:1;
170 unsigned ao_cmd_running:1;
171 unsigned ao_continuous:1;
172 unsigned pwm_cmd_running:1;
173
Bernd Porrdd89e202011-07-30 11:15:02 +0100174 /* number of samples to acquire */
175 int ai_sample_count;
176 int ao_sample_count;
177 /* time between samples in units of the timer */
178 unsigned int ai_timer;
179 unsigned int ao_timer;
Alexandru Guduleasa3ee02062012-03-09 22:29:01 +0200180 /* counter between acquisitions */
Bernd Porrdd89e202011-07-30 11:15:02 +0100181 unsigned int ai_counter;
182 unsigned int ao_counter;
183 /* interval in frames/uframes */
184 unsigned int ai_interval;
Bernd Porrdd89e202011-07-30 11:15:02 +0100185 /* commands */
186 uint8_t *dux_commands;
187 struct semaphore sem;
188};
189
H Hartley Sweetene0bc0792013-07-29 17:43:36 -0700190static void usbduxsigma_unlink_urbs(struct urb **urbs, int num_urbs)
191{
192 int i;
193
194 for (i = 0; i < num_urbs; i++)
195 usb_kill_urb(urbs[i]);
196}
197
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700198static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink)
Bernd Porrdd89e202011-07-30 11:15:02 +0100199{
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700200 struct usbduxsigma_private *devpriv = dev->private;
201
H Hartley Sweetene0bc0792013-07-29 17:43:36 -0700202 if (do_unlink && devpriv->ai_urbs)
203 usbduxsigma_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);
Bernd Porrdd89e202011-07-30 11:15:02 +0100204
H Hartley Sweeten19d61fd2013-05-23 12:40:10 -0700205 devpriv->ai_cmd_running = 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100206}
207
H Hartley Sweetencca5bf12013-05-23 13:06:55 -0700208static int usbduxsigma_ai_cancel(struct comedi_device *dev,
209 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +0100210{
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700211 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100212
H Hartley Sweeteneac456c2013-05-23 12:42:01 -0700213 down(&devpriv->sem);
214 /* unlink only if it is really running */
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700215 usbduxsigma_ai_stop(dev, devpriv->ai_cmd_running);
H Hartley Sweeteneac456c2013-05-23 12:42:01 -0700216 up(&devpriv->sem);
H Hartley Sweeten05d4c6f2013-05-23 12:40:45 -0700217
218 return 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100219}
220
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -0700221static void usbduxsigma_ai_urb_complete(struct urb *urb)
Bernd Porrdd89e202011-07-30 11:15:02 +0100222{
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700223 struct comedi_device *dev = urb->context;
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700224 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700225 struct comedi_subdevice *s = dev->read_subdev;
Bernd Porrdd89e202011-07-30 11:15:02 +0100226 unsigned int dio_state;
Ian Abbottf1d376b2013-10-16 14:40:38 +0100227 uint32_t val;
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700228 int ret;
229 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100230
231 /* first we test if something unusual has just happened */
232 switch (urb->status) {
233 case 0:
234 /* copy the result in the transfer buffer */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700235 memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF);
Bernd Porrdd89e202011-07-30 11:15:02 +0100236 break;
237 case -EILSEQ:
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700238 /*
239 * error in the ISOchronous data
240 * we don't copy the data into the transfer buffer
241 * and recycle the last data byte
242 */
H Hartley Sweeten7333d502013-05-23 13:08:51 -0700243 dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n");
Bernd Porrdd89e202011-07-30 11:15:02 +0100244
245 break;
246
247 case -ECONNRESET:
248 case -ENOENT:
249 case -ESHUTDOWN:
250 case -ECONNABORTED:
251 /* happens after an unlink command */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700252 if (devpriv->ai_cmd_running) {
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700253 usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700254 /* we are still running a command, tell comedi */
255 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
256 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100257 }
258 return;
259
260 default:
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700261 /*
262 * a real error on the bus
263 * pass error to comedi if we are really running a command
264 */
265 if (devpriv->ai_cmd_running) {
266 dev_err(dev->class_dev,
267 "%s: non-zero urb status (%d)\n",
268 __func__, urb->status);
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700269 usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700270 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
271 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100272 }
273 return;
274 }
275
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700276 if (unlikely(!devpriv->ai_cmd_running))
Bernd Porrdd89e202011-07-30 11:15:02 +0100277 return;
Bernd Porrdd89e202011-07-30 11:15:02 +0100278
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700279 urb->dev = comedi_to_usb_dev(dev);
Bernd Porrdd89e202011-07-30 11:15:02 +0100280
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700281 ret = usb_submit_urb(urb, GFP_ATOMIC);
282 if (unlikely(ret < 0)) {
283 dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
284 __func__, ret);
285 if (ret == -EL2NSYNC)
286 dev_err(dev->class_dev,
287 "buggy USB host controller or bug in IRQ handler\n");
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700288 usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700289 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
290 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100291 return;
292 }
293
294 /* get the state of the dio pins to allow external trigger */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700295 dio_state = be32_to_cpu(devpriv->in_buf[0]);
Bernd Porrdd89e202011-07-30 11:15:02 +0100296
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700297 devpriv->ai_counter--;
298 if (likely(devpriv->ai_counter > 0))
Bernd Porrdd89e202011-07-30 11:15:02 +0100299 return;
300
301 /* timer zero, transfer measurements to comedi */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700302 devpriv->ai_counter = devpriv->ai_timer;
Bernd Porrdd89e202011-07-30 11:15:02 +0100303
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700304 if (!devpriv->ai_continuous) {
Alexandru Guduleasa3ee02062012-03-09 22:29:01 +0200305 /* not continuous, fixed number of samples */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700306 devpriv->ai_sample_count--;
307 if (devpriv->ai_sample_count < 0) {
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700308 usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700309 /* acquistion is over, tell comedi */
Bernd Porrdd89e202011-07-30 11:15:02 +0100310 s->async->events |= COMEDI_CB_EOA;
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700311 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100312 return;
313 }
314 }
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700315
Bernd Porrdd89e202011-07-30 11:15:02 +0100316 /* get the data from the USB bus and hand it over to comedi */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700317 for (i = 0; i < s->async->cmd.chanlist_len; i++) {
Bernd Porrdd89e202011-07-30 11:15:02 +0100318 /* transfer data, note first byte is the DIO state */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700319 val = be32_to_cpu(devpriv->in_buf[i+1]);
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700320 val &= 0x00ffffff; /* strip status byte */
321 val ^= 0x00800000; /* convert to unsigned */
322
323 ret = cfc_write_array_to_buffer(s, &val, sizeof(uint32_t));
324 if (unlikely(ret == 0)) {
Bernd Porrdd89e202011-07-30 11:15:02 +0100325 /* buffer overflow */
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700326 usbduxsigma_ai_stop(dev, 0); /* w/o unlink */
Bernd Porrdd89e202011-07-30 11:15:02 +0100327 return;
328 }
329 }
330 /* tell comedi that data is there */
H Hartley Sweeten147b25a2013-05-23 12:45:16 -0700331 s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
332 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100333}
334
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700335static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink)
Bernd Porrdd89e202011-07-30 11:15:02 +0100336{
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700337 struct usbduxsigma_private *devpriv = dev->private;
338
H Hartley Sweetene0bc0792013-07-29 17:43:36 -0700339 if (do_unlink && devpriv->ao_urbs)
340 usbduxsigma_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs);
Bernd Porrdd89e202011-07-30 11:15:02 +0100341
H Hartley Sweeten19d61fd2013-05-23 12:40:10 -0700342 devpriv->ao_cmd_running = 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100343}
344
H Hartley Sweetencca5bf12013-05-23 13:06:55 -0700345static int usbduxsigma_ao_cancel(struct comedi_device *dev,
346 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +0100347{
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700348 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100349
H Hartley Sweeteneac456c2013-05-23 12:42:01 -0700350 down(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100351 /* unlink only if it is really running */
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700352 usbduxsigma_ao_stop(dev, devpriv->ao_cmd_running);
H Hartley Sweeteneac456c2013-05-23 12:42:01 -0700353 up(&devpriv->sem);
H Hartley Sweeten05d4c6f2013-05-23 12:40:45 -0700354
355 return 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100356}
357
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -0700358static void usbduxsigma_ao_urb_complete(struct urb *urb)
Bernd Porrdd89e202011-07-30 11:15:02 +0100359{
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700360 struct comedi_device *dev = urb->context;
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700361 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700362 struct comedi_subdevice *s = dev->write_subdev;
Bernd Porrdd89e202011-07-30 11:15:02 +0100363 uint8_t *datap;
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700364 int len;
365 int ret;
366 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100367
368 switch (urb->status) {
369 case 0:
370 /* success */
371 break;
372
373 case -ECONNRESET:
374 case -ENOENT:
375 case -ESHUTDOWN:
376 case -ECONNABORTED:
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700377 /* happens after an unlink command */
378 if (devpriv->ao_cmd_running) {
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700379 usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
Bernd Porrdd89e202011-07-30 11:15:02 +0100380 s->async->events |= COMEDI_CB_EOA;
H Hartley Sweetenf62024e2013-05-23 12:51:37 -0700381 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100382 }
383 return;
384
385 default:
386 /* a real error */
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700387 if (devpriv->ao_cmd_running) {
388 dev_err(dev->class_dev,
389 "%s: non-zero urb status (%d)\n",
390 __func__, urb->status);
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700391 usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700392 s->async->events |= (COMEDI_CB_ERROR | COMEDI_CB_EOA);
H Hartley Sweetenf62024e2013-05-23 12:51:37 -0700393 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100394 }
395 return;
396 }
397
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700398 if (!devpriv->ao_cmd_running)
Bernd Porrdd89e202011-07-30 11:15:02 +0100399 return;
400
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700401 devpriv->ao_counter--;
402 if ((int)devpriv->ao_counter <= 0) {
403 /* timer zero, transfer from comedi */
404 devpriv->ao_counter = devpriv->ao_timer;
Bernd Porrdd89e202011-07-30 11:15:02 +0100405
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700406 if (!devpriv->ao_continuous) {
407 /* not continuous, fixed number of samples */
408 devpriv->ao_sample_count--;
409 if (devpriv->ao_sample_count < 0) {
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700410 usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700411 /* acquistion is over, tell comedi */
Bernd Porrdd89e202011-07-30 11:15:02 +0100412 s->async->events |= COMEDI_CB_EOA;
H Hartley Sweetenf62024e2013-05-23 12:51:37 -0700413 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100414 return;
415 }
416 }
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700417
Bernd Porrdd89e202011-07-30 11:15:02 +0100418 /* transmit data to the USB bus */
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700419 datap = urb->transfer_buffer;
420 len = s->async->cmd.chanlist_len;
421 *datap++ = len;
422 for (i = 0; i < len; i++) {
H Hartley Sweeten315a2762013-07-29 17:46:46 -0700423 unsigned int chan = devpriv->ao_chanlist[i];
Ian Abbottf1d376b2013-10-16 14:40:38 +0100424 unsigned short val;
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700425
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700426 ret = comedi_buf_get(s->async, &val);
Bernd Porrdd89e202011-07-30 11:15:02 +0100427 if (ret < 0) {
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700428 dev_err(dev->class_dev, "buffer underflow\n");
429 s->async->events |= (COMEDI_CB_EOA |
430 COMEDI_CB_OVERFLOW);
Bernd Porrdd89e202011-07-30 11:15:02 +0100431 }
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700432 *datap++ = val;
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -0700433 *datap++ = chan;
434 devpriv->ao_readback[chan] = val;
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700435
Bernd Porrdd89e202011-07-30 11:15:02 +0100436 s->async->events |= COMEDI_CB_BLOCK;
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700437 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100438 }
439 }
Bernd Porrdd89e202011-07-30 11:15:02 +0100440
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700441 urb->transfer_buffer_length = SIZEOUTBUF;
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700442 urb->dev = comedi_to_usb_dev(dev);
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700443 urb->status = 0;
444 if (devpriv->high_speed)
445 urb->interval = 8; /* uframes */
446 else
447 urb->interval = 1; /* frames */
448 urb->number_of_packets = 1;
449 urb->iso_frame_desc[0].offset = 0;
450 urb->iso_frame_desc[0].length = SIZEOUTBUF;
451 urb->iso_frame_desc[0].status = 0;
452 ret = usb_submit_urb(urb, GFP_ATOMIC);
453 if (ret < 0) {
454 dev_err(dev->class_dev,
455 "%s: urb resubmit failed (%d)\n",
456 __func__, ret);
457 if (ret == EL2NSYNC)
458 dev_err(dev->class_dev,
459 "buggy USB host controller or bug in IRQ handler\n");
H Hartley Sweeten3b081a42013-05-23 13:07:14 -0700460 usbduxsigma_ao_stop(dev, 0); /* w/o unlink */
H Hartley Sweeten641b78f2013-05-23 12:45:51 -0700461 s->async->events |= (COMEDI_CB_EOA | COMEDI_CB_ERROR);
462 comedi_event(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +0100463 }
464}
465
H Hartley Sweetende0a1e972013-05-23 12:46:40 -0700466static int usbduxsigma_submit_urbs(struct comedi_device *dev,
467 struct urb **urbs, int num_urbs,
468 int input_urb)
Bernd Porrdd89e202011-07-30 11:15:02 +0100469{
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700470 struct usb_device *usb = comedi_to_usb_dev(dev);
H Hartley Sweeteneead8c62013-05-23 12:48:12 -0700471 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweetende0a1e972013-05-23 12:46:40 -0700472 struct urb *urb;
473 int ret;
474 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100475
Bernd Porrdd89e202011-07-30 11:15:02 +0100476 /* Submit all URBs and start the transfer on the bus */
H Hartley Sweetende0a1e972013-05-23 12:46:40 -0700477 for (i = 0; i < num_urbs; i++) {
478 urb = urbs[i];
Bernd Porrdd89e202011-07-30 11:15:02 +0100479
Bernd Porrdd89e202011-07-30 11:15:02 +0100480 /* in case of a resubmission after an unlink... */
H Hartley Sweetende0a1e972013-05-23 12:46:40 -0700481 if (input_urb)
482 urb->interval = devpriv->ai_interval;
483 urb->context = dev;
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700484 urb->dev = usb;
H Hartley Sweetende0a1e972013-05-23 12:46:40 -0700485 urb->status = 0;
486 urb->transfer_flags = URB_ISO_ASAP;
487
488 ret = usb_submit_urb(urb, GFP_ATOMIC);
489 if (ret)
490 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100491 }
492 return 0;
493}
494
H Hartley Sweetenfffe8232013-05-23 13:09:08 -0700495static int usbduxsigma_chans_to_interval(int num_chan)
Bernd Porrdd89e202011-07-30 11:15:02 +0100496{
H Hartley Sweetenfffe8232013-05-23 13:09:08 -0700497 if (num_chan <= 2)
498 return 2; /* 4kHz */
499 if (num_chan <= 8)
500 return 4; /* 2kHz */
501 return 8; /* 1kHz */
Bernd Porrdd89e202011-07-30 11:15:02 +0100502}
503
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700504static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
505 struct comedi_subdevice *s,
506 struct comedi_cmd *cmd)
Bernd Porrdd89e202011-07-30 11:15:02 +0100507{
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700508 struct usbduxsigma_private *devpriv = dev->private;
509 int high_speed = devpriv->high_speed;
H Hartley Sweetenfffe8232013-05-23 13:09:08 -0700510 int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700511 int err = 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100512
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700513 /* Step 1 : check if triggers are trivially valid */
Bernd Porrdd89e202011-07-30 11:15:02 +0100514
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700515 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
516 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
517 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
518 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
519 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
Bernd Porrdd89e202011-07-30 11:15:02 +0100520
521 if (err)
522 return 1;
523
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700524 /* Step 2a : make sure trigger sources are unique */
525
526 err |= cfc_check_trigger_is_unique(cmd->start_src);
527 err |= cfc_check_trigger_is_unique(cmd->stop_src);
528
529 /* Step 2b : and mutually compatible */
Bernd Porrdd89e202011-07-30 11:15:02 +0100530
531 if (err)
532 return 2;
533
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700534 /* Step 3: check if arguments are trivially valid */
Bernd Porrdd89e202011-07-30 11:15:02 +0100535
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700536 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
537
538 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
539 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +0100540
541 if (cmd->scan_begin_src == TRIG_TIMER) {
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700542 unsigned int tmp;
543
544 if (high_speed) {
Bernd Porrdd89e202011-07-30 11:15:02 +0100545 /*
546 * In high speed mode microframes are possible.
547 * However, during one microframe we can roughly
548 * sample two channels. Thus, the more channels
549 * are in the channel list the more time we need.
550 */
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700551 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700552 (1000000 / 8 * interval));
553
554 tmp = (cmd->scan_begin_arg / 125000) * 125000;
Bernd Porrdd89e202011-07-30 11:15:02 +0100555 } else {
556 /* full speed */
557 /* 1kHz scans every USB frame */
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700558 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
559 1000000);
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700560
561 tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
Bernd Porrdd89e202011-07-30 11:15:02 +0100562 }
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700563 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
Bernd Porrdd89e202011-07-30 11:15:02 +0100564 }
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700565
566 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
Bernd Porrdd89e202011-07-30 11:15:02 +0100567
568 if (cmd->stop_src == TRIG_COUNT) {
569 /* any count is allowed */
570 } else {
571 /* TRIG_NONE */
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700572 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +0100573 }
574
575 if (err)
576 return 3;
577
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700578 /* Step 4: fix up any arguments */
579
580 if (high_speed) {
581 /*
582 * every 2 channels get a time window of 125us. Thus, if we
583 * sample all 16 channels we need 1ms. If we sample only one
584 * channel we need only 125us
585 */
586 devpriv->ai_interval = interval;
587 devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
588 } else {
589 /* interval always 1ms */
590 devpriv->ai_interval = 1;
591 devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
592 }
593 if (devpriv->ai_timer < 1)
594 err |= -EINVAL;
595
596 if (cmd->stop_src == TRIG_COUNT) {
597 /* data arrives as one packet */
598 devpriv->ai_sample_count = cmd->stop_arg;
599 devpriv->ai_continuous = 0;
600 } else {
601 /* continuous acquisition */
602 devpriv->ai_continuous = 1;
603 devpriv->ai_sample_count = 0;
604 }
605
606 if (err)
607 return 4;
608
Bernd Porrdd89e202011-07-30 11:15:02 +0100609 return 0;
610}
611
612/*
613 * creates the ADC command for the MAX1271
614 * range is the range value from comedi
615 */
616static void create_adc_command(unsigned int chan,
617 uint8_t *muxsg0,
618 uint8_t *muxsg1)
619{
620 if (chan < 8)
621 (*muxsg0) = (*muxsg0) | (1 << chan);
622 else if (chan < 16)
623 (*muxsg1) = (*muxsg1) | (1 << (chan-8));
624}
625
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700626static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type)
Bernd Porrdd89e202011-07-30 11:15:02 +0100627{
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700628 struct usb_device *usb = comedi_to_usb_dev(dev);
629 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten502f9a32013-05-23 12:50:31 -0700630 int nsent;
Bernd Porrdd89e202011-07-30 11:15:02 +0100631
H Hartley Sweeten502f9a32013-05-23 12:50:31 -0700632 devpriv->dux_commands[0] = cmd_type;
Bernd Porrdd89e202011-07-30 11:15:02 +0100633
H Hartley Sweetenb509a762013-07-29 17:43:55 -0700634 return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1),
H Hartley Sweeten502f9a32013-05-23 12:50:31 -0700635 devpriv->dux_commands, SIZEOFDUXBUFFER,
636 &nsent, BULK_TIMEOUT);
Bernd Porrdd89e202011-07-30 11:15:02 +0100637}
638
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700639static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command)
Bernd Porrdd89e202011-07-30 11:15:02 +0100640{
H Hartley Sweetena59a28a2013-05-23 12:51:56 -0700641 struct usb_device *usb = comedi_to_usb_dev(dev);
642 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100643 int nrec;
H Hartley Sweeten125a77f2013-05-23 12:50:51 -0700644 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100645 int i;
646
647 for (i = 0; i < RETRIES; i++) {
H Hartley Sweetenb509a762013-07-29 17:43:55 -0700648 ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8),
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700649 devpriv->insn_buf, SIZEINSNBUF,
H Hartley Sweeten125a77f2013-05-23 12:50:51 -0700650 &nrec, BULK_TIMEOUT);
651 if (ret < 0)
652 return ret;
653
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700654 if (devpriv->insn_buf[0] == command)
H Hartley Sweeten125a77f2013-05-23 12:50:51 -0700655 return 0;
Bernd Porrdd89e202011-07-30 11:15:02 +0100656 }
H Hartley Sweeten125a77f2013-05-23 12:50:51 -0700657 /*
658 * This is only reached if the data has been requested a
659 * couple of times and the command was not received.
660 */
Bernd Porrdd89e202011-07-30 11:15:02 +0100661 return -EFAULT;
662}
663
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700664static int usbduxsigma_ai_inttrig(struct comedi_device *dev,
665 struct comedi_subdevice *s,
666 unsigned int trignum)
Bernd Porrdd89e202011-07-30 11:15:02 +0100667{
H Hartley Sweeten7333d502013-05-23 13:08:51 -0700668 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100669 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100670
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700671 if (trignum != 0)
Bernd Porrdd89e202011-07-30 11:15:02 +0100672 return -EINVAL;
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700673
674 down(&devpriv->sem);
675 if (!devpriv->ai_cmd_running) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700676 devpriv->ai_cmd_running = 1;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700677 ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
678 devpriv->n_ai_urbs, 1);
Bernd Porrdd89e202011-07-30 11:15:02 +0100679 if (ret < 0) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700680 devpriv->ai_cmd_running = 0;
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700681 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100682 return ret;
683 }
684 s->async->inttrig = NULL;
Bernd Porrdd89e202011-07-30 11:15:02 +0100685 }
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700686 up(&devpriv->sem);
687
Bernd Porrdd89e202011-07-30 11:15:02 +0100688 return 1;
689}
690
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700691static int usbduxsigma_ai_cmd(struct comedi_device *dev,
692 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +0100693{
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700694 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100695 struct comedi_cmd *cmd = &s->async->cmd;
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700696 unsigned int len = cmd->chanlist_len;
Bernd Porrdd89e202011-07-30 11:15:02 +0100697 uint8_t muxsg0 = 0;
698 uint8_t muxsg1 = 0;
699 uint8_t sysred = 0;
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700700 int ret;
701 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100702
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700703 down(&devpriv->sem);
704
Alexandru Guduleasa3ee02062012-03-09 22:29:01 +0200705 /* set current channel of the running acquisition to zero */
Bernd Porrdd89e202011-07-30 11:15:02 +0100706 s->async->cur_chan = 0;
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700707 for (i = 0; i < len; i++) {
708 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
Bernd Porrdd89e202011-07-30 11:15:02 +0100709
Bernd Porrdd89e202011-07-30 11:15:02 +0100710 create_adc_command(chan, &muxsg0, &muxsg1);
Bernd Porrdd89e202011-07-30 11:15:02 +0100711 }
Bernd Porrdd89e202011-07-30 11:15:02 +0100712
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700713 devpriv->dux_commands[1] = len; /* num channels per time step */
714 devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
715 devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
716 devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
717 devpriv->dux_commands[5] = muxsg0;
718 devpriv->dux_commands[6] = muxsg1;
719 devpriv->dux_commands[7] = sysred;
720
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700721 ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700722 if (ret < 0) {
723 up(&devpriv->sem);
724 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100725 }
726
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700727 devpriv->ai_counter = devpriv->ai_timer;
Bernd Porrdd89e202011-07-30 11:15:02 +0100728
729 if (cmd->start_src == TRIG_NOW) {
730 /* enable this acquisition operation */
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700731 devpriv->ai_cmd_running = 1;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700732 ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs,
733 devpriv->n_ai_urbs, 1);
Bernd Porrdd89e202011-07-30 11:15:02 +0100734 if (ret < 0) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700735 devpriv->ai_cmd_running = 0;
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700736 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100737 return ret;
738 }
739 s->async->inttrig = NULL;
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700740 } else { /* TRIG_INT */
741 /* wait for an internal signal and submit the urbs later */
H Hartley Sweeten8eea6db2013-05-23 12:53:23 -0700742 s->async->inttrig = usbduxsigma_ai_inttrig;
Bernd Porrdd89e202011-07-30 11:15:02 +0100743 }
H Hartley Sweetenb986be82013-05-23 13:05:38 -0700744
745 up(&devpriv->sem);
746
Bernd Porrdd89e202011-07-30 11:15:02 +0100747 return 0;
748}
749
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700750static int usbduxsigma_ai_insn_read(struct comedi_device *dev,
751 struct comedi_subdevice *s,
752 struct comedi_insn *insn,
753 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +0100754{
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700755 struct usbduxsigma_private *devpriv = dev->private;
756 unsigned int chan = CR_CHAN(insn->chanspec);
Bernd Porrdd89e202011-07-30 11:15:02 +0100757 uint8_t muxsg0 = 0;
758 uint8_t muxsg1 = 0;
759 uint8_t sysred = 0;
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700760 int ret;
761 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100762
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700763 down(&devpriv->sem);
764 if (devpriv->ai_cmd_running) {
765 up(&devpriv->sem);
766 return -EBUSY;
Bernd Porrdd89e202011-07-30 11:15:02 +0100767 }
768
Bernd Porrdd89e202011-07-30 11:15:02 +0100769 create_adc_command(chan, &muxsg0, &muxsg1);
770
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700771 /* Mode 0 is used to get a single conversion on demand */
772 devpriv->dux_commands[1] = 0x16; /* CONFIG0: chopper on */
773 devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
774 devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
775 devpriv->dux_commands[4] = muxsg0;
776 devpriv->dux_commands[5] = muxsg1;
777 devpriv->dux_commands[6] = sysred;
Bernd Porrdd89e202011-07-30 11:15:02 +0100778
779 /* adc commands */
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700780 ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700781 if (ret < 0) {
782 up(&devpriv->sem);
783 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100784 }
785
786 for (i = 0; i < insn->n; i++) {
Ian Abbottf1d376b2013-10-16 14:40:38 +0100787 uint32_t val;
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700788
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700789 ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700790 if (ret < 0) {
791 up(&devpriv->sem);
792 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100793 }
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700794
Bernd Porrdd89e202011-07-30 11:15:02 +0100795 /* 32 bits big endian from the A/D converter */
Ian Abbottf1d376b2013-10-16 14:40:38 +0100796 val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1)));
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700797 val &= 0x00ffffff; /* strip status byte */
798 val ^= 0x00800000; /* convert to unsigned */
799
800 data[i] = val;
Bernd Porrdd89e202011-07-30 11:15:02 +0100801 }
H Hartley Sweetenc5db3b72013-05-23 13:05:19 -0700802 up(&devpriv->sem);
803
804 return insn->n;
Bernd Porrdd89e202011-07-30 11:15:02 +0100805}
806
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700807static int usbduxsigma_ao_insn_read(struct comedi_device *dev,
808 struct comedi_subdevice *s,
809 struct comedi_insn *insn,
810 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +0100811{
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700812 struct usbduxsigma_private *devpriv = dev->private;
813 unsigned int chan = CR_CHAN(insn->chanspec);
Bernd Porrdd89e202011-07-30 11:15:02 +0100814 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100815
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700816 down(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100817 for (i = 0; i < insn->n; i++)
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -0700818 data[i] = devpriv->ao_readback[chan];
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700819 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100820
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700821 return insn->n;
Bernd Porrdd89e202011-07-30 11:15:02 +0100822}
823
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700824static int usbduxsigma_ao_insn_write(struct comedi_device *dev,
825 struct comedi_subdevice *s,
826 struct comedi_insn *insn,
827 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +0100828{
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700829 struct usbduxsigma_private *devpriv = dev->private;
830 unsigned int chan = CR_CHAN(insn->chanspec);
831 int ret;
832 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +0100833
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700834 down(&devpriv->sem);
835 if (devpriv->ao_cmd_running) {
836 up(&devpriv->sem);
837 return -EBUSY;
Bernd Porrdd89e202011-07-30 11:15:02 +0100838 }
839
840 for (i = 0; i < insn->n; i++) {
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700841 devpriv->dux_commands[1] = 1; /* num channels */
842 devpriv->dux_commands[2] = data[i]; /* value */
843 devpriv->dux_commands[3] = chan; /* channel number */
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -0700844 ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DA_CMD);
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700845 if (ret < 0) {
846 up(&devpriv->sem);
847 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100848 }
H Hartley Sweeten44d3fca2013-05-23 13:04:53 -0700849 devpriv->ao_readback[chan] = data[i];
Bernd Porrdd89e202011-07-30 11:15:02 +0100850 }
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700851 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100852
H Hartley Sweeten2dd87ac2013-05-23 13:04:31 -0700853 return insn->n;
Bernd Porrdd89e202011-07-30 11:15:02 +0100854}
855
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700856static int usbduxsigma_ao_inttrig(struct comedi_device *dev,
857 struct comedi_subdevice *s,
858 unsigned int trignum)
Bernd Porrdd89e202011-07-30 11:15:02 +0100859{
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700860 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +0100861 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +0100862
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700863 if (trignum != 0)
864 return -EINVAL;
865
866 down(&devpriv->sem);
867 if (!devpriv->ao_cmd_running) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700868 devpriv->ao_cmd_running = 1;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -0700869 ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
870 devpriv->n_ao_urbs, 0);
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700871 if (ret < 0) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -0700872 devpriv->ao_cmd_running = 0;
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700873 up(&devpriv->sem);
874 return ret;
875 }
Bernd Porrdd89e202011-07-30 11:15:02 +0100876 s->async->inttrig = NULL;
Bernd Porrdd89e202011-07-30 11:15:02 +0100877 }
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -0700878 up(&devpriv->sem);
879
880 return 1;
Bernd Porrdd89e202011-07-30 11:15:02 +0100881}
882
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700883static int usbduxsigma_ao_cmdtest(struct comedi_device *dev,
884 struct comedi_subdevice *s,
885 struct comedi_cmd *cmd)
Bernd Porrdd89e202011-07-30 11:15:02 +0100886{
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700887 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700888 int err = 0;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700889 int high_speed;
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700890 unsigned int flags;
Bernd Porrdd89e202011-07-30 11:15:02 +0100891
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700892 /* high speed conversions are not used yet */
H Hartley Sweeten57ded312013-05-23 13:09:25 -0700893 high_speed = 0; /* (devpriv->high_speed) */
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700894
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700895 /* Step 1 : check if triggers are trivially valid */
Bernd Porrdd89e202011-07-30 11:15:02 +0100896
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700897 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
898
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700899 if (high_speed) {
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700900 /*
901 * start immediately a new scan
902 * the sampling rate is set by the coversion rate
903 */
904 flags = TRIG_FOLLOW;
Bernd Porrdd89e202011-07-30 11:15:02 +0100905 } else {
906 /* start a new scan (output at once) with a timer */
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700907 flags = TRIG_TIMER;
Bernd Porrdd89e202011-07-30 11:15:02 +0100908 }
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700909 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
Bernd Porrdd89e202011-07-30 11:15:02 +0100910
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700911 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
912 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
913 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
Bernd Porrdd89e202011-07-30 11:15:02 +0100914
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700915 if (err) {
916 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +0100917 return 1;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700918 }
Bernd Porrdd89e202011-07-30 11:15:02 +0100919
H Hartley Sweeten27020ff2012-09-26 14:11:10 -0700920 /* Step 2a : make sure trigger sources are unique */
921
922 err |= cfc_check_trigger_is_unique(cmd->start_src);
923 err |= cfc_check_trigger_is_unique(cmd->stop_src);
924
925 /* Step 2b : and mutually compatible */
Bernd Porrdd89e202011-07-30 11:15:02 +0100926
927 if (err)
928 return 2;
929
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700930 /* Step 3: check if arguments are trivially valid */
Bernd Porrdd89e202011-07-30 11:15:02 +0100931
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700932 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +0100933
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700934 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
935 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +0100936
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700937 if (cmd->scan_begin_src == TRIG_TIMER)
938 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
939 1000000);
940
Bernd Porrdd89e202011-07-30 11:15:02 +0100941 /* not used now, is for later use */
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700942 if (cmd->convert_src == TRIG_TIMER)
943 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 125000);
Bernd Porrdd89e202011-07-30 11:15:02 +0100944
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700945 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
Bernd Porrdd89e202011-07-30 11:15:02 +0100946
947 if (cmd->stop_src == TRIG_COUNT) {
948 /* any count is allowed */
949 } else {
950 /* TRIG_NONE */
H Hartley Sweeten7ec26592012-11-13 18:00:21 -0700951 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +0100952 }
953
Bernd Porrdd89e202011-07-30 11:15:02 +0100954 if (err)
955 return 3;
956
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700957 /* Step 4: fix up any arguments */
958
959 /* we count in timer steps */
960 if (high_speed) {
961 /* timing of the conversion itself: every 125 us */
962 devpriv->ao_timer = cmd->convert_arg / 125000;
963 } else {
964 /*
965 * timing of the scan: every 1ms
966 * we get all channels at once
967 */
968 devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700969 }
H Hartley Sweetendd64d1e2013-05-23 13:05:59 -0700970 if (devpriv->ao_timer < 1)
971 err |= -EINVAL;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -0700972
973 if (cmd->stop_src == TRIG_COUNT) {
974 /* not continuous, use counter */
975 if (high_speed) {
976 /* high speed also scans everything at once */
977 devpriv->ao_sample_count = cmd->stop_arg *
978 cmd->scan_end_arg;
979 } else {
980 /*
981 * There's no scan as the scan has been
982 * handled inside the FX2. Data arrives as
983 * one packet.
984 */
985 devpriv->ao_sample_count = cmd->stop_arg;
986 }
987 devpriv->ao_continuous = 0;
988 } else {
989 /* continuous acquisition */
990 devpriv->ao_continuous = 1;
991 devpriv->ao_sample_count = 0;
992 }
993
994 if (err)
995 return 4;
996
Bernd Porrdd89e202011-07-30 11:15:02 +0100997 return 0;
998}
999
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001000static int usbduxsigma_ao_cmd(struct comedi_device *dev,
1001 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +01001002{
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001003 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +01001004 struct comedi_cmd *cmd = &s->async->cmd;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001005 int ret;
1006 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +01001007
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001008 down(&devpriv->sem);
1009
Alexandru Guduleasa3ee02062012-03-09 22:29:01 +02001010 /* set current channel of the running acquisition to zero */
Bernd Porrdd89e202011-07-30 11:15:02 +01001011 s->async->cur_chan = 0;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001012 for (i = 0; i < cmd->chanlist_len; ++i)
H Hartley Sweeten315a2762013-07-29 17:46:46 -07001013 devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]);
Bernd Porrdd89e202011-07-30 11:15:02 +01001014
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001015 devpriv->ao_counter = devpriv->ao_timer;
Bernd Porrdd89e202011-07-30 11:15:02 +01001016
1017 if (cmd->start_src == TRIG_NOW) {
1018 /* enable this acquisition operation */
H Hartley Sweeten9c922a92013-07-25 16:21:13 -07001019 devpriv->ao_cmd_running = 1;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001020 ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs,
1021 devpriv->n_ao_urbs, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +01001022 if (ret < 0) {
H Hartley Sweeten9c922a92013-07-25 16:21:13 -07001023 devpriv->ao_cmd_running = 0;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001024 up(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +01001025 return ret;
1026 }
1027 s->async->inttrig = NULL;
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001028 } else { /* TRIG_INT */
1029 /* wait for an internal signal and submit the urbs later */
H Hartley Sweeten2d4462d2013-05-23 12:52:59 -07001030 s->async->inttrig = usbduxsigma_ao_inttrig;
Bernd Porrdd89e202011-07-30 11:15:02 +01001031 }
1032
H Hartley Sweetenfb1ef622013-05-23 13:04:11 -07001033 up(&devpriv->sem);
1034
Bernd Porrdd89e202011-07-30 11:15:02 +01001035 return 0;
1036}
1037
H Hartley Sweeten62f85ed2013-05-23 13:00:56 -07001038static int usbduxsigma_dio_insn_config(struct comedi_device *dev,
1039 struct comedi_subdevice *s,
1040 struct comedi_insn *insn,
1041 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +01001042{
H Hartley Sweetenddf62f22013-08-06 09:32:33 -07001043 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001044
H Hartley Sweetenddf62f22013-08-06 09:32:33 -07001045 ret = comedi_dio_insn_config(dev, s, insn, data, 0);
1046 if (ret)
1047 return ret;
H Hartley Sweeten62f85ed2013-05-23 13:00:56 -07001048
1049 /*
1050 * We don't tell the firmware here as it would take 8 frames
1051 * to submit the information. We do it in the (*insn_bits).
1052 */
Bernd Porrdd89e202011-07-30 11:15:02 +01001053 return insn->n;
1054}
1055
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001056static int usbduxsigma_dio_insn_bits(struct comedi_device *dev,
1057 struct comedi_subdevice *s,
1058 struct comedi_insn *insn,
1059 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +01001060{
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001061 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001062 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001063
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001064 down(&devpriv->sem);
Bernd Porrdd89e202011-07-30 11:15:02 +01001065
H Hartley Sweeten77e94872013-08-30 11:05:38 -07001066 comedi_dio_update_state(s, data);
Bernd Porrdd89e202011-07-30 11:15:02 +01001067
H Hartley Sweeten77e94872013-08-30 11:05:38 -07001068 /* Always update the hardware. See the (*insn_config). */
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001069 devpriv->dux_commands[1] = s->io_bits & 0xff;
1070 devpriv->dux_commands[4] = s->state & 0xff;
1071 devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
1072 devpriv->dux_commands[5] = (s->state >> 8) & 0xff;
1073 devpriv->dux_commands[3] = (s->io_bits >> 16) & 0xff;
1074 devpriv->dux_commands[6] = (s->state >> 16) & 0xff;
Bernd Porrdd89e202011-07-30 11:15:02 +01001075
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001076 ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001077 if (ret < 0)
1078 goto done;
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001079 ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_DIO_BITS_CMD);
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001080 if (ret < 0)
1081 goto done;
Bernd Porrdd89e202011-07-30 11:15:02 +01001082
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001083 s->state = devpriv->insn_buf[1] |
1084 (devpriv->insn_buf[2] << 8) |
1085 (devpriv->insn_buf[3] << 16);
Bernd Porrdd89e202011-07-30 11:15:02 +01001086
H Hartley Sweeten77a52e62013-05-23 13:00:36 -07001087 data[1] = s->state;
1088 ret = insn->n;
1089
1090done:
1091 up(&devpriv->sem);
1092
1093 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001094}
1095
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001096static void usbduxsigma_pwm_stop(struct comedi_device *dev, int do_unlink)
Bernd Porrdd89e202011-07-30 11:15:02 +01001097{
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001098 struct usbduxsigma_private *devpriv = dev->private;
1099
H Hartley Sweetenf31260f2013-05-23 12:44:39 -07001100 if (do_unlink) {
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001101 if (devpriv->pwm_urb)
1102 usb_kill_urb(devpriv->pwm_urb);
H Hartley Sweetenf31260f2013-05-23 12:44:39 -07001103 }
Bernd Porrdd89e202011-07-30 11:15:02 +01001104
H Hartley Sweeten19d61fd2013-05-23 12:40:10 -07001105 devpriv->pwm_cmd_running = 0;
Bernd Porrdd89e202011-07-30 11:15:02 +01001106}
1107
H Hartley Sweetenfd245192013-05-23 13:03:26 -07001108static int usbduxsigma_pwm_cancel(struct comedi_device *dev,
1109 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +01001110{
H Hartley Sweeteneead8c62013-05-23 12:48:12 -07001111 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +01001112
1113 /* unlink only if it is really running */
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001114 usbduxsigma_pwm_stop(dev, devpriv->pwm_cmd_running);
Bernd Porrdd89e202011-07-30 11:15:02 +01001115
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001116 return usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_OFF_CMD);
Bernd Porrdd89e202011-07-30 11:15:02 +01001117}
1118
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -07001119static void usbduxsigma_pwm_urb_complete(struct urb *urb)
Bernd Porrdd89e202011-07-30 11:15:02 +01001120{
H Hartley Sweeten7fb13b52013-05-23 12:47:48 -07001121 struct comedi_device *dev = urb->context;
H Hartley Sweeteneead8c62013-05-23 12:48:12 -07001122 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +01001123 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001124
1125 switch (urb->status) {
1126 case 0:
1127 /* success */
1128 break;
1129
1130 case -ECONNRESET:
1131 case -ENOENT:
1132 case -ESHUTDOWN:
1133 case -ECONNABORTED:
H Hartley Sweeten7fb13b52013-05-23 12:47:48 -07001134 /* happens after an unlink command */
1135 if (devpriv->pwm_cmd_running)
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001136 usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
Bernd Porrdd89e202011-07-30 11:15:02 +01001137 return;
1138
1139 default:
1140 /* a real error */
H Hartley Sweeten7fb13b52013-05-23 12:47:48 -07001141 if (devpriv->pwm_cmd_running) {
1142 dev_err(dev->class_dev,
1143 "%s: non-zero urb status (%d)\n",
1144 __func__, urb->status);
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001145 usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
Bernd Porrdd89e202011-07-30 11:15:02 +01001146 }
1147 return;
1148 }
1149
H Hartley Sweeten7fb13b52013-05-23 12:47:48 -07001150 if (!devpriv->pwm_cmd_running)
Bernd Porrdd89e202011-07-30 11:15:02 +01001151 return;
1152
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001153 urb->transfer_buffer_length = devpriv->pwm_buf_sz;
H Hartley Sweetena59a28a2013-05-23 12:51:56 -07001154 urb->dev = comedi_to_usb_dev(dev);
Bernd Porrdd89e202011-07-30 11:15:02 +01001155 urb->status = 0;
H Hartley Sweeten7fb13b52013-05-23 12:47:48 -07001156 ret = usb_submit_urb(urb, GFP_ATOMIC);
1157 if (ret < 0) {
1158 dev_err(dev->class_dev, "%s: urb resubmit failed (%d)\n",
1159 __func__, ret);
1160 if (ret == EL2NSYNC)
1161 dev_err(dev->class_dev,
1162 "buggy USB host controller or bug in IRQ handler\n");
H Hartley Sweeten8cd6f5e2013-05-23 13:03:45 -07001163 usbduxsigma_pwm_stop(dev, 0); /* w/o unlink */
Bernd Porrdd89e202011-07-30 11:15:02 +01001164 }
1165}
1166
H Hartley Sweeten6028f4c2013-05-23 12:51:14 -07001167static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev)
Bernd Porrdd89e202011-07-30 11:15:02 +01001168{
H Hartley Sweeten6028f4c2013-05-23 12:51:14 -07001169 struct usb_device *usb = comedi_to_usb_dev(dev);
1170 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001171 struct urb *urb = devpriv->pwm_urb;
Bernd Porrdd89e202011-07-30 11:15:02 +01001172
Bernd Porrdd89e202011-07-30 11:15:02 +01001173 /* in case of a resubmission after an unlink... */
H Hartley Sweetenb509a762013-07-29 17:43:55 -07001174 usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4),
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001175 urb->transfer_buffer, devpriv->pwm_buf_sz,
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -07001176 usbduxsigma_pwm_urb_complete, dev);
Bernd Porrdd89e202011-07-30 11:15:02 +01001177
H Hartley Sweeten6028f4c2013-05-23 12:51:14 -07001178 return usb_submit_urb(urb, GFP_ATOMIC);
Bernd Porrdd89e202011-07-30 11:15:02 +01001179}
1180
H Hartley Sweeten440b2162013-05-23 13:02:45 -07001181static int usbduxsigma_pwm_period(struct comedi_device *dev,
1182 struct comedi_subdevice *s,
1183 unsigned int period)
Bernd Porrdd89e202011-07-30 11:15:02 +01001184{
H Hartley Sweeten440b2162013-05-23 13:02:45 -07001185 struct usbduxsigma_private *devpriv = dev->private;
Bernd Porrdd89e202011-07-30 11:15:02 +01001186 int fx2delay = 255;
1187
1188 if (period < MIN_PWM_PERIOD) {
Bernd Porrdd89e202011-07-30 11:15:02 +01001189 return -EAGAIN;
1190 } else {
H Hartley Sweeten440b2162013-05-23 13:02:45 -07001191 fx2delay = (period / (6 * 512 * 1000 / 33)) - 6;
H Hartley Sweeten38f4e422013-05-23 13:01:18 -07001192 if (fx2delay > 255)
Bernd Porrdd89e202011-07-30 11:15:02 +01001193 return -EAGAIN;
Bernd Porrdd89e202011-07-30 11:15:02 +01001194 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001195 devpriv->pwm_delay = fx2delay;
1196 devpriv->pwm_period = period;
Bernd Porrdd89e202011-07-30 11:15:02 +01001197 return 0;
1198}
1199
H Hartley Sweetena65b0912013-05-23 12:59:24 -07001200static int usbduxsigma_pwm_start(struct comedi_device *dev,
1201 struct comedi_subdevice *s)
Bernd Porrdd89e202011-07-30 11:15:02 +01001202{
H Hartley Sweetena65b0912013-05-23 12:59:24 -07001203 struct usbduxsigma_private *devpriv = dev->private;
1204 int ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001205
H Hartley Sweetena65b0912013-05-23 12:59:24 -07001206 if (devpriv->pwm_cmd_running)
Bernd Porrdd89e202011-07-30 11:15:02 +01001207 return 0;
Bernd Porrdd89e202011-07-30 11:15:02 +01001208
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001209 devpriv->dux_commands[1] = devpriv->pwm_delay;
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001210 ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_PWM_ON_CMD);
Bernd Porrdd89e202011-07-30 11:15:02 +01001211 if (ret < 0)
1212 return ret;
1213
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001214 memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz);
Bernd Porrdd89e202011-07-30 11:15:02 +01001215
H Hartley Sweetena65b0912013-05-23 12:59:24 -07001216 devpriv->pwm_cmd_running = 1;
H Hartley Sweeten9c922a92013-07-25 16:21:13 -07001217 ret = usbduxsigma_submit_pwm_urb(dev);
1218 if (ret < 0) {
1219 devpriv->pwm_cmd_running = 0;
1220 return ret;
1221 }
H Hartley Sweeten6028f4c2013-05-23 12:51:14 -07001222
Bernd Porrdd89e202011-07-30 11:15:02 +01001223 return 0;
1224}
1225
H Hartley Sweetenaa25b912013-07-29 17:46:07 -07001226static void usbduxsigma_pwm_pattern(struct comedi_device *dev,
1227 struct comedi_subdevice *s,
1228 unsigned int chan,
1229 unsigned int value,
1230 unsigned int sign)
Bernd Porrdd89e202011-07-30 11:15:02 +01001231{
H Hartley Sweetenab58a6e2013-05-23 12:58:43 -07001232 struct usbduxsigma_private *devpriv = dev->private;
1233 char pwm_mask = (1 << chan); /* DIO bit for the PWM data */
1234 char sgn_mask = (16 << chan); /* DIO bit for the sign */
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001235 char *buf = (char *)(devpriv->pwm_urb->transfer_buffer);
1236 int szbuf = devpriv->pwm_buf_sz;
H Hartley Sweetenab58a6e2013-05-23 12:58:43 -07001237 int i;
Bernd Porrdd89e202011-07-30 11:15:02 +01001238
Bernd Porrdd89e202011-07-30 11:15:02 +01001239 for (i = 0; i < szbuf; i++) {
H Hartley Sweetenab58a6e2013-05-23 12:58:43 -07001240 char c = *buf;
1241
1242 c &= ~pwm_mask;
Bernd Porrdd89e202011-07-30 11:15:02 +01001243 if (i < value)
H Hartley Sweetenab58a6e2013-05-23 12:58:43 -07001244 c |= pwm_mask;
1245 if (!sign)
1246 c &= ~sgn_mask;
1247 else
1248 c |= sgn_mask;
1249 *buf++ = c;
Bernd Porrdd89e202011-07-30 11:15:02 +01001250 }
Bernd Porrdd89e202011-07-30 11:15:02 +01001251}
1252
H Hartley Sweeten4ced8c62013-05-23 12:58:23 -07001253static int usbduxsigma_pwm_write(struct comedi_device *dev,
1254 struct comedi_subdevice *s,
1255 struct comedi_insn *insn,
1256 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +01001257{
H Hartley Sweeten4ced8c62013-05-23 12:58:23 -07001258 unsigned int chan = CR_CHAN(insn->chanspec);
Bernd Porrdd89e202011-07-30 11:15:02 +01001259
1260 /*
H Hartley Sweeten4ced8c62013-05-23 12:58:23 -07001261 * It doesn't make sense to support more than one value here
1262 * because it would just overwrite the PWM buffer.
Bernd Porrdd89e202011-07-30 11:15:02 +01001263 */
H Hartley Sweeten4ced8c62013-05-23 12:58:23 -07001264 if (insn->n != 1)
1265 return -EINVAL;
1266
1267 /*
1268 * The sign is set via a special INSN only, this gives us 8 bits
1269 * for normal operation, sign is 0 by default.
1270 */
H Hartley Sweetenaa25b912013-07-29 17:46:07 -07001271 usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0);
1272
1273 return insn->n;
Bernd Porrdd89e202011-07-30 11:15:02 +01001274}
1275
H Hartley Sweeten89397872013-05-23 12:57:45 -07001276static int usbduxsigma_pwm_config(struct comedi_device *dev,
1277 struct comedi_subdevice *s,
1278 struct comedi_insn *insn,
1279 unsigned int *data)
Bernd Porrdd89e202011-07-30 11:15:02 +01001280{
H Hartley Sweeten89397872013-05-23 12:57:45 -07001281 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweetenab58a6e2013-05-23 12:58:43 -07001282 unsigned int chan = CR_CHAN(insn->chanspec);
H Hartley Sweeten89397872013-05-23 12:57:45 -07001283
Bernd Porrdd89e202011-07-30 11:15:02 +01001284 switch (data[0]) {
1285 case INSN_CONFIG_ARM:
Bernd Porrdd89e202011-07-30 11:15:02 +01001286 /*
1287 * if not zero the PWM is limited to a certain time which is
1288 * not supported here
1289 */
1290 if (data[1] != 0)
1291 return -EINVAL;
H Hartley Sweetena65b0912013-05-23 12:59:24 -07001292 return usbduxsigma_pwm_start(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +01001293 case INSN_CONFIG_DISARM:
H Hartley Sweetenfd245192013-05-23 13:03:26 -07001294 return usbduxsigma_pwm_cancel(dev, s);
Bernd Porrdd89e202011-07-30 11:15:02 +01001295 case INSN_CONFIG_GET_PWM_STATUS:
H Hartley Sweeten89397872013-05-23 12:57:45 -07001296 data[1] = devpriv->pwm_cmd_running;
Bernd Porrdd89e202011-07-30 11:15:02 +01001297 return 0;
1298 case INSN_CONFIG_PWM_SET_PERIOD:
H Hartley Sweeten440b2162013-05-23 13:02:45 -07001299 return usbduxsigma_pwm_period(dev, s, data[1]);
Bernd Porrdd89e202011-07-30 11:15:02 +01001300 case INSN_CONFIG_PWM_GET_PERIOD:
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001301 data[1] = devpriv->pwm_period;
Bernd Porrdd89e202011-07-30 11:15:02 +01001302 return 0;
1303 case INSN_CONFIG_PWM_SET_H_BRIDGE:
H Hartley Sweeten89397872013-05-23 12:57:45 -07001304 /*
1305 * data[1] = value
1306 * data[2] = sign (for a relay)
1307 */
H Hartley Sweetenaa25b912013-07-29 17:46:07 -07001308 usbduxsigma_pwm_pattern(dev, s, chan, data[1], (data[2] != 0));
1309 return 0;
Bernd Porrdd89e202011-07-30 11:15:02 +01001310 case INSN_CONFIG_PWM_GET_H_BRIDGE:
1311 /* values are not kept in this driver, nothing to return */
1312 return -EINVAL;
1313 }
1314 return -EINVAL;
1315}
1316
H Hartley Sweeten9838f532013-05-23 12:55:08 -07001317static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan)
1318{
1319 struct usbduxsigma_private *devpriv = dev->private;
1320 uint8_t sysred;
1321 uint32_t val;
1322 int ret;
1323
1324 switch (chan) {
1325 default:
1326 case 0:
1327 sysred = 0; /* ADC zero */
1328 break;
1329 case 1:
1330 sysred = 1; /* ADC offset */
1331 break;
1332 case 2:
1333 sysred = 4; /* VCC */
1334 break;
1335 case 3:
1336 sysred = 8; /* temperature */
1337 break;
1338 case 4:
1339 sysred = 16; /* gain */
1340 break;
1341 case 5:
1342 sysred = 32; /* ref */
1343 break;
1344 }
1345
1346 devpriv->dux_commands[1] = 0x12; /* CONFIG0 */
1347 devpriv->dux_commands[2] = 0x80; /* CONFIG1: 2kHz sampling rate */
1348 devpriv->dux_commands[3] = 0x00; /* CONFIG3: diff. channels off */
1349 devpriv->dux_commands[4] = 0;
1350 devpriv->dux_commands[5] = 0;
1351 devpriv->dux_commands[6] = sysred;
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001352 ret = usbbuxsigma_send_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
H Hartley Sweeten9838f532013-05-23 12:55:08 -07001353 if (ret < 0)
1354 return ret;
1355
H Hartley Sweeten2bdd6d22013-05-23 13:06:18 -07001356 ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
H Hartley Sweeten9838f532013-05-23 12:55:08 -07001357 if (ret < 0)
1358 return ret;
1359
1360 /* 32 bits big endian from the A/D converter */
Ian Abbottf1d376b2013-10-16 14:40:38 +01001361 val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1)));
H Hartley Sweeten9838f532013-05-23 12:55:08 -07001362 val &= 0x00ffffff; /* strip status byte */
1363 val ^= 0x00800000; /* convert to unsigned */
1364
1365 return (int)val;
1366}
1367
H Hartley Sweeten46c87802013-05-23 12:57:25 -07001368static int usbduxsigma_firmware_upload(struct comedi_device *dev,
1369 const u8 *data, size_t size,
1370 unsigned long context)
1371{
1372 struct usb_device *usb = comedi_to_usb_dev(dev);
1373 uint8_t *buf;
1374 uint8_t *tmp;
1375 int ret;
1376
1377 if (!data)
1378 return 0;
1379
1380 if (size > FIRMWARE_MAX_LEN) {
1381 dev_err(dev->class_dev, "firmware binary too large for FX2\n");
1382 return -ENOMEM;
1383 }
1384
1385 /* we generate a local buffer for the firmware */
1386 buf = kmemdup(data, size, GFP_KERNEL);
1387 if (!buf)
1388 return -ENOMEM;
1389
1390 /* we need a malloc'ed buffer for usb_control_msg() */
1391 tmp = kmalloc(1, GFP_KERNEL);
1392 if (!tmp) {
1393 kfree(buf);
1394 return -ENOMEM;
1395 }
1396
1397 /* stop the current firmware on the device */
1398 *tmp = 1; /* 7f92 to one */
1399 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1400 USBDUXSUB_FIRMWARE,
1401 VENDOR_DIR_OUT,
1402 USBDUXSUB_CPUCS, 0x0000,
1403 tmp, 1,
1404 BULK_TIMEOUT);
1405 if (ret < 0) {
1406 dev_err(dev->class_dev, "can not stop firmware\n");
1407 goto done;
1408 }
1409
1410 /* upload the new firmware to the device */
1411 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1412 USBDUXSUB_FIRMWARE,
1413 VENDOR_DIR_OUT,
1414 0, 0x0000,
1415 buf, size,
1416 BULK_TIMEOUT);
1417 if (ret < 0) {
1418 dev_err(dev->class_dev, "firmware upload failed\n");
1419 goto done;
1420 }
1421
1422 /* start the new firmware on the device */
1423 *tmp = 0; /* 7f92 to zero */
1424 ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0),
1425 USBDUXSUB_FIRMWARE,
1426 VENDOR_DIR_OUT,
1427 USBDUXSUB_CPUCS, 0x0000,
1428 tmp, 1,
1429 BULK_TIMEOUT);
1430 if (ret < 0)
1431 dev_err(dev->class_dev, "can not start firmware\n");
1432
1433done:
1434 kfree(tmp);
1435 kfree(buf);
1436 return ret;
1437}
1438
H Hartley Sweetena59a28a2013-05-23 12:51:56 -07001439static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev)
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001440{
H Hartley Sweetena59a28a2013-05-23 12:51:56 -07001441 struct usb_device *usb = comedi_to_usb_dev(dev);
1442 struct usbduxsigma_private *devpriv = dev->private;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001443 struct urb *urb;
1444 int i;
1445
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001446 devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001447 devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL);
1448 devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL);
1449 devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb),
1450 GFP_KERNEL);
1451 devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb),
1452 GFP_KERNEL);
H Hartley Sweeten315a2762013-07-29 17:46:46 -07001453 if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf ||
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001454 !devpriv->ai_urbs || !devpriv->ao_urbs)
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001455 return -ENOMEM;
1456
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001457 for (i = 0; i < devpriv->n_ai_urbs; i++) {
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001458 /* one frame: 1ms */
1459 urb = usb_alloc_urb(1, GFP_KERNEL);
1460 if (!urb)
1461 return -ENOMEM;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001462 devpriv->ai_urbs[i] = urb;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001463 urb->dev = usb;
1464 /* will be filled later with a pointer to the comedi-device */
1465 /* and ONLY then the urb should be submitted */
1466 urb->context = NULL;
H Hartley Sweetenb509a762013-07-29 17:43:55 -07001467 urb->pipe = usb_rcvisocpipe(usb, 6);
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001468 urb->transfer_flags = URB_ISO_ASAP;
1469 urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL);
1470 if (!urb->transfer_buffer)
1471 return -ENOMEM;
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -07001472 urb->complete = usbduxsigma_ai_urb_complete;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001473 urb->number_of_packets = 1;
1474 urb->transfer_buffer_length = SIZEINBUF;
1475 urb->iso_frame_desc[0].offset = 0;
1476 urb->iso_frame_desc[0].length = SIZEINBUF;
1477 }
1478
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001479 for (i = 0; i < devpriv->n_ao_urbs; i++) {
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001480 /* one frame: 1ms */
1481 urb = usb_alloc_urb(1, GFP_KERNEL);
1482 if (!urb)
1483 return -ENOMEM;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001484 devpriv->ao_urbs[i] = urb;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001485 urb->dev = usb;
1486 /* will be filled later with a pointer to the comedi-device */
1487 /* and ONLY then the urb should be submitted */
1488 urb->context = NULL;
H Hartley Sweetenb509a762013-07-29 17:43:55 -07001489 urb->pipe = usb_sndisocpipe(usb, 2);
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001490 urb->transfer_flags = URB_ISO_ASAP;
1491 urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
1492 if (!urb->transfer_buffer)
1493 return -ENOMEM;
H Hartley Sweeten702cd2d2013-05-23 13:06:37 -07001494 urb->complete = usbduxsigma_ao_urb_complete;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001495 urb->number_of_packets = 1;
1496 urb->transfer_buffer_length = SIZEOUTBUF;
1497 urb->iso_frame_desc[0].offset = 0;
1498 urb->iso_frame_desc[0].length = SIZEOUTBUF;
1499 if (devpriv->high_speed)
1500 urb->interval = 8; /* uframes */
1501 else
1502 urb->interval = 1; /* frames */
1503 }
1504
H Hartley Sweeten1c379e92013-07-29 17:47:06 -07001505 if (devpriv->pwm_buf_sz) {
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001506 urb = usb_alloc_urb(0, GFP_KERNEL);
1507 if (!urb)
1508 return -ENOMEM;
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001509 devpriv->pwm_urb = urb;
H Hartley Sweeten1c379e92013-07-29 17:47:06 -07001510
1511 urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz,
1512 GFP_KERNEL);
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001513 if (!urb->transfer_buffer)
1514 return -ENOMEM;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001515 }
1516
1517 return 0;
1518}
1519
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001520static void usbduxsigma_free_usb_buffers(struct comedi_device *dev)
1521{
1522 struct usbduxsigma_private *devpriv = dev->private;
1523 struct urb *urb;
1524 int i;
1525
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001526 urb = devpriv->pwm_urb;
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001527 if (urb) {
1528 kfree(urb->transfer_buffer);
1529 usb_free_urb(urb);
1530 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001531 if (devpriv->ao_urbs) {
1532 for (i = 0; i < devpriv->n_ao_urbs; i++) {
1533 urb = devpriv->ao_urbs[i];
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001534 if (urb) {
1535 kfree(urb->transfer_buffer);
1536 usb_free_urb(urb);
1537 }
1538 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001539 kfree(devpriv->ao_urbs);
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001540 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001541 if (devpriv->ai_urbs) {
1542 for (i = 0; i < devpriv->n_ai_urbs; i++) {
1543 urb = devpriv->ai_urbs[i];
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001544 if (urb) {
1545 kfree(urb->transfer_buffer);
1546 usb_free_urb(urb);
1547 }
1548 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001549 kfree(devpriv->ai_urbs);
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001550 }
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001551 kfree(devpriv->insn_buf);
1552 kfree(devpriv->in_buf);
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001553 kfree(devpriv->dux_commands);
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001554}
1555
Ian Abbott807e65b2012-10-30 13:30:03 +00001556static int usbduxsigma_auto_attach(struct comedi_device *dev,
1557 unsigned long context_unused)
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001558{
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001559 struct usb_interface *intf = comedi_to_usb_interface(dev);
1560 struct usb_device *usb = comedi_to_usb_dev(dev);
1561 struct usbduxsigma_private *devpriv;
H Hartley Sweeten259ed072013-07-29 17:48:50 -07001562 struct comedi_subdevice *s;
1563 int offset;
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001564 int ret;
H Hartley Sweeten0b237282013-05-20 14:32:01 -07001565
H Hartley Sweeten0bdab502013-06-24 16:55:44 -07001566 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
H Hartley Sweeten9319d4a2013-05-23 12:49:26 -07001567 if (!devpriv)
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001568 return -ENOMEM;
Bernd Porrdd89e202011-07-30 11:15:02 +01001569
H Hartley Sweeten902add42013-05-23 12:48:41 -07001570 sema_init(&devpriv->sem, 1);
H Hartley Sweeten259ed072013-07-29 17:48:50 -07001571
H Hartley Sweeten902add42013-05-23 12:48:41 -07001572 usb_set_intfdata(intf, devpriv);
Bernd Porrdd89e202011-07-30 11:15:02 +01001573
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001574 devpriv->high_speed = (usb->speed == USB_SPEED_HIGH);
H Hartley Sweeten902add42013-05-23 12:48:41 -07001575 if (devpriv->high_speed) {
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001576 devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH;
1577 devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH;
H Hartley Sweeten1c379e92013-07-29 17:47:06 -07001578 devpriv->pwm_buf_sz = 512;
Bernd Porrdd89e202011-07-30 11:15:02 +01001579 } else {
H Hartley Sweetenaae2f262013-05-23 13:08:33 -07001580 devpriv->n_ai_urbs = NUMOFINBUFFERSFULL;
1581 devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL;
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001582 }
1583
H Hartley Sweetena59a28a2013-05-23 12:51:56 -07001584 ret = usbduxsigma_alloc_usb_buffers(dev);
H Hartley Sweeten1fc56e82013-05-23 12:55:28 -07001585 if (ret)
H Hartley Sweeten65989c02013-05-23 12:49:02 -07001586 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001587
H Hartley Sweeten259ed072013-07-29 17:48:50 -07001588 /* setting to alternate setting 3: enabling iso ep and bulk ep. */
1589 ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber,
1590 3);
1591 if (ret < 0) {
1592 dev_err(dev->class_dev,
1593 "could not set alternate setting 3 in high speed\n");
1594 return ret;
1595 }
1596
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001597 ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE,
1598 usbduxsigma_firmware_upload, 0);
1599 if (ret)
1600 return ret;
Bernd Porrdd89e202011-07-30 11:15:02 +01001601
H Hartley Sweeten259ed072013-07-29 17:48:50 -07001602 ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 4 : 3);
1603 if (ret)
1604 return ret;
1605
1606 /* Analog Input subdevice */
1607 s = &dev->subdevices[0];
1608 dev->read_subdev = s;
1609 s->type = COMEDI_SUBD_AI;
1610 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL;
1611 s->n_chan = NUMCHANNELS;
1612 s->len_chanlist = NUMCHANNELS;
1613 s->maxdata = 0x00ffffff;
1614 s->range_table = &usbduxsigma_ai_range;
1615 s->insn_read = usbduxsigma_ai_insn_read;
1616 s->do_cmdtest = usbduxsigma_ai_cmdtest;
1617 s->do_cmd = usbduxsigma_ai_cmd;
1618 s->cancel = usbduxsigma_ai_cancel;
1619
1620 /* Analog Output subdevice */
1621 s = &dev->subdevices[1];
1622 dev->write_subdev = s;
1623 s->type = COMEDI_SUBD_AO;
1624 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1625 s->n_chan = USBDUXSIGMA_NUM_AO_CHAN;
1626 s->len_chanlist = s->n_chan;
1627 s->maxdata = 0x00ff;
1628 s->range_table = &range_unipolar2_5;
1629 s->insn_write = usbduxsigma_ao_insn_write;
1630 s->insn_read = usbduxsigma_ao_insn_read;
1631 s->do_cmdtest = usbduxsigma_ao_cmdtest;
1632 s->do_cmd = usbduxsigma_ao_cmd;
1633 s->cancel = usbduxsigma_ao_cancel;
1634
1635 /* Digital I/O subdevice */
1636 s = &dev->subdevices[2];
1637 s->type = COMEDI_SUBD_DIO;
1638 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1639 s->n_chan = 24;
1640 s->maxdata = 1;
1641 s->range_table = &range_digital;
1642 s->insn_bits = usbduxsigma_dio_insn_bits;
1643 s->insn_config = usbduxsigma_dio_insn_config;
1644
1645 if (devpriv->high_speed) {
1646 /* Timer / pwm subdevice */
1647 s = &dev->subdevices[3];
1648 s->type = COMEDI_SUBD_PWM;
1649 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
1650 s->n_chan = 8;
1651 s->maxdata = devpriv->pwm_buf_sz;
1652 s->insn_write = usbduxsigma_pwm_write;
1653 s->insn_config = usbduxsigma_pwm_config;
1654
1655 usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
1656 }
1657
1658 offset = usbduxsigma_getstatusinfo(dev, 0);
1659 if (offset < 0)
1660 dev_err(dev->class_dev,
1661 "Communication to USBDUXSIGMA failed! Check firmware and cabling\n");
1662
1663 dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset);
1664
1665 return 0;
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001666}
Bernd Porrdd89e202011-07-30 11:15:02 +01001667
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001668static void usbduxsigma_detach(struct comedi_device *dev)
1669{
H Hartley Sweeten137beb72013-05-23 12:55:48 -07001670 struct usb_interface *intf = comedi_to_usb_interface(dev);
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001671 struct usbduxsigma_private *devpriv = dev->private;
1672
H Hartley Sweeten1da43902013-07-29 17:47:44 -07001673 usb_set_intfdata(intf, NULL);
1674
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001675 if (!devpriv)
1676 return;
1677
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001678 down(&devpriv->sem);
H Hartley Sweeten71d7e1e2013-07-29 17:47:26 -07001679
1680 /* force unlink all urbs */
1681 usbduxsigma_ai_stop(dev, 1);
1682 usbduxsigma_ao_stop(dev, 1);
1683 usbduxsigma_pwm_stop(dev, 1);
1684
H Hartley Sweetene0b12e62013-05-23 12:56:36 -07001685 usbduxsigma_free_usb_buffers(dev);
H Hartley Sweeten71d7e1e2013-07-29 17:47:26 -07001686
H Hartley Sweeten1823fcb2013-05-23 12:49:50 -07001687 up(&devpriv->sem);
1688}
1689
1690static struct comedi_driver usbduxsigma_driver = {
1691 .driver_name = "usbduxsigma",
1692 .module = THIS_MODULE,
1693 .auto_attach = usbduxsigma_auto_attach,
1694 .detach = usbduxsigma_detach,
1695};
1696
1697static int usbduxsigma_usb_probe(struct usb_interface *intf,
1698 const struct usb_device_id *id)
1699{
H Hartley Sweeten5f1d72e2013-05-23 12:56:59 -07001700 return comedi_usb_auto_config(intf, &usbduxsigma_driver, 0);
Bernd Porrdd89e202011-07-30 11:15:02 +01001701}
1702
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001703static const struct usb_device_id usbduxsigma_usb_table[] = {
1704 { USB_DEVICE(0x13d8, 0x0020) },
1705 { USB_DEVICE(0x13d8, 0x0021) },
1706 { USB_DEVICE(0x13d8, 0x0022) },
1707 { }
Bernd Porrdd89e202011-07-30 11:15:02 +01001708};
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001709MODULE_DEVICE_TABLE(usb, usbduxsigma_usb_table);
Bernd Porrdd89e202011-07-30 11:15:02 +01001710
H Hartley Sweetenb7418f42012-06-20 12:01:27 -07001711static struct usb_driver usbduxsigma_usb_driver = {
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001712 .name = "usbduxsigma",
1713 .probe = usbduxsigma_usb_probe,
H Hartley Sweeten9319d4a2013-05-23 12:49:26 -07001714 .disconnect = comedi_usb_auto_unconfig,
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001715 .id_table = usbduxsigma_usb_table,
Bernd Porrdd89e202011-07-30 11:15:02 +01001716};
H Hartley Sweetenb7418f42012-06-20 12:01:27 -07001717module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
Bernd Porrdd89e202011-07-30 11:15:02 +01001718
H Hartley Sweetenab5455a2012-06-20 12:02:15 -07001719MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
1720MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
Bernd Porrdd89e202011-07-30 11:15:02 +01001721MODULE_LICENSE("GPL");
Tim Gardnera1d95cf2012-08-16 11:19:11 -06001722MODULE_FIRMWARE(FIRMWARE);