3 functions to retrieve kernel data
5 COMEDILIB - Linux Control and Measurement Device Interface Library
6 Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
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
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.
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
28 #include <sys/types.h>
32 #include <sys/ioctl.h>
36 #include "libinternal.h"
39 /* these functions download information from the comedi module. */
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);
47 int get_subdevices(comedi_t *it)
55 s = calloc(it->n_subdevices, sizeof(comedi_subdinfo));
63 ret = comedi_ioctl(it->fd, COMEDI_SUBDINFO, s);
70 assert(it->subdevices == NULL);
71 r = it->subdevices = calloc(it->n_subdevices, sizeof(subdevice));
79 it->has_insnlist_ioctl = do_test_for_insnlist(it);
80 it->has_insn_ioctl = do_test_for_insn(it);
81 for(i=0;i<it->n_subdevices;i++){
82 r[i].type = s[i].type;
83 if(r[i].type==COMEDI_SUBD_UNUSED)continue;
84 r[i].n_chan = s[i].n_chan;
85 r[i].subd_flags = s[i].subd_flags;
86 r[i].timer_type = s[i].timer_type;
87 r[i].len_chanlist = s[i].len_chanlist;
88 r[i].maxdata = s[i].maxdata;
89 r[i].flags = s[i].flags;
90 r[i].range_type = s[i].range_type;
92 if(r[i].subd_flags&SDF_FLAGS){
93 r[i].flags_list = calloc(r[i].n_chan, sizeof(*r[i].flags_list));
94 if(r[i].flags_list == NULL){
95 debug_ptr(r[i].flags_list);
101 if(r[i].subd_flags&SDF_MAXDATA){
102 r[i].maxdata_list = calloc(r[i].n_chan, sizeof(*r[i].maxdata_list));
103 if(r[i].maxdata_list == NULL){
104 debug_ptr(r[i].maxdata_list);
109 if(r[i].subd_flags&SDF_RANGETYPE){
110 r[i].range_type_list = calloc(r[i].n_chan, sizeof(*r[i].range_type_list));
111 if(r[i].range_type_list == NULL){
112 debug_ptr(r[i].range_type_list);
118 ci.flaglist = r[i].flags_list;
119 ci.rangelist = r[i].range_type_list;
120 ci.maxdata_list = r[i].maxdata_list;
121 ret = comedi_ioctl(it->fd, COMEDI_CHANINFO, &ci);
127 if(r[i].subd_flags&SDF_RANGETYPE){
128 r[i].rangeinfo_list=calloc(r[i].n_chan, sizeof(*r[i].rangeinfo_list));
129 if(r[i].rangeinfo_list == NULL){
130 debug_ptr(r[i].rangeinfo_list);
134 for(j=0;j<r[i].n_chan;j++){
135 r[i].rangeinfo_list[j]=get_rangeinfo(it->fd,r[i].range_type_list[j]);
136 if(r[i].rangeinfo_list[j] == NULL)
140 r[i].rangeinfo=get_rangeinfo(it->fd,r[i].range_type);
141 if(r[i].rangeinfo == NULL)
145 r[i].has_cmd = do_test_for_cmd(it,i);
146 switch(s[i].insn_bits_support)
148 case COMEDI_UNKNOWN_SUPPORT:
149 if(it->has_insnlist_ioctl){
150 r[i].has_insn_bits = do_test_for_insn_bits(it,i);
152 r[i].has_insn_bits = 0;
155 case COMEDI_SUPPORTED:
156 r[i].has_insn_bits = 1;
158 case COMEDI_UNSUPPORTED:
159 r[i].has_insn_bits = 0;
176 for(i=0;i<it->n_subdevices;i++){
178 free(r[i].flags_list);
179 if(r[i].maxdata_list)
180 free(r[i].maxdata_list);
181 if(r[i].range_type_list)
182 free(r[i].range_type_list);
183 if(r[i].rangeinfo_list){
184 for(j=0;j<r[i].n_chan;j++){
185 if(r[i].rangeinfo_list[j])
186 free(r[i].rangeinfo_list[j]);
190 free(r[i].rangeinfo);
194 it->subdevices = NULL;
200 comedi_range *get_rangeinfo(int fd,unsigned int range_type)
208 kr = calloc(RANGE_LENGTH(range_type), sizeof(comedi_krange));
215 r = calloc(RANGE_LENGTH(range_type), sizeof(comedi_range));
224 memset(&ri, 0, sizeof(ri));
225 ri.range_type = range_type;
227 ret = comedi_ioctl(fd, COMEDI_RANGEINFO, &ri);
229 fprintf(stderr,"ioctl(%d,COMEDI_RANGEINFO,0x%08x,%p)\n",fd,range_type,kr);
235 for(i=0;i<RANGE_LENGTH(range_type);i++){
236 r[i].min=kr[i].min*1e-6;
237 r[i].max=kr[i].max*1e-6;
238 r[i].unit=kr[i].flags;
246 /* some command testing */
248 static int do_test_for_cmd(comedi_t *dev,unsigned int subdevice)
250 /* SDF_CMD was added in 0.7.57 */
251 if(dev->devinfo.version_code >= COMEDI_VERSION_CODE(0,7,57)){
252 if(dev->subdevices[subdevice].subd_flags & SDF_CMD)
259 memset(&it,0,sizeof(it));
261 it.subdev = subdevice;
262 it.start_src = TRIG_ANY;
263 it.scan_begin_src = TRIG_ANY;
264 it.convert_src = TRIG_ANY;
265 it.scan_end_src = TRIG_ANY;
266 it.stop_src = TRIG_ANY;
268 ret = comedi_ioctl(dev->fd, COMEDI_CMDTEST, &it);
270 if(ret<0 && errno==EIO){
274 fprintf(stderr,"BUG in do_test_for_cmd()\n");
281 static int do_test_for_insnlist(comedi_t *dev)
291 memset(&insn,0,sizeof(insn));
292 insn.insn = INSN_GTOD;
295 memset(insn.data, 0, insn.n * sizeof(insn.data[0]));
297 ret = comedi_ioctl(dev->fd, COMEDI_INSNLIST, &il);
301 fprintf(stderr,"BUG in do_test_for_insnlist()\n");
308 /* the COMEID_INSN ioctl was introduced in comedi-0.7.60 */
309 static int do_test_for_insn(comedi_t *dev)
315 memset(&insn,0,sizeof(insn));
316 insn.insn = INSN_GTOD;
319 memset(insn.data, 0, insn.n * sizeof(insn.data[0]));
321 ret = comedi_ioctl(dev->fd, COMEDI_INSN, &insn);
325 fprintf(stderr,"BUG in do_test_for_insn()\n");
332 static int do_test_for_insn_bits(comedi_t *dev,unsigned int subdevice)
339 if(dev->subdevices[subdevice].maxdata != 1)
342 memset(&insn,0,sizeof(insn));
347 insn.insn = INSN_BITS;
350 insn.subdev = subdevice;
351 memset(data, 0, insn.n * sizeof(data[0]));
353 ret = comedi_do_insnlist(dev,&il);
355 if(ret<0 && (errno==EINVAL || errno==EIO)){
359 perror("BUG in do_test_for_insn_bits()\n");