change bufconfig version test from 0.7.56 to 0.7.57
[comedilib.git] / comedi_config / comedi_config.c
1 /*
2     comedi_config/comedi_config.c
3     configuration program for comedi kernel module
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1998,2000 David A. Schleef <ds@stm.lbl.gov>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program 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
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #define CC_VERSION      "0.7.13"
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/sysmacros.h>
29 #include <fcntl.h>
30 #include <sys/ioctl.h>
31 #include <stdio.h>
32 #include <getopt.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <getopt.h>
38
39 #include <comedi.h>
40
41 int quiet=0,verbose=0;
42
43 int read_buf_size=0;
44 int write_buf_size=0;
45
46 int init_fd;
47 char *init_file;
48 void *init_data;
49 int init_size;
50
51 struct option options[] = {
52         { "verbose", 0, 0, 'v' },
53         { "quiet", 0, 0, 'q' },
54         { "version", 0, 0, 'V' },
55         { "init-data", 1, 0, 'i' },
56         { "remove", 0, 0, 'r' },
57         { "read-buffer", 1, NULL, 0x1000},
58         { "write-buffer", 1, NULL, 0x1001},
59 };
60
61 void do_help(int i)
62 {
63         fputs(
64                 "comedi_config version " CC_VERSION "\n"
65                 "usage:  comedi_config [OPTIONS] <device file> [<driver> <opt1>,<opt2>,...]\n"
66                 "\n"
67                 "OPTIONS:\n"
68                 "\t-v --verbose\n"
69                         "\t\tverbose output\n"
70                 "\t-q --quiet\n"
71                         "\t\tquiet output\n"
72                 "\t-V --version\n"
73                         "\t\tprint program version\n"
74                 "\t-i --init-data <filename>\n"
75                         "\t\tI don't know what this does\n"
76                 "\t-r --remove\n"
77                         "\t\tremove previously configured driver\n"
78                 "\t--read-buffer <size>\n"
79                         "\t\tset buffer size in kilobytes used for reads from the <device file>\n"
80                 "\t--write-buffer <size>\n"
81                         "\t\tset buffer size in kilobytes used for writes to the <device file>\n"
82                 "\n"
83                 "<optN> are integers whose interpretation depends on\n"
84                 "the driver.  In general, however, for non-plug-and-play boards\n"
85                 "opt1 refers to the I/O port address and opt2 refers to IRQ number\n"
86                 "to be used by the driver.  For plug-and-play boards, opt1 and opt2\n"
87                 "are optional and allow you to specify the bus and slot of the card\n"
88                 "(in case you have two identical cards).\n"
89                 ,stderr);
90         exit(i);
91 }
92
93 int main(int argc,char *argv[])
94 {
95         comedi_devconfig it;
96         comedi_bufconfig bc;
97         comedi_devinfo devinfo;
98         int fd;
99         int c,i,num,k;
100         char *opts;
101         char *fn,*driver;
102         struct stat statbuf;
103         int ret;
104         int remove=0;
105         int index;
106
107         if(getuid() != 0)
108         {
109                 errno = EPERM;
110                 perror(argv[0]);
111                 exit(1);
112         }
113
114         while(1){
115                 c=getopt_long(argc, argv, "rvVqi:", options, &index);
116                 if(c==-1)break;
117                 switch(c){
118                 case 'v':
119                         verbose=1;
120                         break;
121                 case 'V':
122                         fputs("comedi_config version " CC_VERSION "\n",stderr);
123                         exit(0);
124                         break;
125                 case 'q':
126                         quiet=1;
127                         break;
128                 case 'r':
129                         remove=1;
130                         break;
131                 case 'i':
132                         init_file=optarg;
133                         break;
134                 case 0x1000:
135                         read_buf_size = strtol(optarg, NULL, 0);
136                         if(read_buf_size < 0)
137                         {
138                                 fprintf(stderr, "invalid buffer size\n");
139                                 exit(-1);
140                         }
141                         break;
142                 case 0x1001:
143                         write_buf_size = strtol(optarg, NULL, 0);
144                         if(write_buf_size < 0)
145                         {
146                                 fprintf(stderr, "invalid buffer size\n");
147                                 exit(-1);
148                         }
149                         break;
150                 default:
151                         do_help(1);
152                 }
153         }
154
155         if((argc-optind) < 1 || (argc-optind) > 3 ||
156                 ((argc-optind) == 1 && read_buf_size == 0 && write_buf_size == 0 && remove == 0)){
157                 do_help(1);
158         }
159
160         fn=argv[optind];
161
162         fd=open(fn,O_RDWR);
163         if(fd<0){
164                 switch(errno){
165                 case ENODEV:
166                         fprintf(stderr,"comedi.o not loaded\n");
167                         break;
168                 default:
169                         perror(fn);
170                         break;
171                 }
172                 exit(1);
173         }
174
175         // if we are attaching or detaching a device
176         if((argc-optind) > 1 || ((argc-optind) == 1 && remove))
177         {
178                 if(argc - optind > 1)
179                         driver=argv[optind+1];
180                 else
181                         driver = "none";
182                 strncpy(it.board_name,driver,COMEDI_NAMELEN-1);
183
184                 for(i=0;i<COMEDI_NDEVCONFOPTS;i++)it.options[i]=0;
185
186                 if((argc-optind)==3){
187                         opts=argv[optind+2];
188                         i=0;
189                         while(*opts){
190                                 if((*opts)==','){
191                                         i++;
192                                         opts++;
193                                         if(i>=COMEDI_NDEVCONFOPTS)
194                                                 do_help(1);
195                                         continue;
196                                 }
197                                 if(sscanf(opts,"%i%n",&num,&k)>0){
198                                         it.options[i]=num;
199                                         opts+=k;
200                                         continue;
201                                 }
202                                 do_help(1);
203                         }
204                 }
205
206                 ret=stat(fn,&statbuf);
207                 if(ret<0){
208                         perror(fn);
209                         exit(1);
210                 }
211 #if 0
212                 /* this appears to be broken */
213                 if(  !(S_ISCHR(statbuf.st_mode)) ||
214                      major(statbuf.st_dev)!=COMEDI_MAJOR){
215                         if(!quiet)
216                                 fprintf(stderr,"warning: %s might not be a comedi device\n",fn);
217                 }
218 #endif
219
220                 if(init_file){
221                         struct stat buf;
222
223                         init_fd = open(init_file,O_RDONLY);
224                         if(init_fd<0){
225                                 perror(init_file);
226                                 exit(1);
227                         }
228
229                         fstat(init_fd,&buf);
230
231                         init_size = buf.st_size;
232                         init_data = malloc(init_size);
233                         if(init_data==NULL){
234                                 perror("allocating initialization data\n");
235                                 exit(1);
236                         }
237
238                         ret = read(init_fd,init_data,init_size);
239                         if(ret<0){
240                                 perror("reading initialization data\n");
241                                 exit(1);
242                         }
243
244                         it.options[0]=(int)init_data;
245                         it.options[1]=init_size;
246                 }
247
248         /* add: sanity check for device */
249
250                 if(verbose){
251                         printf("configuring driver=%s ",it.board_name);
252                         for(i=0;i<COMEDI_NDEVCONFOPTS;i++)printf("%d,",it.options[i]);
253                         printf("\n");
254                 }
255                 if(ioctl(fd,COMEDI_DEVCONFIG,remove?NULL:&it)<0){
256                         int err=errno;
257                         perror("Configure failed!");
258                         fprintf(stderr,"Check kernel log for more information\n");
259                         fprintf(stderr,"Possible reasons for failure:\n");
260                         switch(err){
261                         case EINVAL:
262                                 fprintf(stderr,"  \n");
263                                 break;
264                         case EBUSY:
265                                 fprintf(stderr,"  Already configured\n");
266                                 break;
267                         case EIO:
268                                 fprintf(stderr,"  Driver not found\n");
269                                 break;
270                         case EPERM:
271                                 fprintf(stderr,"  Not root\n");
272                                 break;
273                         case EFAULT:
274                                 fprintf(stderr,"  Comedi bug\n");
275                                 break;
276                         default:
277                                 fprintf(stderr,"  Unknown\n");
278                                 break;
279                         }
280
281                         exit(1);
282                 }
283         }
284
285         if(read_buf_size || write_buf_size){
286                 ret = ioctl(fd,COMEDI_DEVINFO,&devinfo);
287                 if(ret<0){
288                         perror("devinfo");
289                         exit(1);
290                 }
291                 if(devinfo.version_code < ((7<<8) | (57))){
292                         fprintf(stderr,"Buffer resizing requires Comedi version >= 0.7.57\n");
293                         exit(1);
294                 }
295         }
296
297         // do buffer resizing
298         if(read_buf_size)
299         {
300                 if(devinfo.read_subdevice){
301                         fprintf(stderr,"warning: no read subdevice, resize ignored\n");
302                 }else{
303                         memset(&bc, 0, sizeof(bc));
304                         bc.subdevice = devinfo.read_subdevice;
305                         bc.maximum_size = read_buf_size * 1024;
306                         bc.size = read_buf_size * 1024;
307                         if(ioctl(fd, COMEDI_BUFCONFIG, &bc) < 0)
308                         {
309                                 perror("buffer resize error");
310                                 exit(1);
311                         }
312                         if(verbose)
313                         {
314                                 printf("%s read buffer resized to %i kilobytes\n",
315                                         fn, bc.size / 1024);
316                         }
317                 }
318         }
319         if(write_buf_size)
320         {
321                 if(devinfo.write_subdevice){
322                         fprintf(stderr,"warning: no write subdevice, resize ignored\n");
323                 }else{
324                         memset(&bc, 0, sizeof(bc));
325                         bc.subdevice = devinfo.write_subdevice;
326                         bc.maximum_size = write_buf_size * 1024;
327                         bc.size = write_buf_size * 1024;
328                         if(ioctl(fd, COMEDI_BUFCONFIG, &bc) < 0)
329                         {
330                                 perror("buffer resize error");
331                                 exit(1);
332                         }
333                         if(verbose)
334                         {
335                                 printf("%s write buffer resized to %i kilobytes\n",
336                                         fn, bc.size / 1024);
337                         }
338                 }
339         }
340
341         exit(0);
342 }
343