from ds
[comedilib.git] / lib / filler.c
1 /*
2     lib/filler.c
3     functions to retrieve kernel data
4
5     COMEDILIB - Linux Control and Measurement Device Interface Library
6     Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
7
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation, version 2.1
11     of the License.
12
13     This library 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 GNU
16     Lesser General Public License for more details.
17
18     You should have received a copy of the GNU Lesser General Public
19     License along with this library; if not, write to the Free Software
20     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
21     USA.
22 */
23
24 #include <stdio.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/ioctl.h>
32 #include <errno.h>
33 #include <comedi.h>
34 #include <string.h>
35
36 #include <libinternal.h>
37
38
39 /* these functions download information from the comedi module. */
40
41 static int do_test_for_cmd(comedi_t *dev,unsigned int subdevice);
42 static int do_test_for_insn(comedi_t *dev);
43 static int do_test_for_insnlist(comedi_t *dev);
44 static int do_test_for_insn_bits(comedi_t *dev,unsigned int subdevice);
45
46
47 int get_subdevices(comedi_t *it)
48 {
49         int i,j;
50         int ret;
51         comedi_subdinfo *s;
52         subdevice *r;
53
54         s=malloc(sizeof(comedi_subdinfo)*it->n_subdevices);
55         debug_ptr(s);
56
57         ret=ioctl_subdinfo(it->fd,s);
58         debug_int(ret);
59
60         r=it->subdevices=realloc(it->subdevices,
61                 sizeof(subdevice)*it->n_subdevices);
62         debug_ptr(r);
63         memset(r,0,sizeof(subdevice)*it->n_subdevices);
64
65         it->has_insnlist_ioctl = do_test_for_insnlist(it);
66         it->has_insn_ioctl = do_test_for_insn(it);
67         for(i=0;i<it->n_subdevices;i++){
68                 r[i].type       = s[i].type;
69                 if(r[i].type==COMEDI_SUBD_UNUSED)continue;
70                 r[i].n_chan     = s[i].n_chan;
71                 r[i].subd_flags = s[i].subd_flags;
72                 r[i].timer_type = s[i].timer_type;
73                 r[i].len_chanlist = s[i].len_chanlist;
74                 r[i].maxdata    = s[i].maxdata;
75                 r[i].flags      = s[i].flags;
76                 r[i].range_type = s[i].range_type;
77
78                 if(r[i].subd_flags&SDF_FLAGS){
79                         r[i].flags_list=malloc(sizeof(*r[i].flags_list)*r[i].n_chan);
80                         debug_ptr(r[i].flags_list);
81                 }
82                 if(r[i].subd_flags&SDF_MAXDATA){
83                         r[i].maxdata_list=malloc(sizeof(*r[i].maxdata_list)*r[i].n_chan);
84                         debug_ptr(r[i].maxdata_list);
85                 }
86                 if(r[i].subd_flags&SDF_RANGETYPE){
87                         r[i].range_type_list=malloc(sizeof(*r[i].range_type_list)*r[i].n_chan);
88                         debug_ptr(r[i].range_type_list);
89                 }
90                 ret=ioctl_chaninfo(it->fd,i,r[i].maxdata_list,r[i].flags_list,r[i].range_type_list);
91                 debug_int(ret);
92
93                 if(r[i].subd_flags&SDF_RANGETYPE){
94                         r[i].rangeinfo_list=malloc(sizeof(*r[i].rangeinfo_list)*r[i].n_chan);
95                         debug_ptr(r[i].rangeinfo_list);
96                         for(j=0;j<r[i].n_chan;j++){
97                                 r[i].rangeinfo_list[j]=get_rangeinfo(it->fd,r[i].range_type_list[j]);
98                         }
99                 }else{
100                         r[i].rangeinfo=get_rangeinfo(it->fd,r[i].range_type);
101                 }
102
103                 r[i].has_cmd = do_test_for_cmd(it,i);
104                 if(it->has_insnlist_ioctl){
105                         r[i].has_insn_bits = do_test_for_insn_bits(it,i);
106                 }else{
107                         r[i].has_insn_bits = 0;
108                 }
109         }
110
111         free(s);
112
113         return 0;
114 }
115
116 comedi_range *get_rangeinfo(int fd,unsigned int range_type)
117 {
118         comedi_krange *kr;
119         comedi_range *r;
120         int ret;
121         int i;
122
123         kr=malloc(sizeof(comedi_krange)*RANGE_LENGTH(range_type));
124         r=malloc(sizeof(comedi_range)*RANGE_LENGTH(range_type));
125
126         ret=ioctl_rangeinfo(fd,range_type,kr);
127         if(ret<0){
128                 fprintf(stderr,"ioctl_rangeinfo(%d,0x%08x,%p)\n",fd,range_type,kr);
129         }
130
131         for(i=0;i<RANGE_LENGTH(range_type);i++){
132                 r[i].min=kr[i].min*1e-6;
133                 r[i].max=kr[i].max*1e-6;
134                 r[i].unit=kr[i].flags;
135         }
136         free(kr);
137
138         return r;
139 }
140
141
142 /* some command testing */
143
144 static int do_test_for_cmd(comedi_t *dev,unsigned int subdevice)
145 {
146         comedi_cmd it;
147         int ret;
148
149         memset(&it,0,sizeof(it));
150
151         it.subdev = subdevice;
152         it.start_src = TRIG_ANY;
153         it.scan_begin_src = TRIG_ANY;
154         it.convert_src = TRIG_ANY;
155         it.scan_end_src = TRIG_ANY;
156         it.stop_src = TRIG_ANY;
157
158         ret = ioctl(dev->fd,COMEDI_CMDTEST,&it);
159
160         if(ret<0 && errno==EIO){
161                 return 0;
162         }
163         if(ret<0){
164                 fprintf(stderr,"BUG in do_test_for_cmd()\n");
165                 return 0;
166         }
167         return 1;
168 }
169
170 static int do_test_for_insnlist(comedi_t *dev)
171 {
172         comedi_insn insn;
173         comedi_insnlist il;
174         lsampl_t data[2];
175         int ret;
176
177         memset(&insn,0,sizeof(insn));
178
179         il.n_insns = 1;
180         il.insns = &insn;
181
182         insn.insn = INSN_GTOD;
183         insn.n = 2;
184         insn.data = data;
185
186         ret = ioctl(dev->fd,COMEDI_INSNLIST,&il);
187
188         if(ret<0){
189                 if(errno!=EIO){
190                         fprintf(stderr,"BUG in do_test_for_insn()\n");
191                 }
192                 return 0;
193         }
194         return 1;
195 }
196
197 /* the COMEID_INSN ioctl was introduced in comedi-0.7.60 */
198 static int do_test_for_insn(comedi_t *dev)
199 {
200         comedi_insn insn;
201         comedi_insnlist il;
202         lsampl_t data[2];
203         int ret;
204
205         memset(&insn,0,sizeof(insn));
206
207         il.n_insns = 1;
208         il.insns = &insn;
209
210         insn.insn = INSN_GTOD;
211         insn.n = 2;
212         insn.data = data;
213
214         ret = ioctl(dev->fd,COMEDI_INSN,&insn);
215
216         if(ret<0){
217                 if(errno!=EIO){
218                         fprintf(stderr,"BUG in do_test_for_insn()\n");
219                 }
220                 return 0;
221         }
222         return 1;
223 }
224
225 static int do_test_for_insn_bits(comedi_t *dev,unsigned int subdevice)
226 {
227         comedi_insn insn;
228         comedi_insnlist il;
229         lsampl_t data[2];
230         int ret;
231
232         memset(&insn,0,sizeof(insn));
233
234         il.n_insns = 1;
235         il.insns = &insn;
236
237         insn.insn = INSN_BITS;
238         insn.n = 2;
239         insn.data = data;
240         insn.subdev = subdevice;
241
242         data[0]=0;
243         data[1]=0;
244
245         ret = comedi_do_insnlist(dev,&il);
246
247         if(ret<0 && (errno==EINVAL || errno==EIO)){
248                 return 0;
249         }
250         if(ret<0){
251                 perror("BUG in do_test_for_insn_bits()\n");
252                 return 0;
253         }
254         return 1;
255 }
256
257
258