linux/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
<<
>>
Prefs
   1/*
   2    kcomedilib/kcomedilib.c
   3    a comedlib interface for kernel modules
   4
   5    COMEDI - Linux Control and Measurement Device Interface
   6    Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
   7
   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.
  12
  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.
  17
  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.
  21
  22*/
  23
  24#define __NO_VERSION__
  25#include <linux/module.h>
  26
  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>
  33#include <linux/mm.h>
  34#include <linux/io.h>
  35
  36#include "../comedi.h"
  37#include "../comedilib.h"
  38#include "../comedidev.h"
  39
  40MODULE_AUTHOR("David Schleef <ds@schleef.org>");
  41MODULE_DESCRIPTION("Comedi kernel library");
  42MODULE_LICENSE("GPL");
  43
  44struct comedi_device *comedi_open(const char *filename)
  45{
  46        struct comedi_device_file_info *dev_file_info;
  47        struct comedi_device *dev;
  48        unsigned int minor;
  49
  50        if (strncmp(filename, "/dev/comedi", 11) != 0)
  51                return NULL;
  52
  53        minor = simple_strtoul(filename + 11, NULL, 0);
  54
  55        if (minor >= COMEDI_NUM_BOARD_MINORS)
  56                return NULL;
  57
  58        dev_file_info = comedi_get_device_file_info(minor);
  59        if (dev_file_info == NULL)
  60                return NULL;
  61        dev = dev_file_info->device;
  62
  63        if (dev == NULL || !dev->attached)
  64                return NULL;
  65
  66        if (!try_module_get(dev->driver->module))
  67                return NULL;
  68
  69        return dev;
  70}
  71EXPORT_SYMBOL(comedi_open);
  72
  73int comedi_close(struct comedi_device *d)
  74{
  75        struct comedi_device *dev = (struct comedi_device *)d;
  76
  77        module_put(dev->driver->module);
  78
  79        return 0;
  80}
  81EXPORT_SYMBOL(comedi_close);
  82
  83static int comedi_do_insn(struct comedi_device *dev, struct comedi_insn *insn)
  84{
  85        struct comedi_subdevice *s;
  86        int ret = 0;
  87
  88        /* a subdevice instruction */
  89        if (insn->subdev >= dev->n_subdevices) {
  90                ret = -EINVAL;
  91                goto error;
  92        }
  93        s = dev->subdevices + insn->subdev;
  94
  95        if (s->type == COMEDI_SUBD_UNUSED) {
  96                printk(KERN_ERR "%d not useable subdevice\n", insn->subdev);
  97                ret = -EIO;
  98                goto error;
  99        }
 100
 101        /* XXX check lock */
 102
 103        ret = comedi_check_chanlist(s, 1, &insn->chanspec);
 104        if (ret < 0) {
 105                printk(KERN_ERR "bad chanspec\n");
 106                ret = -EINVAL;
 107                goto error;
 108        }
 109
 110        if (s->busy) {
 111                ret = -EBUSY;
 112                goto error;
 113        }
 114        s->busy = dev;
 115
 116        switch (insn->insn) {
 117        case INSN_BITS:
 118                ret = s->insn_bits(dev, s, insn, insn->data);
 119                break;
 120        case INSN_CONFIG:
 121                /* XXX should check instruction length */
 122                ret = s->insn_config(dev, s, insn, insn->data);
 123                break;
 124        default:
 125                ret = -EINVAL;
 126                break;
 127        }
 128
 129        s->busy = NULL;
 130error:
 131
 132        return ret;
 133}
 134
 135int comedi_dio_config(struct comedi_device *dev, unsigned int subdev,
 136                      unsigned int chan, unsigned int io)
 137{
 138        struct comedi_insn insn;
 139
 140        memset(&insn, 0, sizeof(insn));
 141        insn.insn = INSN_CONFIG;
 142        insn.n = 1;
 143        insn.data = &io;
 144        insn.subdev = subdev;
 145        insn.chanspec = CR_PACK(chan, 0, 0);
 146
 147        return comedi_do_insn(dev, &insn);
 148}
 149EXPORT_SYMBOL(comedi_dio_config);
 150
 151int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev,
 152                        unsigned int mask, unsigned int *bits)
 153{
 154        struct comedi_insn insn;
 155        unsigned int data[2];
 156        int ret;
 157
 158        memset(&insn, 0, sizeof(insn));
 159        insn.insn = INSN_BITS;
 160        insn.n = 2;
 161        insn.data = data;
 162        insn.subdev = subdev;
 163
 164        data[0] = mask;
 165        data[1] = *bits;
 166
 167        ret = comedi_do_insn(dev, &insn);
 168
 169        *bits = data[1];
 170
 171        return ret;
 172}
 173EXPORT_SYMBOL(comedi_dio_bitfield);
 174
 175int comedi_find_subdevice_by_type(struct comedi_device *dev, int type,
 176                                  unsigned int subd)
 177{
 178        if (subd > dev->n_subdevices)
 179                return -ENODEV;
 180
 181        for (; subd < dev->n_subdevices; subd++) {
 182                if (dev->subdevices[subd].type == type)
 183                        return subd;
 184        }
 185        return -1;
 186}
 187EXPORT_SYMBOL(comedi_find_subdevice_by_type);
 188
 189int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice)
 190{
 191        struct comedi_subdevice *s = dev->subdevices + subdevice;
 192
 193        return s->n_chan;
 194}
 195EXPORT_SYMBOL(comedi_get_n_channels);
 196
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.