extern const char *get_status_string (SANE_Status status) { struct { SANE_Status status; const char *name; } status_names[] = { { SANE_STATUS_GOOD, "SANE_STATUS_GOOD"}, { SANE_STATUS_UNSUPPORTED, "SANE_STATUS_UNSUPPORTED"}, { SANE_STATUS_CANCELLED, "SANE_STATUS_CANCELLED"}, { SANE_STATUS_DEVICE_BUSY, "SANE_STATUS_DEVICE_BUSY"}, { SANE_STATUS_INVAL, "SANE_STATUS_INVAL"}, { SANE_STATUS_EOF, "SANE_STATUS_EOF"}, { SANE_STATUS_JAMMED, "SANE_STATUS_JAMMED"}, { SANE_STATUS_NO_DOCS, "SANE_STATUS_NO_DOCS"}, { SANE_STATUS_COVER_OPEN, "SANE_STATUS_COVER_OPEN"}, { SANE_STATUS_IO_ERROR, "SANE_STATUS_IO_ERROR"}, { SANE_STATUS_NO_MEM, "SANE_STATUS_NO_MEM"}, { SANE_STATUS_ACCESS_DENIED, "SANE_STATUS_ACCESS_DENIED"}, { -1, NULL} }; static char *unknown_string = NULL; int i; for (i = 0; status_names[i].name != NULL && status_names[i].status != status; i++); if (status_names[i].name == NULL) { free (unknown_string); unknown_string = o_strdup(""); o_concatf (&unknown_string, "SANE_ACTION(%d)", status); return unknown_string; /* Note result is undefined on second call to this function */ } return status_names[i].name; }
extern const char *get_action_string (SANE_Action action) { struct { SANE_Action action; const char *name; } action_names[] = { { SANE_ACTION_GET_VALUE, "SANE_ACTION_GET_VALUE" }, { SANE_ACTION_SET_VALUE, "SANE_ACTION_SET_VALUE" }, { SANE_ACTION_SET_AUTO, "SANE_ACTION_SET_AUTO" }, { -1, NULL} }; static char *unknown_string = NULL; int i; for (i = 0; action_names[i].name != NULL && action_names[i].action != action; i++); if (action_names[i].name == NULL) { free (unknown_string); unknown_string = o_strdup(""); o_concatf (&unknown_string, "SANE_ACTION(%d)", action); return unknown_string; /* Note result is undefined on second call to this function */ } return action_names[i].name; }
extern char *internalGetScannerDetails(char *device, char *lang) { char *answer = NULL; SANE_Status status; char *deviceList = o_strdup("");; int hlp = 0, resolution = 300, minRes=50, maxRes=50, phashAvailable=0; char *resolution_s, *maxRes_s, *minRes_s; SANE_Handle *openDeviceHandle; o_log(DEBUGM, "sane_open of \"%s\"", device); status = sane_open (device, (SANE_Handle)&openDeviceHandle); if(status != SANE_STATUS_GOOD) { o_log(ERROR, "Could not open: '%s' with error: %s", device, sane_strstatus(status)); free(deviceList); return NULL; } // // Find resolution ranges // for (hlp = 0; hlp < 9999; hlp++) { const SANE_Option_Descriptor *sod; sod = sane_get_option_descriptor (openDeviceHandle, hlp); if (sod == NULL) break; // Just a placeholder if (sod->type == SANE_TYPE_GROUP || sod->name == NULL || hlp == 0) continue; if ( 0 == strcmp(sod->name, SANE_NAME_SCAN_RESOLUTION) ) { // Some kind of sliding range if (sod->constraint_type == SANE_CONSTRAINT_RANGE) { o_log(DEBUGM, "Resolution setting detected as 'range'"); // Fixed resolution if (sod->type == SANE_TYPE_FIXED) maxRes = (int)SANE_UNFIX (sod->constraint.range->max); else maxRes = sod->constraint.range->max; } // A fixed list of options else if (sod->constraint_type == SANE_CONSTRAINT_WORD_LIST) { int lastIndex = sod->constraint.word_list[0]; o_log(DEBUGM, "Resolution setting detected as 'word list': lastIndex = %d",lastIndex); // maxRes = sod->constraint.word_list[lastIndex]; // resolution list cannot be treated as low to high ordered list // remark: impl capability to select scan resolution in webInterface int n=0; maxRes = 0; for (n=1; n<=lastIndex; n++ ) { o_log(DEBUGM, "index results %d --> %d", n ,(int)sod->constraint.word_list[n]); if ( maxRes < sod->constraint.word_list[n] ) { maxRes=sod->constraint.word_list[n]; } } } break; // we've found our resolution - no need to search more } } o_log(DEBUGM, "Determined max resultion to be %d", maxRes); // Define a default if(resolution >= maxRes) resolution = maxRes; if(resolution <= minRes) resolution = minRes; o_log(DEBUGM, "sane_cancel"); sane_cancel(openDeviceHandle); o_log(DEBUGM, "sane_close"); sane_close(openDeviceHandle); // // What languages can we OCR for? // char *availableLangs = o_strdup(""); #ifdef CAN_OCR struct simpleLinkedList *languages = getOCRAvailableLanguages(); while (languages != NULL ) { if ( checkOCRLanguage( languages->data ) == 0 ) { o_concatf(&availableLangs, "<lang>%s</lang>", languages->data); } languages = sll_getNext(languages); } sll_destroy( languages ); #endif /* CAN_OCR */ // // Can we give the option of doing 'find simmilar'? // #ifdef CAN_PHASH phashAvailable = 1; #endif /* CAN_PHASH */ // Build Reply // resolution_s = itoa(resolution,10); maxRes_s = itoa(maxRes,10); minRes_s = itoa(minRes,10); o_concatf(&deviceList, "<Resolution><max>%s</max><min>%s</min><default>%s</default></Resolution><OCRLanguages>%s</OCRLanguages><phash>%d</phash>", maxRes_s, minRes_s, resolution_s, availableLangs, phashAvailable); free(maxRes_s); free(minRes_s); free(resolution_s); free(availableLangs); // The escaped string placeholder will be interprited in the sane dispatcher client answer = o_printf("<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerDetails>%s</ScannerDetails></Response>", deviceList); free(deviceList); return answer; }
extern void log_option (SANE_Int index, const SANE_Option_Descriptor *option) { char *string; SANE_Word i; SANE_Int cap; string = o_strdup(""); o_concatf (&string, "Option %d:", index); if (option->name) o_concatf (&string, " name='%s'", option->name); if (option->title) o_concatf (&string, " title='%s'", option->title); switch (option->type) { case SANE_TYPE_BOOL: conCat(&string, " type=bool"); break; case SANE_TYPE_INT: conCat(&string, " type=int"); break; case SANE_TYPE_FIXED: conCat(&string, " type=fixed"); break; case SANE_TYPE_STRING: conCat(&string, " type=string"); break; case SANE_TYPE_BUTTON: conCat(&string, " type=button"); break; case SANE_TYPE_GROUP: conCat(&string, " type=group"); break; default: o_concatf (&string, " type=%d", option->type); break; } o_concatf (&string, " size=%d", option->size); switch (option->unit) { case SANE_UNIT_NONE: break; case SANE_UNIT_PIXEL: conCat(&string, " unit=pixels"); break; case SANE_UNIT_BIT: conCat(&string, " unit=bits"); break; case SANE_UNIT_MM: conCat(&string, " unit=mm"); break; case SANE_UNIT_DPI: conCat(&string, " unit=dpi"); break; case SANE_UNIT_PERCENT: conCat(&string, " unit=percent"); break; case SANE_UNIT_MICROSECOND: conCat(&string, " unit=microseconds"); break; default: o_concatf (&string, " unit=%d", option->unit); break; } switch (option->constraint_type) { case SANE_CONSTRAINT_RANGE: if (option->type == SANE_TYPE_FIXED) o_concatf (&string, " min=%f, max=%f, quant=%d", SANE_UNFIX (option->constraint.range->min), SANE_UNFIX (option->constraint.range->max), option->constraint.range->quant); else o_concatf (&string, " min=%d, max=%d, quant=%d", option->constraint.range->min, option->constraint.range->max, option->constraint.range->quant); break; case SANE_CONSTRAINT_WORD_LIST: conCat(&string, " values=["); for (i = 0; i < option->constraint.word_list[0]; i++) { if (i != 0) conCat(&string, ", "); if (option->type == SANE_TYPE_INT) o_concatf (&string, "%d", option->constraint.word_list[i+1]); else o_concatf (&string, "%f", SANE_UNFIX (option->constraint.word_list[i+1])); } conCat(&string, "]"); break; case SANE_CONSTRAINT_STRING_LIST: conCat(&string, " values=["); for (i = 0; option->constraint.string_list[i]; i++) { if (i != 0) conCat(&string, ", "); o_concatf (&string, "\"%s\"", option->constraint.string_list[i]); } conCat(&string, "]"); break; default: break; } cap = option->cap; if (cap) { struct { SANE_Int cap; const char *name; } caps[] = { { SANE_CAP_SOFT_SELECT, "soft-select"}, { SANE_CAP_HARD_SELECT, "hard-select"}, { SANE_CAP_SOFT_DETECT, "soft-detect"}, { SANE_CAP_EMULATED, "emulated"}, { SANE_CAP_AUTOMATIC, "automatic"}, { SANE_CAP_INACTIVE, "inactive"}, { SANE_CAP_ADVANCED, "advanced"}, { 0, NULL} }; int i, n = 0; conCat(&string, " cap="); for (i = 0; caps[i].cap > 0; i++) { if (cap & caps[i].cap) { cap &= ~caps[i].cap; if (n != 0) conCat(&string, ","); conCat(&string, caps[i].name); n++; } } /* Unknown capabilities */ if (cap) { if (n != 0) conCat(&string, ","); o_concatf (&string, "%x", cap); } } o_log(DEBUGM, "%s", string); free(string); // if (option->desc) // o_log(DEBUGM, " Description: %s", option->desc); }
extern char *internalGetScannerList(char *lang) { char *answer = NULL; SANE_Status status; const SANE_Device **SANE_device_list; int scanOK = SANE_FALSE; char *deviceList; status = sane_get_devices (&SANE_device_list, SANE_TRUE); if(status == SANE_STATUS_GOOD) { if (SANE_device_list && SANE_device_list[0]) { scanOK = SANE_TRUE; o_log(DEBUGM, "device(s) found"); } else { o_log(INFORMATION, "No devices found"); } } else { o_log(WARNING, "Checking for devices failed"); } if(scanOK == SANE_TRUE) { int i = 0; char *replyTemplate; replyTemplate = o_strdup("<Device><vendor>%s</vendor><model>%s</model><type>%s</type><name>%s</name><host>%s</host></Device>"); deviceList = o_strdup(""); for (i=0 ; SANE_device_list[i] ; i++) { char *vendor, *model, *type, *name; char *scannerHost; vendor = o_strdup(SANE_device_list[i]->vendor); model = o_strdup(SANE_device_list[i]->model); type = o_strdup(SANE_device_list[i]->type); name = o_strdup(SANE_device_list[i]->name); propper(vendor); propper(model); propper(type); // Find location of the device if ( name && name == strstr(name, "net:") ) { struct sockaddr_in sa; char *ipandmore, *ip; char host[NI_MAXHOST]; char service[NI_MAXSERV]; int len; // Ignore the 'net:' part ipandmore = name + 4; // Find the length of the address part len = strstr(ipandmore, ":") - ipandmore; // Load 'ip' with the network addres ip = malloc(1+(size_t)len); (void) strncpy(ip,ipandmore,(size_t)len); ip[len] = '\0'; // Convert into an inet address memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr( ip ); // Lookup hostname from address o_log(DEBUGM, "Going to lookup: %s", ip); if ( getnameinfo((struct sockaddr *)&sa, sizeof sa, host, sizeof host, service, sizeof service, NI_NAMEREQD) == 0 ) { o_log(DEBUGM, "found host: %s", host); scannerHost = o_strdup(host); } else { o_log(DEBUGM, "Could not get hostname"); scannerHost = o_strdup(ip); } // Clean up free(ip); } else { scannerHost = o_strdup( getString("LOCAL_opendias_server", lang) ); } // Build Reply // o_concatf(&deviceList, replyTemplate, vendor, model, type, name, scannerHost); free(vendor); free(model); free(type); free(name); free(scannerHost); } free(replyTemplate); if(deviceList) { // The escaped string placeholder will be interprited in the sane dispatcher client answer = o_printf("<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerList%%s><Devices>%s</Devices></ScannerList></Response>", deviceList); free(deviceList); } else { // No devices // The escaped string placeholder will be interprited in the sane dispatcher client answer = o_strdup( "<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerList%s></ScannerList></Response>"); } } else { // sane failed. // The escaped string placeholder will be interprited in the sane dispatcher client answer = o_strdup( "<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerList%s></ScannerList></Response>"); } return answer; }