2 kcomedilib/kcomedilib.c
3 a comedlib interface for kernel modules
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define __NO_VERSION__
25 #include <linux/module.h>
27 #include <linux/errno.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/fcntl.h>
31 #include <linux/delay.h>
32 #include <linux/ioport.h>
34 #include <linux/slab.h>
37 #include "../comedi.h"
38 #include "../comedilib.h"
39 #include "../comedidev.h"
41 MODULE_AUTHOR("David Schleef <ds@schleef.org>");
42 MODULE_DESCRIPTION("Comedi kernel library");
43 MODULE_LICENSE("GPL");
45 void *comedi_open(const char *filename
)
47 struct comedi_device_file_info
*dev_file_info
;
48 struct comedi_device
*dev
;
51 if (strncmp(filename
, "/dev/comedi", 11) != 0)
54 minor
= simple_strtoul(filename
+ 11, NULL
, 0);
56 if (minor
>= COMEDI_NUM_BOARD_MINORS
)
59 dev_file_info
= comedi_get_device_file_info(minor
);
60 if (dev_file_info
== NULL
)
62 dev
= dev_file_info
->device
;
64 if (dev
== NULL
|| !dev
->attached
)
67 if (!try_module_get(dev
->driver
->module
))
73 void *comedi_open_old(unsigned int minor
)
75 struct comedi_device_file_info
*dev_file_info
;
76 struct comedi_device
*dev
;
78 if (minor
>= COMEDI_NUM_MINORS
)
81 dev_file_info
= comedi_get_device_file_info(minor
);
82 if (dev_file_info
== NULL
)
84 dev
= dev_file_info
->device
;
86 if (dev
== NULL
|| !dev
->attached
)
92 int comedi_close(void *d
)
94 struct comedi_device
*dev
= (struct comedi_device
*) d
;
96 module_put(dev
->driver
->module
);
101 int comedi_loglevel(int newlevel
)
106 void comedi_perror(const char *message
)
108 printk("%s: unknown error\n", message
);
111 char *comedi_strerror(int err
)
113 return "unknown error";
116 int comedi_fileno(void *d
)
118 struct comedi_device
*dev
= (struct comedi_device
*) d
;
120 /* return something random */
124 int comedi_command(void *d
, struct comedi_cmd
*cmd
)
126 struct comedi_device
*dev
= (struct comedi_device
*) d
;
127 struct comedi_subdevice
*s
;
128 struct comedi_async
*async
;
131 if (cmd
->subdev
>= dev
->n_subdevices
)
134 s
= dev
->subdevices
+ cmd
->subdev
;
135 if (s
->type
== COMEDI_SUBD_UNUSED
)
146 if (async
->cb_mask
& COMEDI_CB_EOS
)
147 cmd
->flags
|= TRIG_WAKE_EOS
;
151 runflags
= SRF_RUNNING
;
153 #ifdef CONFIG_COMEDI_RT
154 if (comedi_switch_to_rt(dev
) == 0)
157 comedi_set_subdevice_runflags(s
, ~0, runflags
);
159 comedi_reset_async_buf(async
);
161 return s
->do_cmd(dev
, s
);
164 int comedi_command_test(void *d
, struct comedi_cmd
*cmd
)
166 struct comedi_device
*dev
= (struct comedi_device
*) d
;
167 struct comedi_subdevice
*s
;
169 if (cmd
->subdev
>= dev
->n_subdevices
)
172 s
= dev
->subdevices
+ cmd
->subdev
;
173 if (s
->type
== COMEDI_SUBD_UNUSED
)
176 if (s
->async
== NULL
)
179 return s
->do_cmdtest(dev
, s
, cmd
);
184 * perform an instruction
186 int comedi_do_insn(void *d
, struct comedi_insn
*insn
)
188 struct comedi_device
*dev
= (struct comedi_device
*) d
;
189 struct comedi_subdevice
*s
;
192 if (insn
->insn
& INSN_MASK_SPECIAL
) {
193 switch (insn
->insn
) {
198 do_gettimeofday(&tv
);
199 insn
->data
[0] = tv
.tv_sec
;
200 insn
->data
[1] = tv
.tv_usec
;
206 /* XXX isn't the value supposed to be nanosecs? */
207 if (insn
->n
!= 1 || insn
->data
[0] >= 100) {
211 udelay(insn
->data
[0]);
219 if (insn
->subdev
>= dev
->n_subdevices
) {
220 printk("%d not usable subdevice\n",
225 s
= dev
->subdevices
+ insn
->subdev
;
227 printk("no async\n");
231 if (!s
->async
->inttrig
) {
232 printk("no inttrig\n");
236 ret
= s
->async
->inttrig(dev
, s
, insn
->data
[0]);
244 /* a subdevice instruction */
245 if (insn
->subdev
>= dev
->n_subdevices
) {
249 s
= dev
->subdevices
+ insn
->subdev
;
251 if (s
->type
== COMEDI_SUBD_UNUSED
) {
252 printk("%d not useable subdevice\n", insn
->subdev
);
259 ret
= check_chanlist(s
, 1, &insn
->chanspec
);
261 printk("bad chanspec\n");
272 switch (insn
->insn
) {
274 ret
= s
->insn_read(dev
, s
, insn
, insn
->data
);
277 ret
= s
->insn_write(dev
, s
, insn
, insn
->data
);
280 ret
= s
->insn_bits(dev
, s
, insn
, insn
->data
);
283 /* XXX should check instruction length */
284 ret
= s
->insn_config(dev
, s
, insn
, insn
->data
);
296 /* XXX do we want this? -- abbotti #if'ed it out for now. */
297 if (ret
!= insn
->n
) {
298 printk("BUG: result of insn != insn.n\n");
322 - ioctl/rt lock (this type)
323 - lock while subdevice busy
324 - lock while subdevice being programmed
327 int comedi_lock(void *d
, unsigned int subdevice
)
329 struct comedi_device
*dev
= (struct comedi_device
*) d
;
330 struct comedi_subdevice
*s
;
334 if (subdevice
>= dev
->n_subdevices
)
337 s
= dev
->subdevices
+ subdevice
;
339 spin_lock_irqsave(&s
->spin_lock
, flags
);
351 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
370 int comedi_unlock(void *d
, unsigned int subdevice
)
372 struct comedi_device
*dev
= (struct comedi_device
*) d
;
373 struct comedi_subdevice
*s
;
375 struct comedi_async
*async
;
378 if (subdevice
>= dev
->n_subdevices
)
381 s
= dev
->subdevices
+ subdevice
;
385 spin_lock_irqsave(&s
->spin_lock
, flags
);
389 } else if (s
->lock
&& s
->lock
!= (void *)d
) {
396 async
->cb_func
= NULL
;
397 async
->cb_arg
= NULL
;
403 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
410 cancel acquisition ioctl
422 int comedi_cancel(void *d
, unsigned int subdevice
)
424 struct comedi_device
*dev
= (struct comedi_device
*) d
;
425 struct comedi_subdevice
*s
;
428 if (subdevice
>= dev
->n_subdevices
)
431 s
= dev
->subdevices
+ subdevice
;
433 if (s
->lock
&& s
->lock
!= d
)
444 if (!s
->cancel
|| !s
->async
)
447 ret
= s
->cancel(dev
, s
);
452 #ifdef CONFIG_COMEDI_RT
453 if (comedi_get_subdevice_runflags(s
) & SRF_RT
)
454 comedi_switch_to_non_rt(dev
);
457 comedi_set_subdevice_runflags(s
, SRF_RUNNING
| SRF_RT
, 0);
458 s
->async
->inttrig
= NULL
;
465 registration of callback functions
467 int comedi_register_callback(void *d
, unsigned int subdevice
,
468 unsigned int mask
, int (*cb
) (unsigned int, void *), void *arg
)
470 struct comedi_device
*dev
= (struct comedi_device
*) d
;
471 struct comedi_subdevice
*s
;
472 struct comedi_async
*async
;
474 if (subdevice
>= dev
->n_subdevices
)
477 s
= dev
->subdevices
+ subdevice
;
480 if (s
->type
== COMEDI_SUBD_UNUSED
|| !async
)
483 /* are we locked? (ioctl lock) */
484 if (s
->lock
&& s
->lock
!= d
)
493 async
->cb_func
= NULL
;
494 async
->cb_arg
= NULL
;
496 async
->cb_mask
= mask
;
504 int comedi_poll(void *d
, unsigned int subdevice
)
506 struct comedi_device
*dev
= (struct comedi_device
*) d
;
507 struct comedi_subdevice
*s
= dev
->subdevices
;
508 struct comedi_async
*async
;
510 if (subdevice
>= dev
->n_subdevices
)
513 s
= dev
->subdevices
+ subdevice
;
516 if (s
->type
== COMEDI_SUBD_UNUSED
|| !async
)
519 /* are we locked? (ioctl lock) */
520 if (s
->lock
&& s
->lock
!= d
)
523 /* are we running? XXX wrong? */
527 return s
->poll(dev
, s
);
530 /* WARNING: not portable */
531 int comedi_map(void *d
, unsigned int subdevice
, void *ptr
)
533 struct comedi_device
*dev
= (struct comedi_device
*) d
;
534 struct comedi_subdevice
*s
;
536 if (subdevice
>= dev
->n_subdevices
)
539 s
= dev
->subdevices
+ subdevice
;
545 *((void **)ptr
) = s
->async
->prealloc_buf
;
547 /* XXX no reference counting */
552 /* WARNING: not portable */
553 int comedi_unmap(void *d
, unsigned int subdevice
)
555 struct comedi_device
*dev
= (struct comedi_device
*) d
;
556 struct comedi_subdevice
*s
;
558 if (subdevice
>= dev
->n_subdevices
)
561 s
= dev
->subdevices
+ subdevice
;
566 /* XXX no reference counting */