File indexing completed on 2024-09-08 12:28:31
0001 /************************************************************************/ 0002 /* */ 0003 /* This file is part of the KDE Project */ 0004 /* Copyright (c) 2004 Jonathan Marten <jjm@keelhaul.me.uk> */ 0005 /* */ 0006 /* This program is free software; you can redistribute it and/or */ 0007 /* modify it under the terms of the GNU General Public License as */ 0008 /* published by the Free Software Foundation; either version 2 of */ 0009 /* the License, or (at your option) any later version. */ 0010 /* */ 0011 /* It is distributed in the hope that it will be useful, but */ 0012 /* WITHOUT ANY WARRANTY; without even the implied warranty of */ 0013 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 0014 /* GNU General Public License for more details. */ 0015 /* */ 0016 /* You should have received a copy of the GNU General Public */ 0017 /* License along with this program; see the file COPYING for further */ 0018 /* details. If not, write to the Free Software Foundation, Inc., */ 0019 /* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 0020 /* */ 0021 /************************************************************************/ 0022 0023 0024 /************************************************************************/ 0025 /* Include files */ 0026 /************************************************************************/ 0027 0028 #include <stdio.h> /* Standard I/O library */ 0029 #include <unistd.h> /* Unix(TM) system routines */ 0030 #include <string.h> /* String handling routines */ 0031 #include <stdarg.h> /* Variable parameter handling */ 0032 #include <errno.h> /* Library error numbers */ 0033 #include <stdlib.h> /* Standard library routines */ 0034 0035 #include <sane/sane.h> /* SANE scanner access */ 0036 0037 /************************************************************************/ 0038 /* Global variables */ 0039 /************************************************************************/ 0040 0041 const char *myname; /* my program name */ 0042 0043 static int listmode = 0; /* option 'L' -> probe and list */ 0044 static char devname[256] = ""; /* option 'd' -> device name */ 0045 static int longdesc = 0; /* option 'l' -> long descriptions */ 0046 static int advopt = 0; /* option 'a' -> advanced options */ 0047 0048 SANE_Status sanerr; /* SANE error status */ 0049 0050 static const char *fmt = "%-14s "; /* format for output */ 0051 0052 /************************************************************************/ 0053 /* Message keys for cmderr() - sync with 'errstrings' */ 0054 /************************************************************************/ 0055 0056 enum cemsg 0057 { 0058 CEERROR = 0, /* exit */ 0059 CENONE = 1, /* benign */ 0060 CEWARNING = 2, /* continue */ 0061 CENOTICE = 3, /* continue */ 0062 CEINFO = 4, /* continue */ 0063 CESUCCESS = 5, /* continue */ 0064 CEFATAL = 6, /* exit */ 0065 CEUNKNOWN = 7 /* must be last */ 0066 }; 0067 0068 /************************************************************************/ 0069 /* Error source keys for cmderr() */ 0070 /************************************************************************/ 0071 0072 enum cesys 0073 { 0074 CSNONE = 0, /* no message */ 0075 CSERRNO = 1, /* decode 'errno' */ 0076 CSSANE = 2 /* decode SANE status */ 0077 }; 0078 0079 /************************************************************************/ 0080 /* Severity strings for cmderr() reports */ 0081 /************************************************************************/ 0082 0083 static const char *errstrings[] = 0084 { 0085 "ERROR", /* 0 */ 0086 NULL, /* 1 */ 0087 "WARNING", /* 2 */ 0088 "NOTICE", /* 3 */ 0089 "INFO", /* 4 */ 0090 "SUCCESS", /* 5 */ 0091 "FATAL", /* 6 */ 0092 NULL /* 7 */ 0093 }; 0094 0095 /************************************************************************/ 0096 /* cmderr -- Display an error message with parameters, optionally */ 0097 /* adding the system or SANE error as well. */ 0098 /************************************************************************/ 0099 0100 void 0101 #if defined(__GNUC__) 0102 __attribute__((format (printf,3,4))) 0103 #endif 0104 cmderr(enum cesys src,enum cemsg sev,const char *fmtstr,...) 0105 { 0106 va_list args; /* parameters for format */ 0107 const char *ss; /* severity string */ 0108 const char *mm = NULL; /* textual error message*/ 0109 0110 if (src==CSERRNO) mm = strerror(errno); /* system error message */ 0111 else if (src==CSSANE) mm = sane_strstatus(sanerr); /* SANE error message */ 0112 0113 fflush(stdout); fflush(stderr); /* flush current output */ 0114 /* catch bad parameter */ 0115 if (((int) sev)<0 || sev>CEUNKNOWN) sev = CEUNKNOWN; 0116 ss = errstrings[sev]; 0117 0118 fprintf(stderr,"%s",myname); /* report our program name */ 0119 if (ss!=NULL) fprintf(stderr," (%s)",ss); /* report severity if there is one */ 0120 fprintf(stderr,": "); 0121 0122 va_start(args,fmtstr); /* locate variable parameters */ 0123 vfprintf(stderr,fmtstr,args); /* user message and parameters */ 0124 if (mm!=NULL) fprintf(stderr,", %s",mm); /* system error message */ 0125 va_end(args); /* finished with parameters */ 0126 fprintf(stderr,"\n"); /* end of message */ 0127 /* exit from application */ 0128 if (sev==CEERROR || sev==CEFATAL) exit(EXIT_FAILURE); 0129 } 0130 0131 /************************************************************************/ 0132 /* usage -- Display the command line and option help. */ 0133 /************************************************************************/ 0134 0135 void usage() 0136 { 0137 fprintf(stderr,"Usage: %s -L probe and list scanner devices\n",myname); 0138 fprintf(stderr," %s [-la] [-d] device display information for scanner device\n",myname); 0139 fprintf(stderr,"\n"); 0140 fprintf(stderr,"Options: -d specify SANE device (backend) name\n"); 0141 fprintf(stderr," -l display long SANE option description\n"); 0142 fprintf(stderr," -a display advanced SANE options\n"); 0143 exit(2); 0144 } 0145 0146 /************************************************************************/ 0147 /* do_init - Initialise SANE and report its version. */ 0148 /************************************************************************/ 0149 0150 void do_init() 0151 { 0152 SANE_Int sanevers; 0153 0154 sanerr = sane_init(&sanevers,NULL); 0155 if (sanerr!=SANE_STATUS_GOOD) cmderr(CSSANE,CEFATAL,"cannot initialise SANE"); 0156 printf(fmt,"SANE version:"); 0157 printf("%d.%d.%d\n",SANE_VERSION_MAJOR(sanevers), 0158 SANE_VERSION_MINOR(sanevers),SANE_VERSION_BUILD(sanevers)); 0159 } 0160 0161 /************************************************************************/ 0162 /* do_listmode -- List all SANE devices known. */ 0163 /************************************************************************/ 0164 0165 void do_listmode() 0166 { 0167 const SANE_Device **devlist; 0168 const SANE_Device *dev; 0169 int i; 0170 0171 do_init(); 0172 0173 sanerr = sane_get_devices(&devlist,SANE_FALSE); /* local and network */ 0174 if (sanerr!=SANE_STATUS_GOOD) cmderr(CSSANE,CEFATAL,"SANE cannot get device list"); 0175 0176 printf("\n"); 0177 for (i = 0; devlist[i]!=NULL; ++i) 0178 { 0179 dev = devlist[i]; 0180 0181 printf(fmt,"Device:",dev->name); 0182 printf(fmt,"Vendor:",dev->vendor); 0183 printf(fmt,"Model:",dev->model); 0184 printf(fmt,"Type:",dev->type); 0185 printf("\n"); 0186 } 0187 0188 if (i==0) 0189 { 0190 cmderr(CSNONE,CENOTICE,"No devices found"); 0191 cmderr(CSNONE,CEINFO,"Try sane-find-scanner(1), or hp-probe(1) for HP devices"); 0192 } 0193 } 0194 0195 /************************************************************************/ 0196 /* do_describe -- Given a SANE device, decode and display all of its */ 0197 /* option descriptors. */ 0198 /************************************************************************/ 0199 0200 void do_describe(const char *dev) 0201 { 0202 SANE_Handle hand; 0203 const SANE_Option_Descriptor *desc; 0204 SANE_Int numopt; 0205 int opt; 0206 double min,max,q; 0207 const SANE_String_Const *sp; 0208 const SANE_Word *wp; 0209 int nw; 0210 int i; 0211 0212 0213 do_init(); 0214 0215 sanerr = sane_open(dev,&hand); 0216 if (sanerr!=SANE_STATUS_GOOD) cmderr(CSSANE,CEFATAL,"SANE cannot open '%s'",dev); 0217 0218 /* get option index 0 = number of options */ 0219 sanerr = sane_control_option(hand,0,SANE_ACTION_GET_VALUE,&numopt,NULL); 0220 if (sanerr!=SANE_STATUS_GOOD) cmderr(CSSANE,CEFATAL,"SANE cannot get option 0"); 0221 0222 printf(fmt,"Found:"); 0223 printf("%d options\n",numopt); 0224 0225 for (opt = 1; opt<numopt; ++opt) 0226 { 0227 desc = sane_get_option_descriptor(hand,opt); 0228 if (desc==NULL) 0229 { 0230 cmderr(CSNONE,CEWARNING,"SANE option %d is not valid",opt); 0231 continue; 0232 } 0233 0234 if (!advopt && (desc->cap & SANE_CAP_ADVANCED)) continue; 0235 0236 printf("\n"); 0237 printf(fmt,"Option:"); 0238 printf("%d\n",opt); 0239 0240 if (desc->name!=NULL && desc->name[0]!='\0') 0241 { 0242 printf(fmt,"Name:"); 0243 printf("%s\n",desc->name); 0244 } 0245 0246 if (desc->title!=NULL) 0247 { 0248 printf(fmt,"Title:"); 0249 printf("\"%s\"\n",desc->title); 0250 } 0251 0252 if (desc->desc!=NULL && desc->desc[0]!='\0' && longdesc) 0253 { 0254 printf(fmt,"Description:"); 0255 printf("\"%s\"\n",desc->desc); 0256 } 0257 0258 printf(fmt,"Value type:"); 0259 switch (desc->type) 0260 { 0261 case SANE_TYPE_BOOL: printf("BOOL"); break; 0262 case SANE_TYPE_INT: printf("INT"); break; 0263 case SANE_TYPE_FIXED: printf("FIXED"); break; 0264 case SANE_TYPE_STRING: printf("STRING"); break; 0265 case SANE_TYPE_BUTTON: printf("BUTTON"); break; 0266 case SANE_TYPE_GROUP: printf("GROUP"); break; 0267 default: printf("%d",desc->type); break; 0268 } 0269 printf("\n"); 0270 0271 if (desc->unit!=SANE_UNIT_NONE) 0272 { 0273 printf(fmt,"Unit:"); 0274 switch (desc->unit) 0275 { 0276 case SANE_UNIT_NONE: printf("NONE"); break; 0277 case SANE_UNIT_PIXEL: printf("PIXELS"); break; 0278 case SANE_UNIT_BIT: printf("BITS"); break; 0279 case SANE_UNIT_MM: printf("MM"); break; 0280 case SANE_UNIT_DPI: printf("DPI"); break; 0281 case SANE_UNIT_PERCENT: printf("PERCENT"); break; 0282 case SANE_UNIT_MICROSECOND: printf("MICROSECOND"); break; 0283 default: printf("%d",desc->unit); break; 0284 } 0285 printf("\n"); 0286 } 0287 0288 if (desc->cap!=0) 0289 { 0290 printf(fmt,"Capabilities:"); 0291 if (desc->cap & SANE_CAP_SOFT_SELECT) printf("SOFT_SELECT "); 0292 if (desc->cap & SANE_CAP_HARD_SELECT) printf("HARD_SELECT "); 0293 if (desc->cap & SANE_CAP_SOFT_DETECT) printf("SOFT_DETECT "); 0294 if (desc->cap & SANE_CAP_EMULATED) printf("EMULATED "); 0295 if (desc->cap & SANE_CAP_AUTOMATIC) printf("AUTOMATIC "); 0296 if (desc->cap & SANE_CAP_INACTIVE) printf("INACTIVE "); 0297 if (desc->cap & SANE_CAP_ADVANCED) printf("ADVANCED "); 0298 #ifdef SANE_CAP_ALWAYS_SETTABLE 0299 if (desc->cap & SANE_CAP_ALWAYS_SETTABLE) printf("ALWAYS_SETTABLE "); 0300 #endif 0301 printf("\n"); 0302 } 0303 0304 if (desc->constraint_type!=SANE_CONSTRAINT_NONE) 0305 { 0306 printf(fmt,"Constraint:"); 0307 switch (desc->constraint_type) 0308 { 0309 case SANE_CONSTRAINT_NONE: printf("NONE"); 0310 break; 0311 0312 case SANE_CONSTRAINT_RANGE: switch (desc->type) 0313 { 0314 case SANE_TYPE_INT: min = desc->constraint.range->min; 0315 max = desc->constraint.range->max; 0316 q = desc->constraint.range->quant; 0317 break; 0318 0319 case SANE_TYPE_FIXED: min = SANE_UNFIX(desc->constraint.range->min); 0320 max = SANE_UNFIX(desc->constraint.range->max); 0321 q = SANE_UNFIX(desc->constraint.range->quant); 0322 break; 0323 0324 default: min = max = q = 0; 0325 break; 0326 } 0327 0328 if (q==0) q = 1.0; 0329 if (q==1.0) 0330 { 0331 printf("RANGE %g - %g",min,max); 0332 } 0333 else 0334 { 0335 printf("RANGE %g - %g by %g = %g - %g", 0336 min,max,q,min/q,max/q); 0337 } 0338 break; 0339 0340 case SANE_CONSTRAINT_STRING_LIST: 0341 printf("STRING_LIST ["); 0342 for (sp = desc->constraint.string_list; *sp!=NULL; ++sp) 0343 { 0344 printf("\"%s\"",*sp); 0345 if (sp[1]!=NULL) printf(" "); 0346 } 0347 printf("]"); 0348 break; 0349 0350 case SANE_CONSTRAINT_WORD_LIST: 0351 printf("WORD_LIST "); 0352 wp = desc->constraint.word_list; 0353 nw = *wp++; 0354 printf("%d [",nw); 0355 for (i = 0; i<nw; ++i) 0356 { 0357 if (desc->type==SANE_TYPE_FIXED) printf("%g",SANE_UNFIX(*wp)); 0358 else printf("%d",*wp); 0359 ++wp; 0360 if ((i+1)!=nw) printf(" "); 0361 } 0362 printf("]"); 0363 break; 0364 0365 default: printf("%d",desc->constraint_type); 0366 break; 0367 } 0368 0369 printf("\n"); 0370 } 0371 0372 if (desc->size>0 && desc->size!=sizeof(SANE_Word)) 0373 { 0374 printf(fmt,"Data size:"); 0375 printf("%d\n",desc->size); 0376 } 0377 } 0378 0379 printf("\n"); 0380 sane_close(hand); 0381 sane_exit(); 0382 } 0383 0384 /************************************************************************/ 0385 /* Main -- Handle command line and options */ 0386 /************************************************************************/ 0387 0388 int main(int argc, char **argv) 0389 { 0390 int opt; 0391 int i; 0392 0393 myname = strrchr(argv[0],'/'); /* extract our program name */ 0394 if (myname==NULL) myname = argv[0]; 0395 else ++myname; 0396 0397 while ((opt = getopt(argc,argv,":halLd:"))!=-1) 0398 { 0399 switch (opt) 0400 { 0401 case 'L': listmode = 1; /* probe and list devices */ 0402 break; 0403 0404 case 'd': strcpy(devname,optarg); /* specify device name */ 0405 break; 0406 0407 case 'l': longdesc = 1; /* show long descriptions */ 0408 break; 0409 0410 case 'a': advopt = 1; /* show advanced options */ 0411 break; 0412 0413 case 'h': usage(); /* display help */ 0414 break; 0415 0416 default: 0417 case '?': cmderr(CSNONE,CEERROR,"Unrecognised option '%c' (use '-h' for help)",optopt); 0418 break; 0419 0420 case ':': cmderr(CSNONE,CEERROR,"Option '%c' requires an argument (use '-h' for help)",optopt); 0421 break; 0422 } 0423 } 0424 0425 argc -= optind; /* adjust for parsed options */ 0426 argv += optind; 0427 0428 if (listmode) 0429 { 0430 if (longdesc || advopt) cmderr(CSNONE,CEWARNING,"Options '-l'/-a' igored in listing mode ('-L')"); 0431 } 0432 0433 if (devname[0]=='\0') 0434 { 0435 if (!listmode) 0436 { 0437 if (argc==0) cmderr(CSNONE,CEERROR,"No options or devices specified (use '-h' for help)"); 0438 for (i = 0; argv[i]!=NULL; ++i) do_describe(argv[i]); 0439 } 0440 else 0441 { 0442 if (argc>0) cmderr(CSNONE,CEWARNING,"Arguments ignored for listing mode ('-L')"); 0443 do_listmode(); 0444 } 0445 } 0446 else 0447 { 0448 if (listmode) cmderr(CSNONE,CEERROR,"Only one of the '-d'/'-L' options may be specified"); 0449 if (argc>0) cmderr(CSNONE,CEWARNING,"Additional arguments with '-d' ignored"); 0450 do_describe(devname); 0451 } 0452 0453 return (EXIT_SUCCESS); 0454 }