fd304f1ba6ce6cbeec5731e3c88ff668bb316b33
[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         comedi_chaninfo ci;
53         subdevice *r;
54
55         s=malloc(sizeof(comedi_subdinfo)*it->n_subdevices);
56         debug_ptr(s);
57
58         ret = comedi_ioctl(it->fd, COMEDI_SUBDINFO, (unsigned long)s);
59         debug_int(ret);
60
61         r=it->subdevices=realloc(it->subdevices,
62                 sizeof(subdevice)*it->n_subdevices);
63         debug_ptr(r);
64         memset(r,0,sizeof(subdevice)*it->n_subdevices);
65
66         it->has_insnlist_ioctl = do_test_for_insnlist(it);
67         it->has_insn_ioctl = do_test_for_insn(it);
68         for(i=0;i<it->n_subdevices;i++){
69                 r[i].type       = s[i].type;
70                 if(r[i].type==COMEDI_SUBD_UNUSED)continue;
71                 r[i].n_chan     = s[i].n_chan;
72                 r[i].subd_flags = s[i].subd_flags;
73                 r[i].timer_type = s[i].timer_type;
74                 r[i].len_chanlist = s[i].len_chanlist;
75                 r[i].maxdata    = s[i].maxdata;
76                 r[i].flags      = s[i].flags;
77                 r[i].range_type = s[i].range_type;
78
79                 if(r[i].subd_flags&SDF_FLAGS){
80                         r[i].flags_list=malloc(sizeof(*r[i].flags_list)*r[i].n_chan);
81                         debug_ptr(r[i].flags_list);
82                 }
83                 if(r[i].subd_flags&SDF_MAXDATA){
84                         r[i].maxdata_list=malloc(sizeof(*r[i].maxdata_list)*r[i].n_chan);
85                         debug_ptr(r[i].maxdata_list);
86                 }
87                 if(r[i].subd_flags&SDF_RANGETYPE){
88                         r[i].range_type_list=malloc(sizeof(*r[i].range_type_list)*r[i].n_chan);
89                         debug_ptr(r[i].range_type_list);
90                 }
91                 ci.subdev = i;
92                 ci.flaglist = r[i].flags_list;
93                 ci.rangelist = r[i].range_type_list;
94                 ci.maxdata_list = r[i].maxdata_list;
95                 ret = comedi_ioctl(it->fd, COMEDI_CHANINFO, (unsigned long)&ci);
96                 debug_int(ret);
97
98                 if(r[i].subd_flags&SDF_RANGETYPE){
99                         r[i].rangeinfo_list=malloc(sizeof(*r[i].rangeinfo_list)*r[i].n_chan);
100                         debug_ptr(r[i].rangeinfo_list);
101                         for(j=0;j<r[i].n_chan;j++){
102                                 r[i].rangeinfo_list[j]=get_rangeinfo(it->fd,r[i].range_type_list[j]);
103                         }
104                 }else{
105                         r[i].rangeinfo=get_rangeinfo(it->fd,r[i].range_type);
106                 }
107
108                 r[i].has_cmd = do_test_for_cmd(it,i);
109                 if(it->has_insnlist_ioctl){
110                         r[i].has_insn_bits = do_test_for_insn_bits(it,i);
111                 }else{
112                         r[i].has_insn_bits = 0;
113                 }
114         }
115
116         free(s);
117
118         return 0;
119 }
120
121 comedi_range *get_rangeinfo(int fd,unsigned int range_type)
122 {
123         comedi_krange *kr;
124         comedi_range *r;
125         comedi_rangeinfo ri;
126         int ret;
127         int i;
128
129         kr=malloc(sizeof(comedi_krange)*RANGE_LENGTH(range_type));
130         r=malloc(sizeof(comedi_range)*RANGE_LENGTH(range_type));
131
132         ri.range_type = range_type;
133         ri.range_ptr = kr;
134         ret = comedi_ioctl(fd, COMEDI_RANGEINFO, (unsigned long)&ri);
135         if(ret<0){
136                 fprintf(stderr,"ioctl(%d,COMEDI_RANGEINFO,0x%08x,%p)\n",fd,range_type,kr);
137         }
138
139         for(i=0;i<RANGE_LENGTH(range_type);i++){
140                 r[i].min=kr[i].min*1e-6;
141                 r[i].max=kr[i].max*1e-6;
142                 r[i].unit=kr[i].flags;
143         }
144         free(kr);
145
146         return r;
147 }
148
149
150 /* some command testing */
151
152 static int do_test_for_cmd(comedi_t *dev,unsigned int subdevice)
153 {
154         /* SDF_CMD was added in 0.7.57 */
155         if(dev->devinfo.version_code >= COMEDI_VERSION_CODE(0,7,57)){
156                 if(dev->subdevices[subdevice].subd_flags & SDF_CMD)
157                         return 1;
158                 return 0;
159         }else{
160                 comedi_cmd it;
161                 int ret;
162
163                 memset(&it,0,sizeof(it));
164
165                 it.subdev = subdevice;
166                 it.start_src = TRIG_ANY;
167                 it.scan_begin_src = TRIG_ANY;
168                 it.convert_src = TRIG_ANY;
169                 it.scan_end_src = TRIG_ANY;
170                 it.stop_src = TRIG_ANY;
171
172                 ret = comedi_ioctl(dev->fd, COMEDI_CMDTEST, (unsigned long)&it);
173
174                 if(ret<0 && errno==EIO){
175                         return 0;
176                 }
177                 if(ret<0){
178                         fprintf(stderr,"BUG in do_test_for_cmd()\n");
179                         return 0;
180                 }
181                 return 1;
182         }
183 }
184
185 static int do_test_for_insnlist(comedi_t *dev)
186 {
187         comedi_insn insn;
188         comedi_insnlist il;
189         lsampl_t data[2];
190         int ret;
191
192         memset(&insn,0,sizeof(insn));
193
194         il.n_insns = 1;
195         il.insns = &insn;
196
197         insn.insn = INSN_GTOD;
198         insn.n = 2;
199         insn.data = data;
200
201         ret = comedi_ioctl(dev->fd, COMEDI_INSNLIST, (unsigned long)&il);
202
203         if(ret<0){
204                 if(errno!=EIO){
205                         fprintf(stderr,"BUG in do_test_for_insn()\n");
206                 }
207                 return 0;
208         }
209         return 1;
210 }
211
212 /* the COMEID_INSN ioctl was introduced in comedi-0.7.60 */
213 static int do_test_for_insn(comedi_t *dev)
214 {
215         comedi_insn insn;
216         comedi_insnlist il;
217         lsampl_t data[2];
218         int ret;
219
220         memset(&insn,0,sizeof(insn));
221
222         il.n_insns = 1;
223         il.insns = &insn;
224
225         insn.insn = INSN_GTOD;
226         insn.n = 2;
227         insn.data = data;
228
229         ret = comedi_ioctl(dev->fd, COMEDI_INSN, (unsigned long)&insn);
230
231         if(ret<0){
232                 if(errno!=EIO){
233                         fprintf(stderr,"BUG in do_test_for_insn()\n");
234                 }
235                 return 0;
236         }
237         return 1;
238 }
239
240 static int do_test_for_insn_bits(comedi_t *dev,unsigned int subdevice)
241 {
242         comedi_insn insn;
243         comedi_insnlist il;
244         lsampl_t data[2];
245         int ret;
246
247         if(dev->subdevices[subdevice].maxdata != 1)
248                 return 0;
249
250         memset(&insn,0,sizeof(insn));
251
252         il.n_insns = 1;
253         il.insns = &insn;
254
255         insn.insn = INSN_BITS;
256         insn.n = 2;
257         insn.data = data;
258         insn.subdev = subdevice;
259
260         data[0]=0;
261         data[1]=0;
262
263         ret = comedi_do_insnlist(dev,&il);
264
265         if(ret<0 && (errno==EINVAL || errno==EIO)){
266                 return 0;
267         }
268         if(ret<0){
269                 perror("BUG in do_test_for_insn_bits()\n");
270                 return 0;
271         }
272         return 1;
273 }
274
275
276