File: comedikernelgeneric.html

package info (click to toggle)
comedilib 0.11.0%2B5-1.3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,544 kB
  • sloc: xml: 19,779; ansic: 14,719; sh: 5,679; cpp: 2,211; ruby: 1,658; perl: 700; makefile: 596; yacc: 439; lex: 86; python: 17
file content (322 lines) | stat: -rw-r--r-- 23,968 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>6.2.  Generic functionality</title><link rel="stylesheet" type="text/css" href="comedilib.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="index.html" title="Comedi"><link rel="up" href="driverwriting.html" title="6.  Writing a Comedi driver"><link rel="prev" href="driverwriting.html" title="6.  Writing a Comedi driver"><link rel="next" href="boardspecific.html" title="6.3.  Board-specific functionality"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">6.2. 
Generic functionality
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="driverwriting.html">Prev</a> </td><th width="60%" align="center">6. 
Writing a <acronym class="acronym">Comedi</acronym> driver
</th><td width="20%" align="right"> <a accesskey="n" href="boardspecific.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="comedikernelgeneric"></a>6.2. 
Generic functionality
</h3></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="comedikernelgeneric.html#driverdatastructures">6.2.1. 
Data structures
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#driversupportfunctions">6.2.2. 
Generic driver support functions
</a></span></dt></dl></div><p>
The major include files of the kernel-space part of <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> are:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
<code class="filename">include/linux/comedidev.h</code>: the
header file for kernel-only structures (device, subdevice, async
(i.e., buffer/event/interrupt/callback functionality for asynchronous
DAQ in a <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> command), driver, lrange), variables, inline functions
and constants.
</p></li><li class="listitem"><p>
<code class="filename">include/linux/comedi_rt.h</code>:
all the real-time stuff, such as management of ISR in RTAI and
RTLinux/Free, and spinlocks for atomic sections.
</p></li><li class="listitem"><p>
<code class="filename">include/linux/comedilib.h</code>: the header file for
the kernel library of <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> (<code class="systemitem">kcomedilib</code> module).
</p></li></ul></div><p>
</p><p>
From all the relevant <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> device driver code that is found in the
<code class="filename">comedi</code> kernel module source directory,
the <span class="strong"><strong>generic</strong></span> functionality is
contained in two parts:
 </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
A couple of <code class="filename">C</code> files contain the <span class="strong"><strong>infrastructural support</strong></span>.
From these <code class="filename">C</code> files, it's especially the
<code class="filename">comedi_fops.c</code> file that implements what makes
<a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> into what people want to use it for: a library that has
solved 90% of the DAQ device driver efforts, once and for all.
 </p></li><li class="listitem"><p>
For <span class="strong"><strong>real-time</strong></span> applications,
the subdirectory <code class="filename">kcomedilib</code>
implements an interface in the kernel that is similar to the <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a>
interface accessible through the
<a class="link" href="functionreference.html" title="5.4. Functions">user-space Comedi library</a>.
</p><p>
There are some differences in what is possible and/or needed
in kernel-space and in user-space, so the functionalities offered in
<code class="filename">kcomedilib</code> are not an exact copy
of the user-space library. For example, locking, interrupt handling,
real-time execution, callback handling, etc., are only available in
kernel-space.
 </p><p>
Most drivers don't make use (yet) of these real-time functionalities.
 </p></li></ul></div><p>
</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="driverdatastructures"></a>6.2.1. 
Data structures
</h4></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="comedikernelgeneric.html#comedilrange">6.2.1.1. 
<span class="type">comedi_lrange</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedisubdevice">6.2.1.2. 
<span class="type">comedi_subdevice</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedidevice">6.2.1.3. 
<span class="type">comedi_device</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comediasync">6.2.1.4. 
<span class="type">comedi_async</span>
</a></span></dt><dt><span class="section"><a href="comedikernelgeneric.html#comedidriver">6.2.1.5. 
<span class="type">comedi_driver</span>
</a></span></dt></dl></div><p>
This Section explains the generic data structures that a device driver
interacts with:
</p><pre class="programlisting">
typedef struct comedi_lrange_struct    <a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1.  comedi_lrange">comedi_lrange</a>;
typedef struct comedi_subdevice_struct <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a>;
typedef struct comedi_device_struct    <a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a>:
typedef struct comedi_async_struct     <a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4.  comedi_async">comedi_async</a>
typedef struct comedi_driver_struct    <a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5.  comedi_driver">comedi_driver</a>;
</pre><p>
They can be found in
<code class="filename">include/linux/comedidev.h</code>.
Most of the fields are filled in by the <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> infrastructure, but
there are still quite a handful that your driver must provide or use.
As for the user-level <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a>, each of the hierarchical layers has
its own data structures: range (<span class="type">comedi_lrange</span>),
subdevice, and device.
</p><p>
Note that these kernel-space data structures have similar names as
their
<a class="link" href="datatypesstructures.html" title="5.3.  Data types and structures">user-space equivalents</a>, but
they have a different (kernel-side) view on the DAQ problem and a
different meaning: they encode the interaction with the
<span class="emphasis"><em>hardware</em></span>, not with the <span class="emphasis"><em>user</em></span>.
</p><p>
However, the <span class="type"><a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a></span>
and <span class="type"><a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7.  comedi_cmd">comedi_cmd</a></span>
data structures are shared between user-space and kernel-space: this
should come as no surprise, since these data structures contain all
information that the user-space program must transfer to the
kernel-space driver for each acquisition.
</p><p>
In addition to these data entities that are also known at the user
level (device, sub-device, channel), the device driver level provides
two more data structures which the application programmer doesn't get
in touch with: the data structure
<span class="type"><a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5.  comedi_driver">comedi_driver</a></span>
that stores the device driver information that is relevant at the
operating system level, and the data structure
<span class="type"><a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4.  comedi_async">comedi_async</a></span> that stores the
information about all <span class="emphasis"><em>asynchronous</em></span> activities
(interrupts, callbacks and events).
</p><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedilrange"></a>6.2.1.1. 
<span class="type">comedi_lrange</span>
</h5></div></div></div><p>
The channel information is simple, since it contains only the signal
range information:
</p><pre class="programlisting">
struct comedi_lrange_struct{
  int           length;
  <a class="link" href="datatypesstructures.html#ref-type-comedi-krange" title="5.3.10.  comedi_krange">comedi_krange</a> range[GCC_ZERO_LENGTH_ARRAY];
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedisubdevice"></a>6.2.1.2. 
<span class="type">comedi_subdevice</span>
</h5></div></div></div><p>
The subdevice is the smallest <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> entity that can be used for
<span class="quote">“<span class="quote">stand-alone</span>”</span> DAQ, so it is no surprise that it is
quite big:
</p><pre class="programlisting">
struct comedi_subdevice_struct{
  int  type;
  int  n_chan;
  int  subdev_flags;
  int  len_chanlist;		/* maximum length of channel/gain list */

  void *private;

  <a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4.  comedi_async">comedi_async</a> *async;

  void         *lock;
  void         *busy;
  unsigned int runflags;

  int          io_bits;

  <a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> maxdata;       /* if maxdata==0, use list */
  <a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *maxdata_list; /* list is channel specific */

  unsigned int flags;
  unsigned int *flaglist;

  <a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1.  comedi_lrange">comedi_lrange</a> *range_table;
  <a class="link" href="comedikernelgeneric.html#comedilrange" title="6.2.1.1.  comedi_lrange">comedi_lrange</a> **range_table_list;

  unsigned int *chanlist;		/* driver-owned chanlist (not used) */

  int (*insn_read)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *);
  int (*insn_write)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *);
  int (*insn_bits)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *);
  int (*insn_config)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a> *,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *);

  int (*do_cmd)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *);
  int (*do_cmdtest)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *,<a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7.  comedi_cmd">comedi_cmd</a> *);
  int (*poll)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *);
  int (*cancel)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *);

  int (*buf_change)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *s,unsigned long new_size);
  void (*munge)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *, <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *s, void *data, unsigned int num_bytes, unsigned int start_chan_index );

  unsigned int state;
};
</pre><p>
The function pointers <em class="structfield"><code>insn_read</code></em> …
<em class="structfield"><code>cancel</code></em> .
offer (pointers to) the standardized
<a class="link" href="functionreference.html" title="5.4. Functions">user-visible API</a>
that every subdevice should offer; every device driver has to fill
in these functions with their board-specific implementations.
(Functionality for which <a class="ulink" href="http://www.comedi.org" target="_top"><acronym class="acronym">Comedi</acronym></a> provides generic functions will, by
definition, not show up in the device driver data structures.)
</p><p>
The <em class="structfield"><code>buf_change</code></em> and <em class="structfield"><code>munge</code></em>
function pointers offer functionality that is not visible to the user and for
which the device driver writer must provide a board-specific
implementation:
<code class="function">buf_change</code> is called when a change in the
data buffer requires handling; <code class="function">munge</code> transforms
different bit-representations of DAQ values, for example from
<span class="emphasis"><em>unsigned</em></span> to <span class="emphasis"><em>2's complement</em></span>.
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedidevice"></a>6.2.1.3. 
<span class="type">comedi_device</span>
</h5></div></div></div><p>
The last data structure stores the information at the
<span class="emphasis"><em>device</em></span> level:
</p><pre class="programlisting">
struct comedi_device_struct{
  int           use_count;
  <a class="link" href="comedikernelgeneric.html#comedidriver" title="6.2.1.5.  comedi_driver">comedi_driver</a> *driver;
  void          *private;
  kdev_t        minor;
  char          *board_name;
  const void    *board_ptr;
  int           attached;
  int           rt;
  spinlock_t    spinlock;
  int           in_request_module;

  int               n_subdevices;
  <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *subdevices;
  int              options[COMEDI_NDEVCONFOPTS];

  /* dumb */
  int iobase;
  int irq;

  <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *read_subdev;
  wait_queue_head_t read_wait;

  <a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *write_subdev;
  wait_queue_head_t write_wait;

  struct fasync_struct *async_queue;

  void (*open)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev);
  void (*close)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev);
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comediasync"></a>6.2.1.4. 
<span class="type">comedi_async</span>
</h5></div></div></div><p>
The following data structure contains all relevant information:
addresses and sizes of buffers, pointers to the actual data, and the
information needed for
<a class="link" href="drivercallbacks.html" title="6.4.  Callbacks, events and interrupts">event handling</a>:
</p><pre class="programlisting">
struct comedi_async_struct{
  void		*prealloc_buf;		/* pre-allocated buffer */
  unsigned int	prealloc_bufsz;		/* buffer size, in bytes */
  unsigned long	*buf_page_list;		/* physical address of each page */
  unsigned int	max_bufsize;		/* maximum buffer size, bytes */
  unsigned int	mmap_count;	/* current number of mmaps of prealloc_buf */

  volatile unsigned int buf_write_count;	/* byte count for writer (write completed) */
  volatile unsigned int buf_write_alloc_count;	/* byte count for writer (allocated for writing) */
  volatile unsigned int buf_read_count;	/* byte count for reader (read completed)*/

  unsigned int buf_write_ptr;	/* buffer marker for writer */
  unsigned int buf_read_ptr;	/* buffer marker for reader */

  unsigned int cur_chan;		/* useless channel marker for interrupt */
  /* number of bytes that have been received for current scan */
  unsigned int scan_progress;
  /* keeps track of where we are in chanlist as for munging */
  unsigned int munge_chan;

  unsigned int	events;		/* events that have occurred */

  <a class="link" href="datatypesstructures.html#ref-type-comedi-cmd" title="5.3.7.  comedi_cmd">comedi_cmd</a> cmd;

  // callback stuff
  unsigned int cb_mask;
  int (*cb_func)(unsigned int flags,void *);
  void *cb_arg;

  int (*inttrig)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *s,unsigned int x);
};
</pre><p>
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a name="comedidriver"></a>6.2.1.5. 
<span class="type">comedi_driver</span>
</h5></div></div></div><p>
</p><pre class="programlisting">
struct comedi_driver_struct{
	struct comedi_driver_struct *next;

	char *driver_name;
	struct module *module;
	int (*attach)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *,comedi_devconfig *);
	int (*detach)(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *);

	/* number of elements in board_name and board_id arrays */
	unsigned int num_names;
	void *board_name;
	/* offset in bytes from one board name pointer to the next */
	int offset;
};
</pre><p>
</p></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="driversupportfunctions"></a>6.2.2. 
Generic driver support functions
</h4></div></div></div><p>
The directory
<code class="filename">comedi</code> contains a large set of
support functions. Some of the most important ones are given below.
</p><p>
From <code class="filename">comedi/comedi_fops.c</code>, functions to handle the
hardware events (which also runs the registered callback function), to
get data in and out of the software data buffer, and to parse the
incoming functional requests:
</p><pre class="programlisting">
  void comedi_event(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev,<a class="link" href="comedikernelgeneric.html#comedisubdevice" title="6.2.1.2.  comedi_subdevice">comedi_subdevice</a> *s,unsigned int mask);

  int comedi_buf_put(<a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4.  comedi_async">comedi_async</a> *async, <a class="link" href="datatypesstructures.html#ref-type-sampl-t" title="5.3.3.  sampl_t">sampl_t</a> x);
  int comedi_buf_get(<a class="link" href="comedikernelgeneric.html#comediasync" title="6.2.1.4.  comedi_async">comedi_async</a> *async, <a class="link" href="datatypesstructures.html#ref-type-sampl-t" title="5.3.3.  sampl_t">sampl_t</a> *x);

  static int parse_insn(<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev,<a class="link" href="datatypesstructures.html#ref-type-comedi-insn" title="5.3.8.  comedi_insn">comedi_insn</a> *insn,<a class="link" href="datatypesstructures.html#ref-type-lsampl-t" title="5.3.4.  lsampl_t">lsampl_t</a> *data,void *file);
</pre><p>
The file <code class="filename">comedi/kcomedilib/kcomedilib_main.c</code> provides
functions to register a callback, to poll an ongoing data acquisition,
and to print an error message:
</p><pre class="programlisting">
  int comedi_register_callback(<a class="link" href="datatypesstructures.html#ref-type-comedi-t" title="5.3.2.  comedi_t">comedi_t</a> *d,unsigned int subdevice, unsigned int mask,int (*cb)(unsigned int,void *),void *arg);

  int comedi_poll(<a class="link" href="datatypesstructures.html#ref-type-comedi-t" title="5.3.2.  comedi_t">comedi_t</a> *d, unsigned int subdevice);

  void comedi_perror(const char *message);
</pre><p>
The file <code class="filename">comedi/rt.c</code> provides interrupt handling
for real-time tasks (one interrupt per <span class="emphasis"><em>device</em></span>!):
</p><pre class="programlisting">
  int comedi_request_irq(unsigned irq,void (*handler)(int, void *,struct pt_regs *), unsigned long flags,const char *device,<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev_id);
  void comedi_free_irq(unsigned int irq,<a class="link" href="comedikernelgeneric.html#comedidevice" title="6.2.1.3.  comedi_device">comedi_device</a> *dev_id)
</pre><p>
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="driverwriting.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="driverwriting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="boardspecific.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. 
Writing a <acronym class="acronym">Comedi</acronym> driver
 </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 6.3. 
Board-specific functionality
</td></tr></table></div></body></html>