Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
staging
comedi
range.c
Go to the documentation of this file.
1
/*
2
module/range.c
3
comedi routines for voltage ranges
4
5
COMEDI - Linux Control and Measurement Device Interface
6
Copyright (C) 1997-8 David A. Schleef <
[email protected]
>
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/uaccess.h
>
25
#include "
comedidev.h
"
26
#include "
comedi_internal.h
"
27
28
const
struct
comedi_lrange
range_bipolar10
= { 1, {
BIP_RANGE
(10)} };
29
EXPORT_SYMBOL
(range_bipolar10);
30
const
struct
comedi_lrange
range_bipolar5
= { 1, {
BIP_RANGE
(5)} };
31
EXPORT_SYMBOL
(range_bipolar5);
32
const
struct
comedi_lrange
range_bipolar2_5
= { 1, {
BIP_RANGE
(2.5)} };
33
EXPORT_SYMBOL
(range_bipolar2_5);
34
const
struct
comedi_lrange
range_unipolar10
= { 1, {
UNI_RANGE
(10)} };
35
EXPORT_SYMBOL
(range_unipolar10);
36
const
struct
comedi_lrange
range_unipolar5
= { 1, {
UNI_RANGE
(5)} };
37
EXPORT_SYMBOL
(range_unipolar5);
38
const
struct
comedi_lrange
range_unknown
= { 1, {{0, 1000000,
UNIT_none
} } };
39
EXPORT_SYMBOL
(range_unknown);
40
41
/*
42
COMEDI_RANGEINFO
43
range information ioctl
44
45
arg:
46
pointer to rangeinfo structure
47
48
reads:
49
range info structure
50
51
writes:
52
n struct comedi_krange structures to rangeinfo->range_ptr
53
*/
54
int
do_rangeinfo_ioctl
(
struct
comedi_device
*
dev
,
55
struct
comedi_rangeinfo
__user *
arg
)
56
{
57
struct
comedi_rangeinfo
it;
58
int
subd,
chan
;
59
const
struct
comedi_lrange
*
lr
;
60
struct
comedi_subdevice
*
s
;
61
62
if
(
copy_from_user
(&it, arg,
sizeof
(
struct
comedi_rangeinfo
)))
63
return
-
EFAULT
;
64
subd = (it.
range_type
>> 24) & 0xf;
65
chan = (it.
range_type
>> 16) & 0xff;
66
67
if
(!dev->
attached
)
68
return
-
EINVAL
;
69
if
(subd >= dev->
n_subdevices
)
70
return
-
EINVAL
;
71
s = &dev->
subdevices
[subd];
72
if
(s->
range_table
) {
73
lr = s->
range_table
;
74
}
else
if
(s->
range_table_list
) {
75
if
(chan >= s->
n_chan
)
76
return
-
EINVAL
;
77
lr = s->
range_table_list
[chan];
78
}
else
{
79
return
-
EINVAL
;
80
}
81
82
if
(
RANGE_LENGTH
(it.
range_type
) != lr->
length
) {
83
DPRINTK
(
"wrong length %d should be %d (0x%08x)\n"
,
84
RANGE_LENGTH
(it.
range_type
), lr->
length
, it.
range_type
);
85
return
-
EINVAL
;
86
}
87
88
if
(
copy_to_user
(it.
range_ptr
, lr->
range
,
89
sizeof
(
struct
comedi_krange
) * lr->
length
))
90
return
-
EFAULT
;
91
92
return
0;
93
}
94
95
static
int
aref_invalid(
struct
comedi_subdevice
*
s
,
unsigned
int
chanspec)
96
{
97
unsigned
int
aref;
98
99
/* disable reporting invalid arefs... maybe someday */
100
return
0;
101
102
aref =
CR_AREF
(chanspec);
103
switch
(aref) {
104
case
AREF_DIFF
:
105
if
(s->
subdev_flags
&
SDF_DIFF
)
106
return
0;
107
break
;
108
case
AREF_COMMON
:
109
if
(s->
subdev_flags
&
SDF_COMMON
)
110
return
0;
111
break
;
112
case
AREF_GROUND
:
113
if
(s->
subdev_flags
&
SDF_GROUND
)
114
return
0;
115
break
;
116
case
AREF_OTHER
:
117
if
(s->
subdev_flags
&
SDF_OTHER
)
118
return
0;
119
break
;
120
default
:
121
break
;
122
}
123
DPRINTK
(
"subdevice does not support aref %i"
, aref);
124
return
1;
125
}
126
127
/*
128
This function checks each element in a channel/gain list to make
129
make sure it is valid.
130
*/
131
int
comedi_check_chanlist
(
struct
comedi_subdevice
*s,
int
n
,
132
unsigned
int
*
chanlist
)
133
{
134
struct
comedi_device
*
dev
= s->
device
;
135
int
i
;
136
int
chan
;
137
138
if
(s->
range_table
) {
139
for
(i = 0; i <
n
; i++)
140
if
(
CR_CHAN
(chanlist[i]) >= s->
n_chan
||
141
CR_RANGE
(chanlist[i]) >= s->
range_table
->length
142
|| aref_invalid(s, chanlist[i])) {
143
dev_warn
(dev->
class_dev
,
144
"bad chanlist[%d]=0x%08x in_chan=%d range length=%d\n"
,
145
i, chanlist[i], s->
n_chan
,
146
s->
range_table
->length);
147
return
-
EINVAL
;
148
}
149
}
else
if
(s->
range_table_list
) {
150
for
(i = 0; i <
n
; i++) {
151
chan =
CR_CHAN
(chanlist[i]);
152
if
(chan >= s->
n_chan
||
153
CR_RANGE
(chanlist[i]) >=
154
s->
range_table_list
[chan]->length
155
|| aref_invalid(s, chanlist[i])) {
156
dev_warn
(dev->
class_dev
,
157
"bad chanlist[%d]=0x%08x\n"
,
158
i, chanlist[i]);
159
return
-
EINVAL
;
160
}
161
}
162
}
else
{
163
dev_err
(dev->
class_dev
,
"(bug) no range type list!\n"
);
164
return
-
EINVAL
;
165
}
166
return
0;
167
}
168
EXPORT_SYMBOL
(
comedi_check_chanlist
);
Generated on Thu Jan 10 2013 14:27:30 for Linux Kernel by
1.8.2