2 This program reads information about a comedi device and
3 displays the information in a human-readable form.
15 static char * const default_filename = "/dev/comedi0";
19 static const char * const subdevice_types[]={
36 const char *sdf_define;
38 const char *description;
41 static struct subdev_flag subdev_flags[] = {
42 {"SDF_MAXDATA",0x0010,"maxdata depends on channel"},
43 {"SDF_FLAGS",0x0020,"flags depend on channel"},
44 {"SDF_RANGETYPE",0x0040,"range type depends on channel"},
45 {"SDF_MODE0",0x0080,"can do mode 0"},
46 {"SDF_MODE1",0x0100,"can do mode 1"},
47 {"SDF_MODE2",0x0200,"can do mode 2"},
48 {"SDF_MODE3",0x0400,"can do mode 3"},
49 {"SDF_MODE4",0x0800,"can do mode 4"},
50 {"SDF_SOFT_CALIBRATED",0x2000,"subdevice uses software calibration"},
51 {"SDF_CMD_WRITE",0x4000,"can do asynchronous output commands"},
52 {"SDF_CMD_READ",0x8000,"can do asynchronous input commands"},
53 {"SDF_READABLE",0x00010000,"subdevice can be read"},
54 {"SDF_WRITABLE",0x00020000,"subdevice can be written"},
55 {"SDF_INTERNAL",0x00040000,"subdevice does not have externally visible lines"},
56 {"SDF_GROUND",0x00100000,"can do aref=ground"},
57 {"SDF_COMMON",0x00200000,"can do aref=common"},
58 {"SDF_DIFF",0x00400000,"aref=diff"},
59 {"SDF_OTHER",0x00800000,"can do aref=other"},
60 {"SDF_DITHER",0x01000000,"can do dithering"},
61 {"SDF_DEGLITCH",0x02000000,"can do deglitching"},
62 {"SDF_MMAP",0x04000000,"can do mmap()"},
63 {"SDF_RUNNING",0x08000000,"subdevice is acquiring data"},
64 {"SDF_LSAMPL",0x10000000,"subdevice uses 32-bit samples for commands"},
65 {"SDF_PACKED",0x20000000,"subdevice can do packed DIO"},
68 void explain_subdevice_flags(char* padding,unsigned int sf) {
70 while (subdev_flags[i].sdf_define) {
71 if (sf & subdev_flags[i].bitmask)
74 subdev_flags[i].sdf_define,
75 subdev_flags[i].description);
80 void unit_to_desc(char *udesc,int unit) {
82 case UNIT_volt: strcpy(udesc," V"); break;
83 case UNIT_mA: strcpy(udesc," mA"); break;
84 case UNIT_none: strcpy(udesc,""); break;
85 default: sprintf(udesc," (unknown unit %d)",
92 char *tobinary(char *s,int bits,int n)
98 *t++=(bits&bit)?'1':'0';
105 char *cmd_src(int src,char *buf)
109 if(src&TRIG_NONE)strcat(buf,"none|");
110 if(src&TRIG_NOW)strcat(buf,"now|");
111 if(src&TRIG_FOLLOW)strcat(buf, "follow|");
112 if(src&TRIG_TIME)strcat(buf, "time|");
113 if(src&TRIG_TIMER)strcat(buf, "timer|");
114 if(src&TRIG_COUNT)strcat(buf, "count|");
115 if(src&TRIG_EXT)strcat(buf, "ext|");
116 if(src&TRIG_INT)strcat(buf, "int|");
118 if(src&TRIG_OTHER)strcat(buf, "other|");
122 sprintf(buf,"unknown(0x%08x)",src);
124 buf[strlen(buf)-1]=0;
132 void probe_cmd_generic_timed(comedi_t *it,int s,int n_channels,int freq_for_generic_timed)
137 printf(" command structure filled with probe_cmd_generic_timed for %d channels:\n",
139 if(comedi_get_cmd_generic_timed(it, s, &cmd, n_channels, 1E9/freq_for_generic_timed)<0){
140 printf(" not supported\n");
142 printf(" start: %s %d\n",
143 cmd_src(cmd.start_src,buf),cmd.start_arg);
144 printf(" scan_begin: %s %d\n",
145 cmd_src(cmd.scan_begin_src,buf),cmd.scan_begin_arg);
147 if ((cmd.scan_begin_src == TRIG_TIMER)&&(cmd.scan_begin_arg)) {
148 printf(" scan_begin_src = TRIG_TIMER:\n"
149 " The sampling rate is defined per scan\n"
150 " meaning all channels are sampled at\n"
151 " the same time. The maximum sampling rate is f=%d Hz\n",
152 (int)(1E9/cmd.scan_begin_arg));}
154 printf(" convert: %s %d\n",
155 cmd_src(cmd.convert_src,buf),cmd.convert_arg);
157 if ((cmd.convert_src == TRIG_TIMER)&&(cmd.convert_arg)) {
158 printf(" convert_src = TRIG_TIMER\n"
159 " The sampling rate is defined per channel\n"
160 " meaning that a multiplexer is being switched from\n"
161 " channel to channel at a maximum rate of %d Hz.\n"
162 " The overall sampling rate needs to be divided\n"
163 " by the number of channels and results in f=%d Hz.\n",
164 (int)(1E9/cmd.convert_arg),
165 (int)(1E9/cmd.convert_arg/n_channels));
168 printf(" scan_end: %s %d\n",
169 cmd_src(cmd.scan_end_src,buf),cmd.scan_end_arg);
170 printf(" stop: %s %d\n",
171 cmd_src(cmd.stop_src,buf),cmd.stop_arg);
177 void get_command_stuff(comedi_t *it,int s,int n_chans_for_generic_timed,int freq_for_generic_timed)
182 if(comedi_get_cmd_src_mask(it,s,&cmd)<0){
183 printf(" not supported\n");
185 printf(" start: %s\n",cmd_src(cmd.start_src,buf));
186 if (cmd.start_src == TRIG_EXT)
187 printf(" cmd.start_src allows external trigger (TRIG_EXT),"
188 " for example from on input pin at the device.\n");
189 printf(" scan_begin: %s\n",cmd_src(cmd.scan_begin_src,buf));
190 printf(" convert: %s\n",cmd_src(cmd.convert_src,buf));
191 printf(" scan_end: %s\n",cmd_src(cmd.scan_end_src,buf));
192 printf(" stop: %s\n",cmd_src(cmd.stop_src,buf));
194 probe_cmd_generic_timed(it,s,n_chans_for_generic_timed,freq_for_generic_timed);
200 int main(int argc,char *argv[])
203 int n_subdevices,type;
204 const char *type_str;
210 char *filename = default_filename;
213 int n_chans_for_generic_timed = 1;
214 int freq_for_generic_timed = 1E9;
216 while (-1 != (c = getopt(argc, argv, "hvn:F:"))) {
219 n_chans_for_generic_timed = strtoul(optarg, NULL, 0);
222 freq_for_generic_timed = strtoul(optarg, NULL, 0);
230 "usage: comedi_board_info [OPTIONS] COMEDI_DEVICE\n"
231 " -n number of channels for async command (default 1)\n"
232 " -F probing sampling rate for async command (default 1Ghz)\n"
233 " -v verbose output\n"
234 " -h this help screen\n");
240 filename = argv[optind];
243 it = comedi_open(filename);
245 comedi_perror(filename);
249 printf("overall info:\n");
250 printf(" version code: 0x%06x\n", comedi_get_version_code(it));
251 printf(" driver name: %s\n", comedi_get_driver_name(it));
252 printf(" board name: %s\n", comedi_get_board_name(it));
253 printf(" number of subdevices: %d\n", n_subdevices = comedi_get_n_subdevices(it));
255 for(i = 0; i < n_subdevices; i++){
256 printf("subdevice %d:\n",i);
257 type = comedi_get_subdevice_type(it, i);
258 if(type < (int)(sizeof(subdevice_types) / sizeof(subdevice_types[0]))){
259 type_str = subdevice_types[type];
261 type_str = "UNKNOWN";
263 printf(" type: %d (%s)\n",type,type_str);
264 if(type==COMEDI_SUBD_UNUSED)
266 subdev_flags = comedi_get_subdevice_flags(it, i);
267 printf(" flags: 0x%08x\n",subdev_flags);
268 if (verbose) explain_subdevice_flags(" ",subdev_flags);
269 n_chans=comedi_get_n_channels(it,i);
270 printf(" number of channels: %d\n",n_chans);
271 if(!comedi_maxdata_is_chan_specific(it,i)){
272 printf(" max data value: %lu\n", (unsigned long)comedi_get_maxdata(it,i,0));
274 printf(" max data value: (channel specific)\n");
275 for(chan=0;chan<n_chans;chan++){
276 printf(" chan%d: %lu\n",chan,
277 (unsigned long)comedi_get_maxdata(it,i,chan));
280 printf(" ranges:\n");
281 if(!comedi_range_is_chan_specific(it,i)){
282 n_ranges=comedi_get_n_ranges(it,i,0);
283 printf(" all chans:");
284 for(j=0;j<n_ranges;j++){
285 rng=comedi_get_range(it,i,0,j);
286 unit_to_desc(strtmp,rng->unit);
287 printf(" [%g%s,%g%s]",rng->min,strtmp,rng->max,strtmp);
291 for(chan=0;chan<n_chans;chan++){
292 n_ranges=comedi_get_n_ranges(it,i,chan);
293 printf(" chan%d:",chan);
294 for(j=0;j<n_ranges;j++){
295 rng=comedi_get_range(it,i,chan,j);
296 unit_to_desc(strtmp,rng->unit);
297 printf(" [%g%s,%g%s]",rng->min,strtmp,rng->max,strtmp);
302 printf(" command:\n");
303 if (n_chans_for_generic_timed>n_chans)
304 n_chans_for_generic_timed = n_chans;
305 if (n_chans_for_generic_timed<1)
306 n_chans_for_generic_timed = 1;
307 if (freq_for_generic_timed > 1E9)
308 freq_for_generic_timed = 1E9;
309 if (freq_for_generic_timed < 1)
310 freq_for_generic_timed = 1;
311 get_command_stuff(it,i,n_chans_for_generic_timed,freq_for_generic_timed);