STRUCT COMEDI_SUBDEVICE(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

✨ NAME ✨

okay so welcome to the struct comedi_subdevice(9) page from the Kernel API Manual β€” this is the one that explains the working data for a COMEDI subdevice, and honestly it's giving main-character energy for every subdevice in the system. πŸ’…

struct comedi_subdevice β€” working data for a COMEDI subdevice. That's the whole vibe: this struct is the control center for one subdevice, and every low-level driver is gonna be poking at it. πŸŽ€


🌸 SYNOPSIS 🌸

here's the whole struct, bestie β€” every field is here exactly as the kernel declares it, no cap:

       struct comedi_subdevice {
           struct comedi_device *device;
           int index;
           int type;
           int n_chan;
           int subdev_flags;
           int len_chanlist;
           void *private;
           struct comedi_async *async;
           void *lock;
           void *busy;
           unsigned int runflags;
           spinlock_t spin_lock;
           unsigned int io_bits;
           unsigned int maxdata;
           const unsigned int *maxdata_list;
           const struct comedi_lrange *range_table;
           const struct comedi_lrange *const *range_table_list;
           unsigned int *chanlist;
           int (*insn_read)(struct comedi_device *dev, struct comedi_subdevice
       *s, struct comedi_insn *insn, unsigned int *data);
           int (*insn_write)(struct comedi_device *dev, struct comedi_subdevice
       *s, struct comedi_insn *insn, unsigned int *data);
           int (*insn_bits)(struct comedi_device *dev, struct comedi_subdevice
       *s, struct comedi_insn *insn, unsigned int *data);
           int (*insn_config)(struct comedi_device *dev, struct
       comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data);
           int (*do_cmd)(struct comedi_device *dev, struct comedi_subdevice
       *s);
           int (*do_cmdtest)(struct comedi_device *dev, struct comedi_subdevice
       *s, struct comedi_cmd *cmd);
           int (*poll)(struct comedi_device *dev, struct comedi_subdevice *s);
           int (*cancel)(struct comedi_device *dev, struct comedi_subdevice
       *s);
           int (*buf_change)(struct comedi_device *dev, struct comedi_subdevice
       *s);
           void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s,
       void *data, unsigned int num_bytes, unsigned int start_chan_index);
           enum dma_data_direction async_dma_dir;
           unsigned int state;
           struct device *class_dev;
           int minor;
           unsigned int *readback;
        };

πŸŽ€ Members πŸŽ€

okay, it's member-by-member tea time. every field, every default, every little "initialized by" note β€” we are not skipping a single one. 🫢

bestie, do not sleep on the parentheticals β€” they tell you who initializes what and when. πŸ‘€
  • device β€” the COMEDI device to which this subdevice belongs. (Initialized by comedi_alloc_subdevices.) ✨
  • index β€” the index of this subdevice within device's array of subdevices. (Initialized by comedi_alloc_subdevices.) πŸ”’
  • type β€” the type of subdevice from enum comedi_subdevice_type. (Initialized by the low-level driver.) 🏷️
  • n_chan β€” how many channels the subdevice supports. (Initialized by the low-level driver.) 🎚️
  • subdev_flags β€” the various "SDF" flags indicating aspects of the subdevice to the COMEDI core and user application. (Initialized by the low-level driver.) 🚩
  • len_chanlist β€” maximum length of a channel list if the subdevice supports asynchronous acquisition commands. (Optionally initialized by the low-level driver, or changed from 0 to 1 during post-configuration.) πŸ“
  • private β€” private data pointer which is either set by the low-level driver itself, or by a call to comedi_alloc_spriv which allocates storage. In the latter case, the storage is automatically freed after the low-level driver's "detach" handler is called for the device. (Initialized by the low-level driver.) πŸ”’
  • async β€” pointer to struct comedi_async if the subdevice supports asynchronous acquisition commands. (Allocated and initialized during post-configuration if needed.) ⚑
  • lock β€” pointer to a file object that performed a COMEDI_LOCK ioctl on the subdevice. (Initially NULL.) πŸ”
  • busy β€” pointer to a file object that is performing an asynchronous acquisition command on the subdevice. (Initially NULL.) 🚦
  • runflags β€” internal flags for use by the COMEDI core, mostly indicating whether an asynchronous acquisition command is running. πŸƒ
  • spin_lock β€” generic spin-lock for use by the COMEDI core and the low-level driver. (Initialized by comedi_alloc_subdevices.) πŸŒ€
  • io_bits β€” bit-mask indicating the channel directions for a DIO subdevice with no more than 32 channels. A '1' at a bit position indicates the corresponding channel is configured as an output. (Initialized by the low-level driver for a DIO subdevice. Forced to all-outputs during post-configuration for a digital output subdevice.) 🧭
  • maxdata β€” if non-zero, this is the maximum raw data value of each channel. If zero, the maximum data value is channel-specific. (Initialized by the low-level driver.) πŸ”’
  • maxdata_list β€” if the maximum data value is channel-specific, this points to an array of maximum data values indexed by channel index. (Initialized by the low-level driver.) πŸ“‹
  • range_table β€” if non-NULL, this points to a COMEDI range table for the subdevice. If NULL, the range table is channel-specific. (Initialized by the low-level driver, will be set to an "invalid" range table during post-configuration if range_table and range_table_list are both NULL.) 🌈
  • range_table_list β€” if the COMEDI range table is channel-specific, this points to an array of pointers to COMEDI range tables indexed by channel number. (Initialized by the low-level driver.) πŸ—‚οΈ
  • chanlist β€” not used. literally just vibing. πŸ’€
  • insn_read β€” optional pointer to a handler for the INSN_READ instruction. (Initialized by the low-level driver, or set to a default handler during post-configuration.) πŸ“–
  • insn_write β€” optional pointer to a handler for the INSN_WRITE instruction. (Initialized by the low-level driver, or set to a default handler during post-configuration.) ✍️
  • insn_bits β€” optional pointer to a handler for the INSN_BITS instruction for a digital input, digital output or digital input/output subdevice. (Initialized by the low-level driver, or set to a default handler during post-configuration.) πŸ”˜
  • insn_config β€” optional pointer to a handler for the INSN_CONFIG instruction. (Initialized by the low-level driver, or set to a default handler during post-configuration.) βš™οΈ
  • do_cmd β€” if the subdevice supports asynchronous acquisition commands, this points to a handler to set it up in hardware. (Initialized by the low-level driver.) πŸ› οΈ
  • do_cmdtest β€” if the subdevice supports asynchronous acquisition commands, this points to a handler used to check and possibly tweak a prospective acquisition command without setting it up in hardware. (Initialized by the low-level driver.) πŸ§ͺ
  • poll β€” if the subdevice supports asynchronous acquisition commands, this is an optional pointer to a handler for the COMEDI_POLL ioctl which instructs the low-level driver to synchronize buffers. (Initialized by the low-level driver if needed.) πŸ“‘
  • cancel β€” if the subdevice supports asynchronous acquisition commands, this points to a handler used to terminate a running command. (Initialized by the low-level driver.) πŸ›‘
  • buf_change β€” if the subdevice supports asynchronous acquisition commands, this is an optional pointer to a handler that is called when the data buffer for handling asynchronous commands is allocated or reallocated. (Initialized by the low-level driver if needed.) πŸ”„
  • munge β€” if the subdevice supports asynchronous acquisition commands and uses DMA to transfer data from the hardware to the acquisition buffer, this points to a function used to "munge" the data values from the hardware into the format expected by COMEDI. (Initialized by the low-level driver if needed.) πŸͺ„
  • async_dma_dir β€” if the subdevice supports asynchronous acquisition commands and uses DMA to transfer data from the hardware to the acquisition buffer, this sets the DMA direction for the buffer. (initialized to DMA_NONE by comedi_alloc_subdevices and changed by the low-level driver if necessary.) 🧲
  • state β€” handy bit-mask indicating the output states for a DIO or digital output subdevice with no more than 32 channels. (Initialized by the low-level driver.) πŸ’‘
  • class_dev β€” if the subdevice supports asynchronous acquisition commands, this points to a sysfs comediX_subdY device where X is the minor device number of the COMEDI device and Y is the subdevice number. The minor device number for the sysfs device is allocated dynamically in the range 48 to 255. This is used to allow the COMEDI device to be opened with a different default read or write subdevice. (Allocated during post-configuration if needed.) 🏠
  • minor β€” if class_dev is set, this is its dynamically allocated minor device number. (Set during post-configuration if necessary.) πŸ”’
  • readback β€” optional pointer to memory allocated by comedi_alloc_subdev_readback used to hold the values written to analog output channels so they can be read back. The storage is automatically freed after the low-level driver's "detach" handler is called for the device. (Initialized by the low-level driver.) πŸ“

πŸ’– Description πŸ’–

okay so real talk: this is the main control structure for a COMEDI subdevice. If the subdevice supports asynchronous acquisition commands, additional information is stored in the struct comedi_async pointed to by async. πŸ¦‹

Most of the subdevice is initialized by the low-level driver's "attach" or "auto_attach" handlers, but parts of it are initialized by comedi_alloc_subdevices, and other parts are initialized during post-configuration on return from that handler. 🧚

A low-level driver that sets insn_bits for a digital input, digital output, or DIO subdevice may leave insn_read and insn_write uninitialized, in which case they will be set to a default handler during post-configuration that uses insn_bits to emulate the INSN_READ and INSN_WRITE instructions. πŸ‘‘

🌸 to be continued β€” part 2 is next, bestie. 🌸

✨ SEE ALSO ✨

okay bestie, this is the part where we go "and if you liked that, you have got to meet these other pages" πŸ’… it's basically the friend group of the comedi subsystem, and honestly every single one of them is iconic in their own way 🫢


okay that's genuinely the whole page!! go touch some registers, hydrate, and remember: read your comedidev.h πŸ¦‹

this lil page came from the kernel source dir ./include/linux/comedi, dated October 2026, and it's all about struct comedi_subdevice(9) β€” mwah, bye bestie πŸ’œβœ¨πŸŽ€

πŸ“¦ where this page comes from