Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

comedi: comedi_test: add a DIO subdevice

The fake "comedi_test" device currently has two subdevices: an analog
input subdevice, and an analog output subdevice. To make it a bit more
useful for testing, add a third subdevice for digital I/O.

The new DIO subdevice has 32 channels with each channel individually
programmable as an input or an output. To add a bit of interaction,
channels 0 to 15 are wired to channels 16 to 31 (0 to 16, 1 to 17,
etc.), and the state of each wire can be read back on both of the
channels connected to it. The outputs are modelled as NPN open
collector outputs with a pull-up resistor on the wire, so the state of
each wire (and the value read back from each channel connected to it)
will be logic level 1 unless either channel is configured as an output
at logic level 0.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20251210124455.69131-1-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ian Abbott and committed by
Greg Kroah-Hartman
b842f8c6 d63cf1ee

+49 -1
+49 -1
drivers/comedi/drivers/comedi_test.c
··· 692 692 return -EINVAL; 693 693 } 694 694 695 + static int waveform_dio_insn_bits(struct comedi_device *dev, 696 + struct comedi_subdevice *s, 697 + struct comedi_insn *insn, 698 + unsigned int *data) 699 + { 700 + u32 driven_low; 701 + u16 wires; 702 + 703 + /* Update the channel outputs. */ 704 + comedi_dio_update_state(s, data); 705 + /* 706 + * We are modelling the outputs as NPN open collector (0 = driven low, 707 + * 1 = high impedance), with the lower 16 channels wired to the upper 708 + * 16 channels in pairs (0 to 16, 1 to 17, ..., 15 to 31), with a 709 + * pull-up resistor on each wire. When reading back each channel, we 710 + * read back the state of the wire to which it is connected. 711 + * 712 + * The state of each wire and the value read back from both channels 713 + * connected to it will be logic 1 unless either channel connected to 714 + * the wire is configured as an output in the logic 0 state. 715 + */ 716 + driven_low = s->io_bits & ~s->state; 717 + wires = 0xFFFF & ~driven_low & ~(driven_low >> 16); 718 + /* Read back the state of the wires for each pair of channels. */ 719 + data[1] = wires | (wires << 16); 720 + 721 + return insn->n; 722 + } 723 + 724 + static int waveform_dio_insn_config(struct comedi_device *dev, 725 + struct comedi_subdevice *s, 726 + struct comedi_insn *insn, 727 + unsigned int *data) 728 + { 729 + /* configure each channel as input or output individually */ 730 + return comedi_dio_insn_config(dev, s, insn, data, 0); 731 + } 732 + 695 733 static int waveform_common_attach(struct comedi_device *dev, 696 734 int amplitude, int period) 697 735 { ··· 745 707 devpriv->wf_amplitude = amplitude; 746 708 devpriv->wf_period = period; 747 709 748 - ret = comedi_alloc_subdevices(dev, 2); 710 + ret = comedi_alloc_subdevices(dev, 3); 749 711 if (ret) 750 712 return ret; 751 713 ··· 783 745 /* Our default loopback value is just a 0V flatline */ 784 746 for (i = 0; i < s->n_chan; i++) 785 747 devpriv->ao_loopbacks[i] = s->maxdata / 2; 748 + 749 + s = &dev->subdevices[2]; 750 + /* digital input/output subdevice */ 751 + s->type = COMEDI_SUBD_DIO; 752 + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 753 + s->n_chan = 32; 754 + s->maxdata = 1; 755 + s->range_table = &range_digital; 756 + s->insn_bits = waveform_dio_insn_bits; 757 + s->insn_config = waveform_dio_insn_config; 786 758 787 759 devpriv->dev = dev; 788 760 timer_setup(&devpriv->ai_timer, waveform_ai_timer, 0);