6.3.  Board-specific functionality

The comedi/drivers subdirectory contains the board-specific device driver code. Each new card must get an entry in this directory. Or extend the functionality of an already existing driver file if the new card is quite similar to that implemented in an already existing driver. For example, many of the National Instruments DAQ cards use the same driver files.

To help device driver writers, Comedi provides the skeleton of a new device driver, in the comedi/drivers/skel.c file. Before starting to write a new driver, make sure you understand this file, and compare it to what you find in the other already available board-specific files in the same directory.

The first thing you notice in skel.c is the documentation section: the Comedi documentation is partially generated automatically, from the information that is given in this section. So, please comply with the structure and the keywords provided as Comedi standards.

The second part of the device driver contains board-specific static data structure and defines: addresses of hardware registers; defines and function prototypes for functionality that is only used inside of the device driver for this board; the encoding of the types and number of available channels; PCI information; etc.

Each driver has to register two functions which are called when you load and unload your board's device driver (typically via a kernel module):

  mydriver_attach();
  mydriver_detach();

In the attach function, memory is allocated for the necessary data structures, all properties of a device and its subdevices are defined, and filled in in the generic Comedi data structures. As part of this, pointers to the low level instructions being supported by the subdevice have to be set, which define the basic functionality. In somewhat more detail, the mydriver_attach function must:

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 appropriate 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:

Finally, the device driver writer must implement the insn_read and insn_write functions for the analog channels on the card:

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…