![]() |
RTXI 1.3
|
00001 /* 00002 comedi_config/comedi_config.c 00003 configuration program for comedi kernel module 00004 00005 COMEDI - Linux Control and Measurement Device Interface 00006 Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 */ 00023 00024 #define CC_VERSION "0.7.16" 00025 00026 #include <sys/types.h> 00027 #include <sys/stat.h> 00028 #include <sys/sysmacros.h> 00029 #include <fcntl.h> 00030 #include <sys/ioctl.h> 00031 #include <stdio.h> 00032 #include <getopt.h> 00033 #include <errno.h> 00034 #include <string.h> 00035 #include <stdint.h> 00036 #include <stdlib.h> 00037 #include <unistd.h> 00038 #include <getopt.h> 00039 00040 #include <comedi.h> 00041 00042 #ifdef I18N 00043 #include <libintl.h> 00044 #define _(a) gettext(a) 00045 #else 00046 #define _(a) (a) 00047 #endif 00048 00049 int quiet=0,verbose=0; 00050 00051 int read_buf_size=0; 00052 int write_buf_size=0; 00053 00054 int init_fd; 00055 #define MAX_NUM_INIT_FILES 4 00056 char *init_file[MAX_NUM_INIT_FILES] = {NULL,NULL,NULL,NULL}; 00057 00058 enum option_ids 00059 { 00060 READ_BUFFER_OPT_ID = 0x1000, 00061 WRITE_BUFFER_OPT_ID, 00062 INIT_DATA1_OPT_ID, 00063 INIT_DATA2_OPT_ID, 00064 INIT_DATA3_OPT_ID 00065 }; 00066 00067 struct option options[] = { 00068 { "verbose", 0, NULL, 'v' }, 00069 { "quiet", 0, NULL, 'q' }, 00070 { "version", 0, NULL, 'V' }, 00071 { "init-data", 1, NULL, 'i' }, 00072 { "init-data0", 1, NULL, 'i' }, 00073 { "remove", 0, NULL, 'r' }, 00074 { "read-buffer", 1, NULL, READ_BUFFER_OPT_ID}, 00075 { "write-buffer", 1, NULL, WRITE_BUFFER_OPT_ID}, 00076 { "init-data1", 1, NULL, INIT_DATA1_OPT_ID }, 00077 { "init-data2", 1, NULL, INIT_DATA2_OPT_ID }, 00078 { "init-data3", 1, NULL, INIT_DATA3_OPT_ID }, 00079 { 0 }, 00080 }; 00081 00082 void do_help(int i) 00083 { 00084 fputs("comedi_config version " CC_VERSION "\n",stderr); 00085 fputs( 00086 _("usage: comedi_config [OPTIONS] <device file> [<driver> <opt1>,<opt2>,...]\n" 00087 "\n" 00088 "OPTIONS:\n" 00089 " -v, --verbose\n" 00090 " verbose output\n" 00091 " -q, --quiet\n" 00092 " quiet output\n" 00093 " -V, --version\n" 00094 " print program version\n" 00095 " -i, --init-data, --init-data0 <filename>\n" 00096 " Use file for driver initialization data, typically firmware code.\n" 00097 " --init-data1 <filename>\n" 00098 " --init-data2 <filename>\n" 00099 " --init-data3 <filename>\n" 00100 " Some drivers require multiple files of initialization data. Use these\n" 00101 " options to specify them. See the driver-specific documentation for further details.\n" 00102 " -r, --remove\n" 00103 " remove previously configured driver\n" 00104 " --read-buffer <size>\n" 00105 " set buffer size in kilobytes used for reading\n" 00106 " --write-buffer <size>\n" 00107 " set buffer size in kilobytes used for writing\n" 00108 "\n" 00109 " <optN> are integers whose interpretation is driver dependent.\n" 00110 " In general, for PCI boards, <opt1> and <opt2> refer to the bus/slot\n" 00111 " indices of the board. If not specified, a board will automatically\n" 00112 " be chosen. For non-PCI boards, <opt1> specifies the I/O port base\n" 00113 " address and, if applicable, <opt2> specifies the IRQ. Additional\n" 00114 " options may be useful, see the Comedi documentation for details.\n") 00115 ,stderr); 00116 exit(i); 00117 } 00118 00119 void read_init_files(char* file_names[], int num_files, int *options) 00120 { 00121 int i; 00122 int offset; 00123 FILE* files[num_files]; 00124 int sizes[num_files]; 00125 uintptr_t data_address; 00126 int data_length = 0; 00127 void *data = NULL; 00128 for(i = 0; i < num_files; ++i) 00129 { 00130 struct stat buf; 00131 if(file_names[i] == NULL) 00132 { 00133 sizes[i] = 0; 00134 continue; 00135 } 00136 files[i] = fopen(file_names[i],"r"); 00137 if(files[i] == NULL) 00138 { 00139 perror(file_names[i]); 00140 exit(1); 00141 } 00142 fstat(fileno(files[i]), &buf); 00143 sizes[i] = buf.st_size; 00144 data_length += sizes[i]; 00145 } 00146 options[COMEDI_DEVCONF_AUX_DATA0_LENGTH] = sizes[0]; 00147 options[COMEDI_DEVCONF_AUX_DATA1_LENGTH] = sizes[1]; 00148 options[COMEDI_DEVCONF_AUX_DATA2_LENGTH] = sizes[2]; 00149 options[COMEDI_DEVCONF_AUX_DATA3_LENGTH] = sizes[3]; 00150 options[COMEDI_DEVCONF_AUX_DATA_LENGTH] = data_length; 00151 if(data_length == 0) 00152 { 00153 return; 00154 } 00155 data = malloc(data_length); 00156 if(data==NULL) 00157 { 00158 perror(_("allocating initialization data\n")); 00159 exit(1); 00160 } 00161 data_address = (uintptr_t)data; 00162 options[COMEDI_DEVCONF_AUX_DATA_LO] = data_address; 00163 options[COMEDI_DEVCONF_AUX_DATA_HI] = 0; 00164 if(sizeof(void*) > sizeof(int)) 00165 { 00166 int bit_shift = sizeof(int) * 8; 00167 options[COMEDI_DEVCONF_AUX_DATA_HI] = data_address >> bit_shift; 00168 } 00169 offset = 0; 00170 for(i = 0; i < num_files; ++i) 00171 { 00172 size_t ret; 00173 if(file_names[i] == NULL) 00174 { 00175 continue; 00176 } 00177 ret = fread(data + offset, 1, sizes[i], files[i]); 00178 if(ret < sizes[i]) 00179 { 00180 perror(_("reading initialization data\n")); 00181 exit(1); 00182 } 00183 offset += sizes[i]; 00184 fclose(files[i]); 00185 } 00186 return; 00187 } 00188 00189 int main(int argc,char *argv[]) 00190 { 00191 comedi_devconfig it; 00192 comedi_bufconfig bc; 00193 comedi_devinfo devinfo; 00194 int fd; 00195 int c,i,num,k; 00196 char *opts; 00197 char *fn,*driver; 00198 struct stat statbuf; 00199 int ret; 00200 int remove=0; 00201 int index; 00202 00203 #ifdef I18N 00204 setlocale(LC_ALL, ""); 00205 bindtextdomain("comedilib", "/usr/share/locale"); 00206 textdomain("comedilib"); 00207 #endif 00208 00209 if(geteuid() != 0) 00210 fprintf(stderr,_("comedi_config should be run as root. Attempting to continue anyway.\n")); 00211 00212 while(1){ 00213 c=getopt_long(argc, argv, "rvVqi:", options, &index); 00214 if(c==-1)break; 00215 switch(c){ 00216 case 'v': 00217 verbose=1; 00218 break; 00219 case 'V': 00220 fputs("comedi_config version " CC_VERSION "\n",stderr); 00221 exit(0); 00222 break; 00223 case 'q': 00224 quiet=1; 00225 break; 00226 case 'r': 00227 remove=1; 00228 break; 00229 case 'i': 00230 init_file[0]=optarg; 00231 break; 00232 case INIT_DATA1_OPT_ID: 00233 init_file[1]=optarg; 00234 break; 00235 case INIT_DATA2_OPT_ID: 00236 init_file[2]=optarg; 00237 break; 00238 case INIT_DATA3_OPT_ID: 00239 init_file[3]=optarg; 00240 break; 00241 case READ_BUFFER_OPT_ID: 00242 read_buf_size = strtol(optarg, NULL, 0); 00243 if(read_buf_size < 0) 00244 { 00245 fprintf(stderr, _("invalid buffer size\n")); 00246 exit(-1); 00247 } 00248 break; 00249 case WRITE_BUFFER_OPT_ID: 00250 write_buf_size = strtol(optarg, NULL, 0); 00251 if(write_buf_size < 0) 00252 { 00253 fprintf(stderr, _("invalid buffer size\n")); 00254 exit(-1); 00255 } 00256 break; 00257 default: 00258 do_help(1); 00259 } 00260 } 00261 00262 if((argc-optind) < 1 || (argc-optind) > 3 || 00263 ((argc-optind) == 1 && read_buf_size == 0 && write_buf_size == 0 && remove == 0)){ 00264 do_help(1); 00265 } 00266 00267 fn=argv[optind]; 00268 00269 fd=open(fn,O_RDWR); 00270 if(fd<0){ 00271 switch(errno){ 00272 case ENODEV: 00273 fprintf(stderr,_("comedi.o not loaded\n")); 00274 break; 00275 case ENXIO: 00276 fprintf(stderr,_("device not configured\n")); 00277 break; 00278 case EPERM: 00279 fprintf(stderr,_("modprobe problem\n")); 00280 break; 00281 default: 00282 perror(fn); 00283 break; 00284 } 00285 exit(1); 00286 } 00287 00288 // if we are attaching or detaching a device 00289 if((argc-optind) > 1 || ((argc-optind) == 1 && remove)) 00290 { 00291 if(argc - optind > 1) 00292 driver=argv[optind+1]; 00293 else 00294 driver = "none"; 00295 strncpy(it.board_name,driver,COMEDI_NAMELEN-1); 00296 00297 for(i=0;i<COMEDI_NDEVCONFOPTS;i++)it.options[i]=0; 00298 00299 if((argc-optind)==3){ 00300 opts=argv[optind+2]; 00301 i=0; 00302 while(*opts){ 00303 if((*opts)==','){ 00304 i++; 00305 opts++; 00306 if(i>=COMEDI_NDEVCONFOPTS) 00307 do_help(1); 00308 continue; 00309 } 00310 if(sscanf(opts,"%i%n",&num,&k)>0){ 00311 it.options[i]=num; 00312 opts+=k; 00313 continue; 00314 } 00315 do_help(1); 00316 } 00317 } 00318 00319 ret=stat(fn,&statbuf); 00320 if(ret<0){ 00321 perror(fn); 00322 exit(1); 00323 } 00324 #if 0 00325 /* this appears to be broken */ 00326 if( !(S_ISCHR(statbuf.st_mode)) || 00327 major(statbuf.st_dev)!=COMEDI_MAJOR){ 00328 if(!quiet) 00329 fprintf(stderr,"warning: %s might not be a comedi device\n",fn); 00330 } 00331 #endif 00332 read_init_files(init_file, MAX_NUM_INIT_FILES, it.options); 00333 /* add: sanity check for device */ 00334 00335 if(verbose){ 00336 printf(_("configuring driver=%s "),it.board_name); 00337 for(i=0;i<COMEDI_NDEVCONFOPTS;i++)printf("%d,",it.options[i]); 00338 printf("\n"); 00339 } 00340 if(ioctl(fd,COMEDI_DEVCONFIG,remove?NULL:&it)<0){ 00341 int err=errno; 00342 perror(_("Configure failed!")); 00343 fprintf(stderr,_("Check kernel log for more information\n")); 00344 fprintf(stderr,_("Possible reasons for failure:\n")); 00345 switch(err){ 00346 case EINVAL: 00347 fprintf(stderr," \n"); 00348 break; 00349 case EBUSY: 00350 fprintf(stderr,_(" Already configured\n")); 00351 break; 00352 case EIO: 00353 fprintf(stderr,_(" Driver not found\n")); 00354 break; 00355 case EPERM: 00356 fprintf(stderr,_(" Not root\n")); 00357 break; 00358 case EFAULT: 00359 fprintf(stderr,_(" Comedi bug\n")); 00360 break; 00361 default: 00362 fprintf(stderr,_(" Unknown\n")); 00363 break; 00364 } 00365 00366 exit(1); 00367 } 00368 } 00369 00370 // dont do buffer resize if we have removed device 00371 if(remove == 0) 00372 { 00373 if(read_buf_size || write_buf_size){ 00374 ret = ioctl(fd,COMEDI_DEVINFO,&devinfo); 00375 if(ret<0){ 00376 perror("devinfo"); 00377 exit(1); 00378 } 00379 if(devinfo.version_code < ((7<<8) | (57))){ 00380 fprintf(stderr,_("Buffer resizing requires Comedi version >= 0.7.57\n")); 00381 exit(1); 00382 } 00383 } 00384 00385 // do buffer resizing 00386 if(read_buf_size) 00387 { 00388 if(devinfo.read_subdevice < 0){ 00389 fprintf(stderr,_("warning: no read subdevice, resize ignored\n")); 00390 }else{ 00391 memset(&bc, 0, sizeof(bc)); 00392 bc.subdevice = devinfo.read_subdevice; 00393 bc.maximum_size = read_buf_size * 1024; 00394 bc.size = read_buf_size * 1024; 00395 if(ioctl(fd, COMEDI_BUFCONFIG, &bc) < 0) 00396 { 00397 perror(_("buffer resize error")); 00398 exit(1); 00399 } 00400 if(verbose) 00401 { 00402 printf(_("%s read buffer resized to %i kilobytes\n"), 00403 fn, bc.size / 1024); 00404 } 00405 } 00406 } 00407 if(write_buf_size) 00408 { 00409 if(devinfo.write_subdevice < 0){ 00410 fprintf(stderr,_("warning: no write subdevice, resize ignored\n")); 00411 }else{ 00412 memset(&bc, 0, sizeof(bc)); 00413 bc.subdevice = devinfo.write_subdevice; 00414 bc.maximum_size = write_buf_size * 1024; 00415 bc.size = write_buf_size * 1024; 00416 if(ioctl(fd, COMEDI_BUFCONFIG, &bc) < 0) 00417 { 00418 perror(_("buffer resize error")); 00419 exit(1); 00420 } 00421 if(verbose) 00422 { 00423 printf(_("%s write buffer resized to %i kilobytes\n"), 00424 fn, bc.size / 1024); 00425 } 00426 } 00427 } 00428 } 00429 00430 exit(0); 00431 } 00432