return ret;
}
-/* force unlink, is called by comedi */
static int usbdux_ao_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct usbdux_private *this_usbduxsub = dev->private;
- int res = 0;
-
- if (!this_usbduxsub)
- return -EFAULT;
+ struct usbdux_private *devpriv = dev->private;
+ int ret = 0;
/* prevent other CPUs from submitting a command just now */
- down(&this_usbduxsub->sem);
+ down(&devpriv->sem);
/* unlink only if it is really running */
- res = usbdux_ao_stop(dev, this_usbduxsub->ao_cmd_running);
- up(&this_usbduxsub->sem);
- return res;
+ ret = usbdux_ao_stop(dev, devpriv->ao_cmd_running);
+ up(&devpriv->sem);
+
+ return ret;
}
static void usbduxsub_ao_isoc_irq(struct urb *urb)
}
static int usbdux_ai_inttrig(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int trignum)
+ struct comedi_subdevice *s,
+ unsigned int trignum)
{
- int ret;
- struct usbdux_private *this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
+ struct usbdux_private *devpriv = dev->private;
+ int ret = -EINVAL;
- down(&this_usbduxsub->sem);
+ down(&devpriv->sem);
- if (trignum != 0) {
- up(&this_usbduxsub->sem);
- return -EINVAL;
- }
- if (!(this_usbduxsub->ai_cmd_running)) {
- this_usbduxsub->ai_cmd_running = 1;
+ if (trignum != 0)
+ goto ai_trig_exit;
+
+ if (!devpriv->ai_cmd_running) {
+ devpriv->ai_cmd_running = 1;
ret = usbduxsub_submit_inurbs(dev);
if (ret < 0) {
- this_usbduxsub->ai_cmd_running = 0;
- up(&this_usbduxsub->sem);
- return ret;
+ devpriv->ai_cmd_running = 0;
+ goto ai_trig_exit;
}
s->async->inttrig = NULL;
+ } else {
+ ret = -EBUSY;
}
- up(&this_usbduxsub->sem);
- return 1;
+
+ai_trig_exit:
+ up(&devpriv->sem);
+ return ret;
}
static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct usbdux_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int chan, range;
- int i, ret;
- struct usbdux_private *this_usbduxsub = dev->private;
- int result;
-
- if (!this_usbduxsub)
- return -EFAULT;
+ int len = cmd->chanlist_len;
+ int ret = -EBUSY;
+ int i;
/* block other CPUs from starting an ai_cmd */
- down(&this_usbduxsub->sem);
- if (this_usbduxsub->ai_cmd_running) {
- up(&this_usbduxsub->sem);
- return -EBUSY;
- }
+ down(&devpriv->sem);
+
+ if (devpriv->ai_cmd_running)
+ goto ai_cmd_exit;
+
/* set current channel of the running acquisition to zero */
s->async->cur_chan = 0;
- this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
- for (i = 0; i < cmd->chanlist_len; ++i) {
- chan = CR_CHAN(cmd->chanlist[i]);
- range = CR_RANGE(cmd->chanlist[i]);
+ devpriv->dux_commands[1] = len;
+ for (i = 0; i < len; ++i) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+
if (i >= NUMCHANNELS)
break;
- this_usbduxsub->dux_commands[i + 2] =
- create_adc_command(chan, range);
- }
- result = send_dux_commands(dev, SENDADCOMMANDS);
- if (result < 0) {
- up(&this_usbduxsub->sem);
- return result;
+ devpriv->dux_commands[i + 2] = create_adc_command(chan, range);
}
- if (this_usbduxsub->high_speed) {
+ ret = send_dux_commands(dev, SENDADCOMMANDS);
+ if (ret < 0)
+ goto ai_cmd_exit;
+
+ if (devpriv->high_speed) {
/*
* every channel gets a time window of 125us. Thus, if we
* sample all 8 channels we need 1ms. If we sample only one
* channel we need only 125us
*/
- this_usbduxsub->ai_interval = 1;
+ devpriv->ai_interval = 1;
/* find a power of 2 for the interval */
- while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
- this_usbduxsub->ai_interval =
- (this_usbduxsub->ai_interval) * 2;
- }
- this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
- (this_usbduxsub->
- ai_interval));
+ while (devpriv->ai_interval < len)
+ devpriv->ai_interval *= 2;
+
+ devpriv->ai_timer = cmd->scan_begin_arg /
+ (125000 * devpriv->ai_interval);
} else {
/* interval always 1ms */
- this_usbduxsub->ai_interval = 1;
- this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
+ devpriv->ai_interval = 1;
+ devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
}
- if (this_usbduxsub->ai_timer < 1) {
- up(&this_usbduxsub->sem);
- return -EINVAL;
+ if (devpriv->ai_timer < 1) {
+ ret = -EINVAL;
+ goto ai_cmd_exit;
}
- this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+
+ devpriv->ai_counter = devpriv->ai_timer;
if (cmd->stop_src == TRIG_COUNT) {
/* data arrives as one packet */
- this_usbduxsub->ai_sample_count = cmd->stop_arg;
- this_usbduxsub->ai_continous = 0;
+ devpriv->ai_sample_count = cmd->stop_arg;
+ devpriv->ai_continous = 0;
} else {
/* continous acquisition */
- this_usbduxsub->ai_continous = 1;
- this_usbduxsub->ai_sample_count = 0;
+ devpriv->ai_continous = 1;
+ devpriv->ai_sample_count = 0;
}
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
- this_usbduxsub->ai_cmd_running = 1;
+ devpriv->ai_cmd_running = 1;
ret = usbduxsub_submit_inurbs(dev);
if (ret < 0) {
- this_usbduxsub->ai_cmd_running = 0;
+ devpriv->ai_cmd_running = 0;
/* fixme: unlink here?? */
- up(&this_usbduxsub->sem);
- return ret;
+ goto ai_cmd_exit;
}
s->async->inttrig = NULL;
} else {
/* wait for an internal signal */
s->async->inttrig = usbdux_ai_inttrig;
}
- up(&this_usbduxsub->sem);
- return 0;
+
+ai_cmd_exit:
+ up(&devpriv->sem);
+
+ return ret;
}
/* Mode 0 is used to get a single conversion on demand */
static int usbdux_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct usbdux_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ int ret = -EBUSY;
int i;
- unsigned int one = 0;
- int chan, range;
- int err;
- struct usbdux_private *this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return 0;
+ down(&devpriv->sem);
- down(&this_usbduxsub->sem);
- if (this_usbduxsub->ai_cmd_running) {
- up(&this_usbduxsub->sem);
- return 0;
- }
+ if (devpriv->ai_cmd_running)
+ goto ai_read_exit;
- /* sample one channel */
- chan = CR_CHAN(insn->chanspec);
- range = CR_RANGE(insn->chanspec);
/* set command for the first channel */
- this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
+ devpriv->dux_commands[1] = create_adc_command(chan, range);
/* adc commands */
- err = send_dux_commands(dev, SENDSINGLEAD);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
- }
+ ret = send_dux_commands(dev, SENDSINGLEAD);
+ if (ret < 0)
+ goto ai_read_exit;
for (i = 0; i < insn->n; i++) {
- err = receive_dux_commands(dev, SENDSINGLEAD);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return 0;
- }
- one = le16_to_cpu(this_usbduxsub->insn_buffer[1]);
- if (CR_RANGE(insn->chanspec) <= 1)
- one = one ^ 0x800;
+ ret = receive_dux_commands(dev, SENDSINGLEAD);
+ if (ret < 0)
+ goto ai_read_exit;
+
+ val = le16_to_cpu(devpriv->insn_buffer[1]);
+
+ /* bipolar data is two's-complement */
+ if (comedi_range_is_bipolar(s, range))
+ val ^= ((s->maxdata + 1) >> 1);
- data[i] = one;
+ data[i] = val;
}
- up(&this_usbduxsub->sem);
- return i;
-}
-/************************************/
-/* analog out */
+ai_read_exit:
+ up(&devpriv->sem);
+
+ return ret ? ret : insn->n;
+}
static int usbdux_ao_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
+ struct usbdux_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
- int chan = CR_CHAN(insn->chanspec);
- struct usbdux_private *this_usbduxsub = dev->private;
- if (!this_usbduxsub)
- return -EFAULT;
-
- down(&this_usbduxsub->sem);
+ down(&devpriv->sem);
for (i = 0; i < insn->n; i++)
- data[i] = this_usbduxsub->out_buffer[chan];
+ data[i] = devpriv->out_buffer[chan];
+ up(&devpriv->sem);
- up(&this_usbduxsub->sem);
- return i;
+ return insn->n;
}
static int usbdux_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int i, err;
- int chan = CR_CHAN(insn->chanspec);
- struct usbdux_private *this_usbduxsub = dev->private;
+ struct usbdux_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val = devpriv->out_buffer[chan];
+ int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+ int ret = -EBUSY;
+ int i;
- if (!this_usbduxsub)
- return -EFAULT;
+ down(&devpriv->sem);
- down(&this_usbduxsub->sem);
- if (this_usbduxsub->ao_cmd_running) {
- up(&this_usbduxsub->sem);
- return 0;
- }
+ if (devpriv->ao_cmd_running)
+ goto ao_write_exit;
+
+ /* number of channels: 1 */
+ devpriv->dux_commands[1] = 1;
+ /* channel number */
+ devpriv->dux_commands[4] = chan << 6;
for (i = 0; i < insn->n; i++) {
- /* number of channels: 1 */
- this_usbduxsub->dux_commands[1] = 1;
+ val = data[i];
+
/* one 16 bit value */
- *((int16_t *) (this_usbduxsub->dux_commands + 2)) =
- cpu_to_le16(data[i]);
- this_usbduxsub->out_buffer[chan] = data[i];
- /* channel number */
- this_usbduxsub->dux_commands[4] = (chan << 6);
- err = send_dux_commands(dev, SENDDACOMMANDS);
- if (err < 0) {
- up(&this_usbduxsub->sem);
- return err;
- }
+ *p = cpu_to_le16(val);
+
+ ret = send_dux_commands(dev, SENDDACOMMANDS);
+ if (ret < 0)
+ goto ao_write_exit;
}
- up(&this_usbduxsub->sem);
+ devpriv->out_buffer[chan] = val;
- return i;
+ao_write_exit:
+ up(&devpriv->sem);
+
+ return ret ? ret : insn->n;
}
static int usbdux_ao_inttrig(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int trignum)
+ struct comedi_subdevice *s,
+ unsigned int trignum)
{
- int ret;
- struct usbdux_private *this_usbduxsub = dev->private;
+ struct usbdux_private *devpriv = dev->private;
+ int ret = -EINVAL;
- if (!this_usbduxsub)
- return -EFAULT;
+ down(&devpriv->sem);
- down(&this_usbduxsub->sem);
- if (trignum != 0) {
- up(&this_usbduxsub->sem);
- return -EINVAL;
- }
- if (!(this_usbduxsub->ao_cmd_running)) {
- this_usbduxsub->ao_cmd_running = 1;
+ if (trignum != 0)
+ goto ao_trig_exit;
+
+ if (!devpriv->ao_cmd_running) {
+ devpriv->ao_cmd_running = 1;
ret = usbduxsub_submit_outurbs(dev);
if (ret < 0) {
- this_usbduxsub->ao_cmd_running = 0;
- up(&this_usbduxsub->sem);
- return ret;
+ devpriv->ao_cmd_running = 0;
+ goto ao_trig_exit;
}
s->async->inttrig = NULL;
+ } else {
+ ret = -EBUSY;
}
- up(&this_usbduxsub->sem);
- return 1;
+
+ao_trig_exit:
+ up(&devpriv->sem);
+ return ret;
}
static int usbdux_ao_cmdtest(struct comedi_device *dev,
static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct usbdux_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- unsigned int chan, gain;
- int i, ret;
- struct usbdux_private *this_usbduxsub = dev->private;
+ int ret = -EBUSY;
+ int i;
- if (!this_usbduxsub)
- return -EFAULT;
+ down(&devpriv->sem);
- down(&this_usbduxsub->sem);
+ if (devpriv->ao_cmd_running)
+ goto ao_cmd_exit;
/* set current channel of the running acquisition to zero */
s->async->cur_chan = 0;
+
for (i = 0; i < cmd->chanlist_len; ++i) {
- chan = CR_CHAN(cmd->chanlist[i]);
- gain = CR_RANGE(cmd->chanlist[i]);
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+
if (i >= NUMOUTCHANNELS)
break;
- this_usbduxsub->dac_commands[i] = (chan << 6);
+
+ devpriv->dac_commands[i] = chan << 6;
}
/* we count in steps of 1ms (125us) */
/* 125us mode not used yet */
- if (0) { /* (this_usbduxsub->high_speed) */
+ if (0) { /* (devpriv->high_speed) */
/* 125us */
/* timing of the conversion itself: every 125 us */
- this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
+ devpriv->ao_timer = cmd->convert_arg / 125000;
} else {
/* 1ms */
/* timing of the scan: we get all channels at once */
- this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
- if (this_usbduxsub->ao_timer < 1) {
- up(&this_usbduxsub->sem);
- return -EINVAL;
+ devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
+ if (devpriv->ao_timer < 1) {
+ ret = -EINVAL;
+ goto ao_cmd_exit;
}
}
- this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+
+ devpriv->ao_counter = devpriv->ao_timer;
if (cmd->stop_src == TRIG_COUNT) {
/* not continuous */
/* counter */
/* high speed also scans everything at once */
- if (0) { /* (this_usbduxsub->high_speed) */
- this_usbduxsub->ao_sample_count =
- (cmd->stop_arg) * (cmd->scan_end_arg);
+ if (0) { /* (devpriv->high_speed) */
+ devpriv->ao_sample_count = cmd->stop_arg *
+ cmd->scan_end_arg;
} else {
/* there's no scan as the scan has been */
/* perf inside the FX2 */
/* data arrives as one packet */
- this_usbduxsub->ao_sample_count = cmd->stop_arg;
+ devpriv->ao_sample_count = cmd->stop_arg;
}
- this_usbduxsub->ao_continous = 0;
+ devpriv->ao_continous = 0;
} else {
/* continous acquisition */
- this_usbduxsub->ao_continous = 1;
- this_usbduxsub->ao_sample_count = 0;
+ devpriv->ao_continous = 1;
+ devpriv->ao_sample_count = 0;
}
if (cmd->start_src == TRIG_NOW) {
/* enable this acquisition operation */
- this_usbduxsub->ao_cmd_running = 1;
+ devpriv->ao_cmd_running = 1;
ret = usbduxsub_submit_outurbs(dev);
if (ret < 0) {
- this_usbduxsub->ao_cmd_running = 0;
+ devpriv->ao_cmd_running = 0;
/* fixme: unlink here?? */
- up(&this_usbduxsub->sem);
- return ret;
+ goto ao_cmd_exit;
}
s->async->inttrig = NULL;
} else {
s->async->inttrig = usbdux_ao_inttrig;
}
- up(&this_usbduxsub->sem);
- return 0;
+ao_cmd_exit:
+ up(&devpriv->sem);
+
+ return ret;
}
static int usbdux_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int chan = CR_CHAN(insn->chanspec);
-
- /* The input or output configuration of each digital line is
- * configured by a special insn_config instruction. chanspec
- * contains the channel to be changed, and data[0] contains the
- * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ unsigned int mask = 1 << CR_CHAN(insn->chanspec);
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
- s->io_bits |= 1 << chan; /* 1 means Out */
+ s->io_bits |= mask;
break;
case INSN_CONFIG_DIO_INPUT:
- s->io_bits &= ~(1 << chan);
+ s->io_bits &= ~mask;
break;
case INSN_CONFIG_DIO_QUERY:
- data[1] =
- (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
break;
default:
return -EINVAL;
break;
}
- /* we don't tell the firmware here as it would take 8 frames */
- /* to submit the information. We do it in the insn_bits. */
+
+ /*
+ * We don't tell the firmware here as it would take 8 frames
+ * to submit the information. We do it in the insn_bits.
+ */
return insn->n;
}