drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / kcomedilib / kcomedilib_main.c
CommitLineData
b79a7a20
DS
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
b79a7a20
DS
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>
7382e571 33#include <linux/io.h>
b79a7a20
DS
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
472dfe77 43struct comedi_device *comedi_open(const char *filename)
b79a7a20 44{
71b5f4f1 45 struct comedi_device *dev;
b79a7a20
DS
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
4da5fa9a 56 dev = comedi_dev_from_minor(minor);
b79a7a20 57
4da5fa9a 58 if (!dev || !dev->attached)
b79a7a20
DS
59 return NULL;
60
61 if (!try_module_get(dev->driver->module))
62 return NULL;
63
472dfe77 64 return dev;
b79a7a20 65}
5660e742 66EXPORT_SYMBOL_GPL(comedi_open);
b79a7a20 67
472dfe77 68int comedi_close(struct comedi_device *d)
b79a7a20 69{
0a85b6f0 70 struct comedi_device *dev = (struct comedi_device *)d;
b79a7a20
DS
71
72 module_put(dev->driver->module);
73
74 return 0;
75}
5660e742 76EXPORT_SYMBOL_GPL(comedi_close);
b79a7a20 77
1f5cc359
HS
78static int comedi_do_insn(struct comedi_device *dev,
79 struct comedi_insn *insn,
80 unsigned int *data)
b79a7a20 81{
34c43922 82 struct comedi_subdevice *s;
b79a7a20
DS
83 int ret = 0;
84
3781bc54
GKH
85 /* a subdevice instruction */
86 if (insn->subdev >= dev->n_subdevices) {
87 ret = -EINVAL;
88 goto error;
b79a7a20 89 }
5818e709 90 s = &dev->subdevices[insn->subdev];
3781bc54
GKH
91
92 if (s->type == COMEDI_SUBD_UNUSED) {
49e8e44b
YT
93 dev_err(dev->class_dev,
94 "%d not useable subdevice\n", insn->subdev);
3781bc54 95 ret = -EIO;
b79a7a20 96 goto error;
3781bc54
GKH
97 }
98
99 /* XXX check lock */
100
101 ret = comedi_check_chanlist(s, 1, &insn->chanspec);
102 if (ret < 0) {
49e8e44b 103 dev_err(dev->class_dev, "bad chanspec\n");
b79a7a20
DS
104 ret = -EINVAL;
105 goto error;
106 }
3781bc54
GKH
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:
1f5cc359 116 ret = s->insn_bits(dev, s, insn, data);
3781bc54
GKH
117 break;
118 case INSN_CONFIG:
119 /* XXX should check instruction length */
1f5cc359 120 ret = s->insn_config(dev, s, insn, data);
3781bc54
GKH
121 break;
122 default:
123 ret = -EINVAL;
124 break;
125 }
126
127 s->busy = NULL;
0a85b6f0 128error:
b79a7a20
DS
129
130 return ret;
131}
132
472dfe77
GKH
133int comedi_dio_config(struct comedi_device *dev, unsigned int subdev,
134 unsigned int chan, unsigned int io)
a1525758
GKH
135{
136 struct comedi_insn insn;
137
138 memset(&insn, 0, sizeof(insn));
139 insn.insn = INSN_CONFIG;
140 insn.n = 1;
a1525758
GKH
141 insn.subdev = subdev;
142 insn.chanspec = CR_PACK(chan, 0, 0);
143
1f5cc359 144 return comedi_do_insn(dev, &insn, &io);
a1525758 145}
5660e742 146EXPORT_SYMBOL_GPL(comedi_dio_config);
a1525758 147
472dfe77
GKH
148int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev,
149 unsigned int mask, unsigned int *bits)
a1525758
GKH
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;
a1525758
GKH
158 insn.subdev = subdev;
159
160 data[0] = mask;
161 data[1] = *bits;
162
1f5cc359 163 ret = comedi_do_insn(dev, &insn, data);
a1525758
GKH
164
165 *bits = data[1];
166
167 return ret;
168}
5660e742 169EXPORT_SYMBOL_GPL(comedi_dio_bitfield);
a1525758 170
472dfe77
GKH
171int comedi_find_subdevice_by_type(struct comedi_device *dev, int type,
172 unsigned int subd)
a1525758 173{
5818e709
HS
174 struct comedi_subdevice *s;
175
a1525758
GKH
176 if (subd > dev->n_subdevices)
177 return -ENODEV;
178
179 for (; subd < dev->n_subdevices; subd++) {
5818e709
HS
180 s = &dev->subdevices[subd];
181 if (s->type == type)
a1525758
GKH
182 return subd;
183 }
184 return -1;
185}
5660e742 186EXPORT_SYMBOL_GPL(comedi_find_subdevice_by_type);
a1525758 187
472dfe77 188int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice)
a1525758 189{
5818e709 190 struct comedi_subdevice *s = &dev->subdevices[subdevice];
a1525758
GKH
191
192 return s->n_chan;
193}
5660e742 194EXPORT_SYMBOL_GPL(comedi_get_n_channels);