Specifications
Comedi
146 / 148
Typically, you will be able to implement most of the above-mentioned functionality by cut-and-paste from already existing
drivers. The mydriver_attach() function needs most of your attention, because it must correctly define and allocate the
(private and generic) data structures that are needed for this device. That is, each sub-device and each channel must get appro-
priate data fields, and an appropriate initialization. The good news, of course, is that Comedi provides the data structures and the
defines that fit very well with almost all DAQ functionalities found on interface cards. These can be found in the header files of
the include/linux/ directory.
Drivers with digital I/O subdevices should implement the following functions, setting the function pointers in the comedi_subdevice:
• insn_bits(): drivers set this if they have a function that supports reading and writing multiple bits in a digital I/O subdevice
at the same time. Most (if not all) of the drivers use this interface instead of insn_read and insn_write for DIO subdevices.
• insn_config(): implements INSN_CONFIG instructions. Currently used for configuring the direction of digital I/O lines,
although will eventually be used for generic configuration of drivers that is outside the scope of the currently defined Comedi
interface.
Finally, the device driver writer must implement the insn_read() and insn_write() functions for the analog channels on
the card:
• insn_read(): acquire the inputs on the board and transfer them to the software buffer of the driver.
• insn_write(): transfer data from the software buffer to the card, and execute the appropriate output conversions.
In some drivers, you want to catch interrupts, and/or want to use the INSN_INTTRIG instruction. In this case, you must provide
and register these callback functions.
Implementation of all of the above-mentioned functions requires perfect knowledge about the hardware registers and addresses
of the interface card. In general, you can find some inspiration in the already available device drivers, but don’t trust that blind
cut-and-paste will bring you far. . .
6.4 Callbacks, events and interrupts
Continuous acquisition is tyically an asynchronous activity: the function call that has set the acquisition in motion has returned
before the acquisition has finished (or even started). So, not only the acquired data must be sent back to the user’s buffer ‘in the
background’, but various types of asynchronous event handling can be needed during the acquisition:
• The hardware can generate some error or warning events.
• Normal functional interrupts are generated by the hardware, e.g., signalling the filling-up of the card’s hardware buffer, or the
end of an acquisition scan, etc.
• The device driver writer can register a driver-supplied ‘callback’ function, that is called at the end of each hardware interrupt
routine.
• Another driver-supplied callback function is executed when the user program launches an INSN_INTTRIG instruction. This
event handling is executed synchronously with the execution of the triggering instruction.
The interrupt handlers are registered through the functions mentioned before The event handling is done in the existing Comedi
drivers in statements such as this one:
s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR
It fills in the bits corresponding to particular events in the comedi_async data structure. The possible event bits are:
• COMEDI_CB_EOA: execute the callback at the ‘End-Of-Acquisition’ (or ‘End-Of-Output’).
• COMEDI_CB_EOS: execute the callback at the ‘End-Of-Scan’.
• COMEDI_CB_OVERFLOW: execute the callback when a buffer overflow or underflow has occurred.
• COMEDI_CB_ERROR: execute the callback at the occurrence of an (undetermined) error.