RTXI 1.3
comedilib/comedi_config/comedi_config.c
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines