]>
git.ipfire.org Git - people/arne_f/kernel.git/blob - drivers/staging/comedi/kcomedilib/kcomedilib_main.c
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>
36 #include "../comedi.h"
37 #include "../comedilib.h"
38 #include "../comedidev.h"
40 MODULE_AUTHOR("David Schleef <ds@schleef.org>");
41 MODULE_DESCRIPTION("Comedi kernel library");
42 MODULE_LICENSE("GPL");
44 void *comedi_open(const char *filename
)
46 struct comedi_device_file_info
*dev_file_info
;
47 struct comedi_device
*dev
;
50 if (strncmp(filename
, "/dev/comedi", 11) != 0)
53 minor
= simple_strtoul(filename
+ 11, NULL
, 0);
55 if (minor
>= COMEDI_NUM_BOARD_MINORS
)
58 dev_file_info
= comedi_get_device_file_info(minor
);
59 if (dev_file_info
== NULL
)
61 dev
= dev_file_info
->device
;
63 if (dev
== NULL
|| !dev
->attached
)
66 if (!try_module_get(dev
->driver
->module
))
72 void *comedi_open_old(unsigned int minor
)
74 struct comedi_device_file_info
*dev_file_info
;
75 struct comedi_device
*dev
;
77 if (minor
>= COMEDI_NUM_MINORS
)
80 dev_file_info
= comedi_get_device_file_info(minor
);
81 if (dev_file_info
== NULL
)
83 dev
= dev_file_info
->device
;
85 if (dev
== NULL
|| !dev
->attached
)
91 int comedi_close(void *d
)
93 struct comedi_device
*dev
= (struct comedi_device
*)d
;
95 module_put(dev
->driver
->module
);
100 int comedi_loglevel(int newlevel
)
105 void comedi_perror(const char *message
)
107 printk("%s: unknown error\n", message
);
110 char *comedi_strerror(int err
)
112 return "unknown error";
115 int comedi_fileno(void *d
)
117 struct comedi_device
*dev
= (struct comedi_device
*)d
;
119 /* return something random */
123 int comedi_command(void *d
, struct comedi_cmd
*cmd
)
125 struct comedi_device
*dev
= (struct comedi_device
*)d
;
126 struct comedi_subdevice
*s
;
127 struct comedi_async
*async
;
130 if (cmd
->subdev
>= dev
->n_subdevices
)
133 s
= dev
->subdevices
+ cmd
->subdev
;
134 if (s
->type
== COMEDI_SUBD_UNUSED
)
145 if (async
->cb_mask
& COMEDI_CB_EOS
)
146 cmd
->flags
|= TRIG_WAKE_EOS
;
150 runflags
= SRF_RUNNING
;
152 comedi_set_subdevice_runflags(s
, ~0, runflags
);
154 comedi_reset_async_buf(async
);
156 return s
->do_cmd(dev
, s
);
159 int comedi_command_test(void *d
, struct comedi_cmd
*cmd
)
161 struct comedi_device
*dev
= (struct comedi_device
*)d
;
162 struct comedi_subdevice
*s
;
164 if (cmd
->subdev
>= dev
->n_subdevices
)
167 s
= dev
->subdevices
+ cmd
->subdev
;
168 if (s
->type
== COMEDI_SUBD_UNUSED
)
171 if (s
->async
== NULL
)
174 return s
->do_cmdtest(dev
, s
, cmd
);
179 * perform an instruction
181 int comedi_do_insn(void *d
, struct comedi_insn
*insn
)
183 struct comedi_device
*dev
= (struct comedi_device
*)d
;
184 struct comedi_subdevice
*s
;
187 if (insn
->insn
& INSN_MASK_SPECIAL
) {
188 switch (insn
->insn
) {
193 do_gettimeofday(&tv
);
194 insn
->data
[0] = tv
.tv_sec
;
195 insn
->data
[1] = tv
.tv_usec
;
201 /* XXX isn't the value supposed to be nanosecs? */
202 if (insn
->n
!= 1 || insn
->data
[0] >= 100) {
206 udelay(insn
->data
[0]);
214 if (insn
->subdev
>= dev
->n_subdevices
) {
215 printk("%d not usable subdevice\n",
220 s
= dev
->subdevices
+ insn
->subdev
;
222 printk("no async\n");
226 if (!s
->async
->inttrig
) {
227 printk("no inttrig\n");
231 ret
= s
->async
->inttrig(dev
, s
, insn
->data
[0]);
239 /* a subdevice instruction */
240 if (insn
->subdev
>= dev
->n_subdevices
) {
244 s
= dev
->subdevices
+ insn
->subdev
;
246 if (s
->type
== COMEDI_SUBD_UNUSED
) {
247 printk("%d not useable subdevice\n", insn
->subdev
);
254 ret
= check_chanlist(s
, 1, &insn
->chanspec
);
256 printk("bad chanspec\n");
267 switch (insn
->insn
) {
269 ret
= s
->insn_read(dev
, s
, insn
, insn
->data
);
272 ret
= s
->insn_write(dev
, s
, insn
, insn
->data
);
275 ret
= s
->insn_bits(dev
, s
, insn
, insn
->data
);
278 /* XXX should check instruction length */
279 ret
= s
->insn_config(dev
, s
, insn
, insn
->data
);
291 /* XXX do we want this? -- abbotti #if'ed it out for now. */
292 if (ret
!= insn
->n
) {
293 printk("BUG: result of insn != insn.n\n");
317 - ioctl/rt lock (this type)
318 - lock while subdevice busy
319 - lock while subdevice being programmed
322 int comedi_lock(void *d
, unsigned int subdevice
)
324 struct comedi_device
*dev
= (struct comedi_device
*)d
;
325 struct comedi_subdevice
*s
;
329 if (subdevice
>= dev
->n_subdevices
)
332 s
= dev
->subdevices
+ subdevice
;
334 spin_lock_irqsave(&s
->spin_lock
, flags
);
346 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
365 int comedi_unlock(void *d
, unsigned int subdevice
)
367 struct comedi_device
*dev
= (struct comedi_device
*)d
;
368 struct comedi_subdevice
*s
;
370 struct comedi_async
*async
;
373 if (subdevice
>= dev
->n_subdevices
)
376 s
= dev
->subdevices
+ subdevice
;
380 spin_lock_irqsave(&s
->spin_lock
, flags
);
384 } else if (s
->lock
&& s
->lock
!= (void *)d
) {
391 async
->cb_func
= NULL
;
392 async
->cb_arg
= NULL
;
398 spin_unlock_irqrestore(&s
->spin_lock
, flags
);
405 cancel acquisition ioctl
417 int comedi_cancel(void *d
, unsigned int subdevice
)
419 struct comedi_device
*dev
= (struct comedi_device
*)d
;
420 struct comedi_subdevice
*s
;
423 if (subdevice
>= dev
->n_subdevices
)
426 s
= dev
->subdevices
+ subdevice
;
428 if (s
->lock
&& s
->lock
!= d
)
439 if (!s
->cancel
|| !s
->async
)
442 ret
= s
->cancel(dev
, s
);
447 comedi_set_subdevice_runflags(s
, SRF_RUNNING
| SRF_RT
, 0);
448 s
->async
->inttrig
= NULL
;
455 registration of callback functions
457 int comedi_register_callback(void *d
, unsigned int subdevice
,
458 unsigned int mask
, int (*cb
) (unsigned int,
461 struct comedi_device
*dev
= (struct comedi_device
*)d
;
462 struct comedi_subdevice
*s
;
463 struct comedi_async
*async
;
465 if (subdevice
>= dev
->n_subdevices
)
468 s
= dev
->subdevices
+ subdevice
;
471 if (s
->type
== COMEDI_SUBD_UNUSED
|| !async
)
474 /* are we locked? (ioctl lock) */
475 if (s
->lock
&& s
->lock
!= d
)
484 async
->cb_func
= NULL
;
485 async
->cb_arg
= NULL
;
487 async
->cb_mask
= mask
;
495 int comedi_poll(void *d
, unsigned int subdevice
)
497 struct comedi_device
*dev
= (struct comedi_device
*)d
;
498 struct comedi_subdevice
*s
= dev
->subdevices
;
499 struct comedi_async
*async
;
501 if (subdevice
>= dev
->n_subdevices
)
504 s
= dev
->subdevices
+ subdevice
;
507 if (s
->type
== COMEDI_SUBD_UNUSED
|| !async
)
510 /* are we locked? (ioctl lock) */
511 if (s
->lock
&& s
->lock
!= d
)
514 /* are we running? XXX wrong? */
518 return s
->poll(dev
, s
);
521 /* WARNING: not portable */
522 int comedi_map(void *d
, unsigned int subdevice
, void *ptr
)
524 struct comedi_device
*dev
= (struct comedi_device
*)d
;
525 struct comedi_subdevice
*s
;
527 if (subdevice
>= dev
->n_subdevices
)
530 s
= dev
->subdevices
+ subdevice
;
536 *((void **)ptr
) = s
->async
->prealloc_buf
;
538 /* XXX no reference counting */
543 /* WARNING: not portable */
544 int comedi_unmap(void *d
, unsigned int subdevice
)
546 struct comedi_device
*dev
= (struct comedi_device
*)d
;
547 struct comedi_subdevice
*s
;
549 if (subdevice
>= dev
->n_subdevices
)
552 s
= dev
->subdevices
+ subdevice
;
557 /* XXX no reference counting */