136ed044394fae11ced76e77cfa5b10fc5a1941b
[comedi.git] / comedi / range.c
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 <ds@stm.lbl.gov>
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 <comedi_module.h>
25 #ifdef LINUX_V22
26 #include <asm/uaccess.h>
27 #endif
28
29
30 comedi_lrange range_bipolar10={ 1, {BIP_RANGE(10)}};
31 comedi_lrange range_bipolar5={ 1, {BIP_RANGE(5)}};
32 comedi_lrange range_bipolar2_5={ 1, {BIP_RANGE(2.5)}};
33 comedi_lrange range_unipolar10={ 1, {UNI_RANGE(10)}};
34 comedi_lrange range_unipolar5={ 1, {UNI_RANGE(5)}};
35 comedi_lrange range_unknown={ 1, {{0,1,0}}};    /* XXX */
36
37 /*
38         COMEDI_RANGEINFO
39         range information ioctl
40
41         arg:
42                 pointer to rangeinfo structure
43
44         reads:
45                 range info structure
46         
47         writes:
48                 n comedi_krange structures to rangeinfo->range_ptr
49 */
50 int do_rangeinfo_ioctl(comedi_device *dev,comedi_rangeinfo *arg)
51 {
52         comedi_rangeinfo it;
53         int minor,subd,chan;
54         comedi_lrange *lr;
55         comedi_subdevice *s;
56
57         if(copy_from_user(&it,arg,sizeof(comedi_rangeinfo)))
58                 return -EFAULT;
59
60         minor=(it.range_type>>24)&0xf;
61         subd=(it.range_type>>20)&0xf;
62         chan=(it.range_type>>16)&0xff;
63
64         if(minor>COMEDI_NDEVICES)
65                 return -EINVAL;
66         dev=comedi_devices+minor;
67         if(!dev->attached)return -EINVAL;
68         if(subd>=dev->n_subdevices)return -EINVAL;
69         s=dev->subdevices+subd;
70         if(s->range_table){
71                 lr=s->range_table;
72         }else if(s->range_table_list){
73                 if(chan>=s->n_chan)return -EINVAL;
74                 lr=s->range_table_list[chan];
75         }else{
76                 return -EINVAL;
77         }
78
79         if(copy_to_user(it.range_ptr,lr->range,
80                 sizeof(comedi_krange)*lr->length))
81                 return -EFAULT;
82         
83         return 0;
84 }
85
86
87 /*
88    This function checks each element in a channel/gain list to make
89    make sure it is valid.
90 */
91 int check_chanlist(comedi_subdevice *s,int n,unsigned int *chanlist)
92 {
93         int i;
94         int chan;
95
96
97         if(s->range_table){
98                 for(i=0;i<n;i++)
99                         if(CR_CHAN(chanlist[i])>=s->n_chan || 
100                            CR_RANGE(chanlist[i])>=s->range_table->length){
101                                 rt_printk("bad chanlist[%d]=0x%08x n_chan=%d range length=%d\n",
102                                         i,chanlist[i],s->n_chan,s->range_table->length);
103 #if 0
104 for(i=0;i<n;i++){
105         printk("[%d]=0x%08x\n",i,chanlist[i]);
106 }
107 #endif
108                                 return -EINVAL;
109                         }
110         }else if(s->range_table_list){
111                 for(i=0;i<n;i++){
112                         chan=CR_CHAN(chanlist[i]);
113                         if(chan>=s->n_chan ||
114                            CR_RANGE(chanlist[i])>=s->range_table_list[chan]->length){
115                                 rt_printk("bad chanlist[%d]=0x%08x\n",i,chanlist[i]);
116                                 return -EINVAL;
117                         }
118                 }
119         }else{
120                 rt_printk("comedi: (bug) no range type list!\n");
121                 return -EINVAL;
122         }
123         return 0;
124 }
125
126