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