STRUCT COMEDI_SUBDEVICE(9)
β¨ 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 bycomedi_alloc_subdevices.) β¨indexβ the index of this subdevice withindevice's array of subdevices. (Initialized bycomedi_alloc_subdevices.) π’typeβ the type of subdevice fromenum 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 from0to1during post-configuration.) πprivateβ private data pointer which is either set by the low-level driver itself, or by a call tocomedi_alloc_sprivwhich 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 tostruct comedi_asyncif the subdevice supports asynchronous acquisition commands. (Allocated and initialized during post-configuration if needed.) β‘lockβ pointer to a file object that performed aCOMEDI_LOCKioctl on the subdevice. (InitiallyNULL.) πbusyβ pointer to a file object that is performing an asynchronous acquisition command on the subdevice. (InitiallyNULL.) π¦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 bycomedi_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. IfNULL, the range table is channel-specific. (Initialized by the low-level driver, will be set to an "invalid" range table during post-configuration ifrange_tableandrange_table_listare bothNULL.) π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 theINSN_READinstruction. (Initialized by the low-level driver, or set to a default handler during post-configuration.) πinsn_writeβ optional pointer to a handler for theINSN_WRITEinstruction. (Initialized by the low-level driver, or set to a default handler during post-configuration.) βοΈinsn_bitsβ optional pointer to a handler for theINSN_BITSinstruction 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 theINSN_CONFIGinstruction. (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 theCOMEDI_POLLioctl 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 toDMA_NONEbycomedi_alloc_subdevicesand 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 sysfscomediX_subdYdevice whereXis the minor device number of the COMEDI device andYis the subdevice number. The minor device number for the sysfs device is allocated dynamically in the range48to255. 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β ifclass_devis set, this is its dynamically allocated minor device number. (Set during post-configuration if necessary.) π’readbackβ optional pointer to memory allocated bycomedi_alloc_subdev_readbackused 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 π«Ά
- Kernel file
./include/linux/comedi/comedidev.hβ yes, the actual source file, go read it, it's giving main character energy π struct comedi_buf_page(9)β the buffer page struct, lowkey essential β¨struct comedi_buf_map(9)β mapping the buffer, no cap πΊοΈstruct comedi_async(9)β the async stuff, and you know async is where it gets spicy π₯enum comedi_cb(9)β callback flags, the little enum that could πstruct comedi_driver(9)β your driver's whole personality lives here πstruct comedi_device(9)β the device struct, the big one, the moment πstruct comedi_lrange(9)β the range struct, very demure, very mindful πcomedi_range_is_bipolar(9)β is it bipolar? let's check, bestie π¦comedi_range_is_unipolar(9)β or unipolar? fake it till you make it πcomedi_range_is_external(9)β or external?? the plot thickens πcomedi_chan_range_is_bipolar(9)β same vibe but per-channel, slay β¨comedi_chan_range_is_unipolar(9)β per-channel unipolar, we love consistency π«Άcomedi_chan_range_is_external(9)β per-channel external, obsessed honestly βcomedi_offset_munge(9)β the offset munge, and honestly the name alone ate πcomedi_bytes_per_sample(9)β bytes per sample, math but make it cute π§comedi_sample_shift(9)β the sample shift, shift it bestie π«comedi_bytes_to_samples(9)β converting bytes β samples, we been knew πcomedi_samples_to_bytes(9)β and samples β bytes, the other direction, obviously πcomedi_check_trigger_src(9)β check that trigger source, periodt πcomedi_check_trigger_is_unique(9)β make sure it's unique, no duplicates allowed πcomedi_check_trigger_arg_is(9)β arg equals check, validating fr fr βcomedi_check_trigger_arg_min(9)β arg minimum check, boundaries are hot πΈcomedi_check_trigger_arg_max(9)β arg maximum check, also boundaries, also hot π₯comedi_buf_n_bytes_ready(9)β how many bytes are ready? ask it β¨__comedi_request_region(9)β the underscore-underscore one, the inner circle πcomedi_request_region(9)β the public one, for the rest of us π«Άmodule_comedi_driver(9)β register that driver module, go off king π
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
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms