kcomedilib_main.c revision 3781bc5425f985c2ceffa3b2111e1d0eeb38cc24
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 44void *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 (void *)dev; 70} 71EXPORT_SYMBOL(comedi_open); 72 73int comedi_close(void *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("%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("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(void *dev, unsigned int subdev, unsigned int chan, 136 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(void *dev, unsigned int subdev, unsigned int mask, 152 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(void *d, int type, unsigned int subd) 176{ 177 struct comedi_device *dev = (struct comedi_device *)d; 178 179 if (subd > dev->n_subdevices) 180 return -ENODEV; 181 182 for (; subd < dev->n_subdevices; subd++) { 183 if (dev->subdevices[subd].type == type) 184 return subd; 185 } 186 return -1; 187} 188EXPORT_SYMBOL(comedi_find_subdevice_by_type); 189 190int comedi_get_n_channels(void *d, unsigned int subdevice) 191{ 192 struct comedi_device *dev = (struct comedi_device *)d; 193 struct comedi_subdevice *s = dev->subdevices + subdevice; 194 195 return s->n_chan; 196} 197EXPORT_SYMBOL(comedi_get_n_channels); 198