static SANE_Status u12if_getCaps( U12_Device *dev ) { int cntr; int res_x = 600 ; /*dev->caps.OpticDpi.x */ DBG( _DBG_INFO, "u12if_getCaps()\n" ); /* FIXME: set dpi_range.max, max_x & max_y on a per model base */ dev->dpi_max_x = 600; dev->dpi_max_y = 1200; /* A4 devices */ dev->max_x = 8.5 * (double)_MM_PER_INCH; dev->max_y = 11.6934 * (double)_MM_PER_INCH; /* limit the range */ dev->dpi_range.min = _DEF_DPI; dev->dpi_range.max = dev->dpi_max_y; dev->dpi_range.quant = 0; dev->x_range.min = 0; dev->x_range.max = SANE_FIX(dev->max_x); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX(dev->max_y); dev->y_range.quant = 0; /* calculate the size of the resolution list + * one more to avoid a buffer overflow, then allocate it... */ dev->res_list = (SANE_Int *) calloc((((res_x * 16)-_DEF_DPI)/25+1), sizeof (SANE_Int)); if (NULL == dev->res_list) { DBG( _DBG_ERROR, "alloc fail, resolution problem\n" ); u12if_close(dev); return SANE_STATUS_INVAL; } /* build up the resolution table */ dev->res_list_size = 0; for( cntr = _DEF_DPI; cntr <= (res_x*16); cntr += 25 ) { dev->res_list_size++; dev->res_list[dev->res_list_size - 1] = (SANE_Int)cntr; } return SANE_STATUS_GOOD; }
static TW_UINT16 set_one_coord(const char *name, double coord) { SANE_Status status; status = sane_option_set_fixed(activeDS.deviceHandle, name, SANE_FIX(coord), NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); return TWCC_SUCCESS; }
/* * options */ static void st400_reset_options( ST400_Device *dev ) { DBG(DCODE, "st400_reset_options(%p)\n", (void *) dev); dev->val[OPT_NUM_OPTS] = NUM_OPTIONS; dev->val[OPT_RESOLUTION] = dev->opt[OPT_RESOLUTION].constraint.word_list[1]; dev->val[OPT_DEPTH] = dev->opt[OPT_DEPTH].constraint.word_list[1]; dev->val[OPT_THRESHOLD] = SANE_FIX(50.0); dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->val[OPT_TL_X] = SANE_FIX(0.0); dev->val[OPT_TL_Y] = SANE_FIX(0.0); dev->val[OPT_BR_X] = SANE_FIX(0.0); dev->val[OPT_BR_Y] = SANE_FIX(0.0); if( dev->model->dpi_list ) dev->opt[OPT_RESOLUTION].constraint.word_list = dev->model->dpi_list; }
scan_area_t model_info_max_scan_area(const void *self, const char *option, const char *mode) { _model_info_t *self_ = NULL; scan_area_t scan_area; require (self); require (option); scan_area.width = SANE_FIX(-1); scan_area.height = SANE_FIX(-1); self_ = (_model_info_t *) self; if(strcmp(option, "adf") == 0 && strcmp_c(mode, "duplex") == 0){ if(self_->adf_duplex){ scan_area.width = SANE_FIX (self_->adf_duplex->width * MM_PER_INCH / self_->adf_duplex->base); scan_area.height = SANE_FIX (self_->adf_duplex->height * MM_PER_INCH / self_->adf_duplex->base); } }else { if(self_->dfault){ scan_area.width = SANE_FIX (self_->dfault->width * MM_PER_INCH / self_->dfault->base); scan_area.height = SANE_FIX (self_->dfault->height * MM_PER_INCH / self_->dfault->base); } } return scan_area; }
static void reset_options(struct device *dev) { dev->val[OPT_RESOLUTION].w = 150; dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR); /* if docs loaded in adf use it as default source, flatbed oterwise */ dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]); dev->val[OPT_THRESHOLD].w = SANE_FIX(50); /* this is reported maximum window size, will be fixed later */ dev->win_x_range.min = SANE_FIX(0); dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM); dev->win_x_range.quant = SANE_FIX(1); dev->win_y_range.min = SANE_FIX(0); dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM); dev->win_y_range.quant = SANE_FIX(1); dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min; dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min; dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max; dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max; }
* distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdlib.h> #include <string.h> #include "sanemock.h" static SANE_Device **sane_device_list = NULL; static SANE_Virtual_Device *first_virtual_device = NULL; static SANE_String_Const string_list[] = { SANE_I18N("First String Option"), SANE_I18N("Second String Option"), 0 }; static SANE_Int word_list_int[] = { 10, 20, 30 }; static SANE_Int word_list_fixed[] = { SANE_FIX(25.4), SANE_FIX(30.2) }; static SANE_Range range = { SANE_FIX(10.0), SANE_FIX(100.0), SANE_FIX(5.0) }; SANE_Bool is_initialized = SANE_FALSE; SANE_Status sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize) { if (is_initialized) { return SANE_STATUS_INVAL; } SANE_Device *sane_device = NULL; SANE_Virtual_Device* virtual_device = NULL; SANE_Virtual_Device* previous_virtual_device = NULL; *version_code = SANE_VERSION_CODE(MAJOR, MINOR, BUILD); sane_device_list = malloc((DEVICE_COUNT + 1) * sizeof(sane_device)); SANE_Int i; for (i = 0; i < DEVICE_COUNT; i++) {
#include "leo.h" /*--------------------------------------------------------------------------*/ /* Lists of possible scan modes. */ static SANE_String_Const scan_mode_list[] = { BLACK_WHITE_STR, GRAY_STR, COLOR_STR, NULL }; /*--------------------------------------------------------------------------*/ /* Minimum and maximum width and length supported. */ static SANE_Range x_range = { SANE_FIX (0), SANE_FIX (8.5 * MM_PER_INCH), 0 }; static SANE_Range y_range = { SANE_FIX (0), SANE_FIX (11.5 * MM_PER_INCH), 0 }; /*--------------------------------------------------------------------------*/ static const SANE_Range gamma_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /*--------------------------------------------------------------------------*/ static SANE_String_Const halftone_pattern_list[] = { SANE_I18N ("None"),
static PyObject * SaneDev_set_option(SaneDevObject *self, PyObject *args) { SANE_Status st; const SANE_Option_Descriptor *d; SANE_Int i; PyObject *value; int n; void *v; if (!PyArg_ParseTuple(args, "iO", &n, &value)) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } d=sane_get_option_descriptor(self->h, n); v=malloc(d->size+1); switch(d->type) { case(SANE_TYPE_BOOL): if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_BOOL requires an integer"); free(v); return NULL; } /* fall through */ case(SANE_TYPE_INT): if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_INT requires an integer"); free(v); return NULL; } *( (SANE_Int*)v) = PyInt_AsLong(value); break; case(SANE_TYPE_FIXED): if (!PyFloat_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_FIXED requires a floating point number"); free(v); return NULL; } *( (SANE_Fixed*)v) = SANE_FIX(PyFloat_AsDouble(value)); break; case(SANE_TYPE_STRING): if (!PyString_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_STRING requires a string"); free(v); return NULL; } strncpy(v, PyString_AsString(value), d->size-1); ((char*)v)[d->size-1] = 0; break; case(SANE_TYPE_BUTTON): case(SANE_TYPE_GROUP): break; } st=sane_control_option(self->h, n, SANE_ACTION_SET_VALUE, v, &i); if (st) {free(v); return PySane_Error(st);} free(v); return Py_BuildValue("i", i); }
/* called after option changed and in set_window */ static int fix_window(struct device *dev) { double win_width_mm, win_len_mm; int i; int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w); dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w); dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)]; if (dev->composition == MODE_LINEART || dev->composition == MODE_HALFTONE) { dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; } if (threshold < 30) { dev->val[OPT_THRESHOLD].w = SANE_FIX(30); } else if (threshold > 70) { dev->val[OPT_THRESHOLD].w = SANE_FIX(70); } threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w); dev->threshold = (threshold - 30) / 10; dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30); dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)]; /* max window len is dependent of document source */ if (dev->doc_source == DOC_FLATBED || (dev->doc_source == DOC_AUTO && !dev->doc_loaded)) dev->max_len = dev->max_len_fb; else dev->max_len = dev->max_len_adf; /* parameters */ dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM); /* window sanity checking */ for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) { if (dev->val[i].w < dev->opt[i].constraint.range->min) dev->val[i].w = dev->opt[i].constraint.range->min; if (dev->val[i].w > dev->opt[i].constraint.range->max) dev->val[i].w = dev->opt[i].constraint.range->max; } if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w) SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w); if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w) SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w); /* recalculate millimeters to inches */ dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH; dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH; /* calc win size in mm */ win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) - SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w); win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) - SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w); /* convert mm to 1200 dpi points */ dev->win_width = (int)(win_width_mm * PNT_PER_MM); dev->win_len = (int)(win_len_mm * PNT_PER_MM); /* don't scan if window is zero size */ if (!dev->win_width || !dev->win_len) { /* "The scan cannot be started with the current set of options." */ dev->state = SANE_STATUS_INVAL; return 0; } return 1; }
typedef enum { optCount, optGroupMode, optMode, optResolution, #ifdef SM3600_SUPPORT_EXPOSURE optBrightness, optContrast, #endif optPreview, optGrayPreview, optGroupGeometry,optTLX, optTLY, optBRX, optBRY, optGroupEnhancement, optGammaY, optGammaR,optGammaG,optGammaB, optLast } TOptionIndex; static const SANE_String_Const aScanModes[]= { "color", "gray", "lineart", "halftone", NULL }; static const SANE_Range rangeXmm = { SANE_FIX(0), SANE_FIX(220), SANE_FIX(0.1) }; static const SANE_Range rangeYmm = { SANE_FIX(0), SANE_FIX(300), SANE_FIX(0.1) }; #ifdef SM3600_SUPPORT_EXPOSURE static const SANE_Range rangeLumi = { SANE_FIX(-100.0), SANE_FIX(100.0), SANE_FIX(1.0) }; #endif
int bb_open(struct ledm_session *ps) { struct bb_ledm_session *pbb; struct device_settings *ds; int stat=1, i, j; _DBG("bb_open()\n"); if ((ps->bb_session = create_session()) == NULL) goto bugout; pbb = ps->bb_session; /* Get scanner elements from device. */ if (get_scanner_elements(ps, &pbb->elements)) { goto bugout; } /* Determine supported Scan Modes. */ ds = &pbb->elements.config.settings; for(i=0, j=0; i<CE_MAX; i++) { if (ds->color[i] == CE_K1) { ps->scanModeList[j] = SANE_VALUE_SCAN_MODE_LINEART; ps->scanModeMap[j++] = CE_K1; } if (ds->color[i] == CE_GRAY8) { ps->scanModeList[j] = SANE_VALUE_SCAN_MODE_GRAY; ps->scanModeMap[j++] = CE_GRAY8; } if (ds->color[i] == CE_COLOR8) { ps->scanModeList[j] = SANE_VALUE_SCAN_MODE_COLOR; ps->scanModeMap[j++] = CE_COLOR8; } } /* Determine scan input sources. */ i=0; if (pbb->elements.config.platen.flatbed_supported) { ps->inputSourceList[i] = STR_ADF_MODE_FLATBED; ps->inputSourceMap[i++] = IS_PLATEN; } if (pbb->elements.config.adf.supported) { ps->inputSourceList[i] = STR_ADF_MODE_ADF; ps->inputSourceMap[i++] = IS_ADF; } if (pbb->elements.config.adf.duplex_supported) { ps->inputSourceList[i] = STR_TITLE_DUPLEX; ps->inputSourceMap[i++] = IS_ADF_DUPLEX; } /* Determine if jpeg quality factor is supported. */ if (pbb->elements.config.settings.jpeg_quality_factor_supported) ps->option[LEDM_OPTION_JPEG_QUALITY].cap &= ~SANE_CAP_INACTIVE; else ps->option[LEDM_OPTION_JPEG_QUALITY].cap |= SANE_CAP_INACTIVE; /* Set flatbed x,y extents. */ ps->platen_min_width = SANE_FIX(pbb->elements.config.platen.minimum_size.width/1000.0*MM_PER_INCH); ps->platen_min_height = SANE_FIX(pbb->elements.config.platen.minimum_size.height/1000.0*MM_PER_INCH); ps->platen_tlxRange.max = SANE_FIX(pbb->elements.config.platen.maximum_size.width/11.811023); ps->platen_brxRange.max = ps->platen_tlxRange.max; ps->platen_tlyRange.max = SANE_FIX(pbb->elements.config.platen.maximum_size.height/11.811023); ps->platen_bryRange.max = ps->platen_tlyRange.max; /* Set adf/duplex x,y extents. */ ps->adf_min_width = SANE_FIX(pbb->elements.config.adf.minimum_size.width/1000.0*MM_PER_INCH); ps->adf_min_height = SANE_FIX(pbb->elements.config.adf.minimum_size.height/1000.0*MM_PER_INCH); ps->adf_tlxRange.max = SANE_FIX(pbb->elements.config.adf.maximum_size.width/11.811023); ps->adf_brxRange.max = ps->adf_tlxRange.max; ps->adf_tlyRange.max = SANE_FIX(pbb->elements.config.adf.maximum_size.height/11.811023); ps->adf_bryRange.max = ps->adf_tlyRange.max; if (pbb->elements.config.platen.flatbed_supported) { i = pbb->elements.config.platen.platen_resolution_list[0] + 1; while(i--) { _DBG("bb_open platen_resolution_list = %d\n", pbb->elements.config.platen.platen_resolution_list[i]); ps->platen_resolutionList[i] = pbb->elements.config.platen.platen_resolution_list[i]; ps->resolutionList[i] = pbb->elements.config.platen.platen_resolution_list[i]; } } if (pbb->elements.config.adf.supported) { i = pbb->elements.config.adf.adf_resolution_list[0] + 1; while(i--) { _DBG("bb_open adf_resolution_list = %d\n", pbb->elements.config.adf.adf_resolution_list[i]); ps->adf_resolutionList[i] = pbb->elements.config.adf.adf_resolution_list[i]; ps->resolutionList[i] = pbb->elements.config.adf.adf_resolution_list[i]; } } stat = 0; bugout: return stat; } /* bb_open */
static const SANE_Range buffer_range = { 1024, /* minimum bytes */ 2048 * 1024, /* maximum bytes */ 1024 /* quantization */ }; /* range for int value in [0-15] */ static const SANE_Range value16_range = { 0, /* minimum */ 15, /* maximum */ 1 /* quantization */ }; /* range for fixed height value */ static const SANE_Range height_range = { SANE_FIX (0), /* minimum */ SANE_FIX (29.7), /* maximum */ 0 /* no quantization : hard to do for float values ... */ }; /* list of astra models */ static const SANE_String_Const astra_models[] = { "610", "1220", "1600", "2000", NULL }; /* string list */ static const SANE_String_Const string_list[] = { "string1", "string2", "string3", "string4", NULL }; /* last device name used for attach callback */ static char *lastdevname = NULL;
/* * fixed option */ static void fixed_option (void) { SANE_Status status; SANEI_Config config; SANE_Word width, height, fixedarray[7]; SANE_Option_Descriptor *options[3]; void *values[3]; int i; i = 0; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "width"; options[i]->title = "width"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &width; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "height"; options[i]->title = "height"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (SANE_Word); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_NONE; values[i] = &height; i++; options[i] = (SANE_Option_Descriptor *) malloc (sizeof (SANE_Option_Descriptor)); options[i]->name = "array-of-fixed"; options[i]->title = "array of fixed"; options[i]->type = SANE_TYPE_FIXED; options[i]->unit = SANE_UNIT_NONE; options[i]->size = sizeof (fixedarray); options[i]->cap = SANE_CAP_SOFT_SELECT; options[i]->constraint_type = SANE_CONSTRAINT_RANGE; options[i]->constraint.range = &height_range; values[i] = fixedarray; i++; config.descriptors = options; config.values = values; config.count = i; /* configure and attach */ status = sanei_configure_attach (CONFIG_PATH "/data/fixed.conf", &config, check_config_attach); /* check results */ assert (status == SANE_STATUS_GOOD); assert (width == SANE_FIX (21.0)); assert (height == SANE_FIX (29.7)); for (i = 0; i < 7; i++) { assert (fixedarray[i] == SANE_FIX (2.0 + 0.1 * ((float) i))); } }
int setOptions( char *uuid, SANE_Handle *openDeviceHandle, int *request_resolution ) { int option = 0; SANE_Status status; SANE_Fixed v_f; SANE_Int v_i; SANE_Bool v_b; char *v_c; //const char *modes[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL }; const char *modes_colour[] = { SANE_VALUE_SCAN_MODE_COLOR, "Color", SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL }; const char *modes_gray[] = { SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL }; const char *speeds[] = { "Auto", "Normal", "Fast", NULL }; const char *compression[] = { "None", NULL }; const char *sources[] = { "Auto", SANE_I18N ("Auto"), "Flatbed", SANE_I18N ("Flatbed"), "FlatBed", "Normal", SANE_I18N ("Normal"), NULL }; int testScanner = 0; char *devName = getScanParam(uuid, SCAN_PARAM_DEVNAME); if ( strstr(devName, "test") != 0 ) { testScanner = 1; } free(devName); for (option = 0; option < 9999; option++) { const SANE_Option_Descriptor *sod = sane_get_option_descriptor (openDeviceHandle, option); // No more options if (sod == NULL) break; // Just a placeholder if (sod->type == SANE_TYPE_GROUP || sod->name == NULL || option == 0) continue; log_option( option, sod ); // Validation if ( (sod->cap & SANE_CAP_SOFT_SELECT) && (sod->cap & SANE_CAP_HARD_SELECT) ) { o_log(DEBUGM, "The backend said that '%s' is both hardward and software settable! Err", sod->name); updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, 0); return 0; } // we MUST set this value if ( (sod->cap & SANE_CAP_SOFT_DETECT) && ((sod->cap & SANE_CAP_INACTIVE) == 0) ) { // A hardware setting if ( sod->cap & SANE_CAP_HARD_SELECT ) { o_log(DEBUGM, "We've got no way of telling the user to set the hardward %s! Err", sod->name); } // a software setting else { int paramSetRet = 0; // Set scanning Source if ( strcmp(sod->name, SANE_NAME_SCAN_SOURCE) == 0 ) { if ( !setDefaultScannerOption(openDeviceHandle, sod, option, ¶mSetRet) ) { int i, j; int foundMatch = 0; for (i = 0; sources[i] != NULL; i++) { for (j = 0; sod->constraint.string_list[j]; j++) { if (strcmp (sources[i], sod->constraint.string_list[j]) == 0) break; } if (sod->constraint.string_list[j] != NULL) { v_c = o_strdup(sources[i]); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, ¶mSetRet); free(v_c); foundMatch = 1; break; } } if( foundMatch == 0 ) { o_log(DEBUGM, "Non of the available options are appropriate."); } } } // Set scanning mode else if ( strcmp(sod->name, SANE_NAME_SCAN_MODE ) == 0 ) { const char **modes; char *requested_mode = getScanParam(uuid, SCAN_PARAM_FORMAT ); if( 0 == strcmp( "colour", requested_mode ) ) { modes = modes_colour; } else { modes = modes_gray; } free( requested_mode ); int i, j; int foundMatch = 0; for (i = 0; modes[i] != NULL; i++) { for (j = 0; sod->constraint.string_list[j]; j++) { if (strcmp (modes[i], sod->constraint.string_list[j]) == 0) break; } if (sod->constraint.string_list[j] != NULL) { v_c = o_strdup(modes[i]); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, ¶mSetRet); free(v_c); foundMatch = 1; break; } } if( foundMatch == 0 ) { o_log(DEBUGM, "Non of the available options are appropriate."); } } else if ( strcmp(sod->name, "batch-scan" ) == 0 ) { v_b = SANE_FALSE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "compression") == 0 ) { int i, j; int foundMatch = 0; for (i = 0; compression[i] != NULL; i++) { for (j = 0; sod->constraint.string_list[j]; j++) { o_log(DEBUGM, "n list: %s", sod->constraint.string_list[j]); if (strcmp (compression[i], sod->constraint.string_list[j]) == 0) break; } if (sod->constraint.string_list[j] != NULL) { o_log(DEBUGM, "Attempting to set compresstion to: %s", compression[i]); v_c = o_strdup(compression[i]); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, ¶mSetRet); free(v_c); foundMatch = 1; break; } } if( foundMatch == 0 ) { o_log(DEBUGM, "Non of the available options are appropriate."); } } // Set scanning depth else if ( strcmp(sod->name, SANE_NAME_BIT_DEPTH) == 0 ) { if ( !setDefaultScannerOption(openDeviceHandle, sod, option, ¶mSetRet) ) { if( sod->type == SANE_TYPE_STRING ) { v_c = o_strdup("8"); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, ¶mSetRet); free(v_c); } if (sod->type == SANE_TYPE_FIXED) { v_f = SANE_FIX( 8 ); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else { v_i = 8; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, ¶mSetRet); } } } // Set Preview mode else if ( strcmp(sod->name, SANE_NAME_PREVIEW) == 0 ) { if ( !setDefaultScannerOption(openDeviceHandle, sod, option, ¶mSetRet) ) { v_b = SANE_FALSE; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } } // Set scanning resolution else if ( strcmp(sod->name, SANE_NAME_SCAN_RESOLUTION) == 0 ) { char *request_resolution_s; request_resolution_s = getScanParam(uuid, SCAN_PARAM_REQUESTED_RESOLUTION); *request_resolution = atoi(request_resolution_s); free(request_resolution_s); if (sod->type == SANE_TYPE_FIXED) { v_f = SANE_FIX( *request_resolution ); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if (sod->type == SANE_TYPE_INT) { int sane_resolution = *request_resolution; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &sane_resolution, ¶mSetRet); } else { int sane_resolution = *request_resolution; if( sod->constraint.range->quant != 0 ) sane_resolution = sane_resolution * sod->constraint.range->quant; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &sane_resolution, ¶mSetRet); } } else if ( strcmp(sod->name, SANE_NAME_SCAN_TL_Y) == 0 ) { v_f = sod->constraint.range->min; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_SCAN_TL_X) == 0 ) { v_f = sod->constraint.range->min; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_SCAN_BR_Y) == 0 ) { int pagelength; char *length_s; v_f = sod->constraint.range->max; length_s = getScanParam(uuid, SCAN_PARAM_LENGTH); pagelength = atoi(length_s); if(pagelength && pagelength >= 20 && pagelength < 100) v_f = SANE_FIX( ( SANE_UNFIX(v_f) * (double)pagelength) / 100); free(length_s); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_SCAN_BR_X) == 0 ) { v_f = sod->constraint.range->max; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_BRIGHTNESS) == 0 ) { v_f = 0; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_CONTRAST) == 0 ) { v_f = 0; status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, ¶mSetRet); } else if ( strcmp(sod->name, SANE_NAME_SCAN_SPEED) == 0) { if ( !setDefaultScannerOption(openDeviceHandle, sod, option, ¶mSetRet) ) { int i, j; int foundMatch = 0; for (i = 0; speeds[i] != NULL; i++) { for (j = 0; sod->constraint.string_list[j]; j++) { if (strcmp (speeds[i], sod->constraint.string_list[j]) == 0) break; } if (sod->constraint.string_list[j] != NULL) { v_c = o_strdup(speeds[i]); status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, ¶mSetRet); free(v_c); foundMatch = 1; break; } } if( foundMatch == 0 ) { o_log(DEBUGM, "Non of the available options are appropriate."); } } } else if ( strcmp(sod->name, "custom-gamma") == 0 ) { v_b = SANE_FALSE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } // For the test 'virtual scanner' else if (testScanner == 1) { if ( strcmp(sod->name, "hand-scanner" ) == 0 ) { v_b = SANE_FALSE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "three-pass") == 0 ){ v_b = SANE_FALSE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "three-pass-order") == 0 ) { status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "RGB", ¶mSetRet); } else if ( strcmp(sod->name, "test-raw_imageture") == 0 ) { status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "Color pattern", ¶mSetRet); } else if ( strcmp(sod->name, "read-delay") == 0 ) { v_b = SANE_TRUE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "fuzzy-parameters") == 0 ) { v_b = SANE_TRUE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "read-delay-duration") == 0 ) { v_i = 1000; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, ¶mSetRet); } else if ( strcmp(sod->name, "read-limit") == 0 ) { v_b = SANE_TRUE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } else if ( strcmp(sod->name, "read-limit-size") == 0 ) { v_i = sod->constraint.range->max; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, ¶mSetRet); } else if ( strcmp(sod->name, "read-return-value") == 0 ) { status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "Default", ¶mSetRet); } else if ( strcmp(sod->name, "ppl-loss") == 0 ) { v_i = 0; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, ¶mSetRet); } else if ( strcmp(sod->name, "invert-endianess") == 0 ) { v_b = SANE_FALSE; status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, ¶mSetRet); } } // not a 'well known' option else { // try setting automatically if ( !setDefaultScannerOption(openDeviceHandle, sod, option, ¶mSetRet) ) o_log(DEBUGM, "Could not set authmatically", sod->name); } if( status != SANE_STATUS_GOOD ) { handleSaneErrors("Cannot set no to", sod->name, status, paramSetRet); updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status); return 0; } if ( paramSetRet & SANE_INFO_RELOAD_OPTIONS ) { //start from the beginning again. option = 0; } } // setable option } else { o_log(DEBUGM, "The option does not need to be set."); } } // options loop return 1; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { struct hp5590_scanner *scanner = handle; if (!value) return SANE_STATUS_INVAL; if (!handle) return SANE_STATUS_INVAL; if (option >= HP5590_OPT_LAST) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { if (option == HP5590_OPT_NUM) { DBG(3, "%s: get total number of options - %u\n", __FUNCTION__, HP5590_OPT_LAST); *((SANE_Int *) value) = HP5590_OPT_LAST; return SANE_STATUS_GOOD; } if (!scanner->opts) return SANE_STATUS_INVAL; DBG (DBG_proc, "%s: get option '%s' value\n", __FUNCTION__, scanner->opts[option].name); if (option == HP5590_OPT_BR_X) { *(SANE_Fixed *) value = SANE_FIX (scanner->br_x * 25.4); } if (option == HP5590_OPT_BR_Y) { *(SANE_Fixed *) value = SANE_FIX (scanner->br_y * 25.4); } if (option == HP5590_OPT_TL_X) { *(SANE_Fixed *) value = SANE_FIX ((scanner->tl_x) * 25.4); } if (option == HP5590_OPT_TL_Y) { *(SANE_Fixed *) value = SANE_FIX (scanner->tl_y * 25.4); } if (option == HP5590_OPT_MODE) { switch (scanner->depth) { case DEPTH_BW: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_LINEART, strlen (SANE_VALUE_SCAN_MODE_LINEART)); break; case DEPTH_GRAY: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_GRAY, strlen (SANE_VALUE_SCAN_MODE_GRAY)); break; case DEPTH_COLOR_24: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_24, strlen (SANE_VALUE_SCAN_MODE_COLOR_24)); break; case DEPTH_COLOR_48: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_MODE_COLOR_48, strlen (SANE_VALUE_SCAN_MODE_COLOR_48)); break; default: return SANE_STATUS_INVAL; } } if (option == HP5590_OPT_SOURCE) { switch (scanner->source) { case SOURCE_FLATBED: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_FLATBED, strlen (SANE_VALUE_SCAN_SOURCE_FLATBED)); break; case SOURCE_ADF: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF, strlen (SANE_VALUE_SCAN_SOURCE_ADF)); break; case SOURCE_ADF_DUPLEX: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX, strlen (SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX)); break; case SOURCE_TMA_SLIDES: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_SLIDES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_SLIDES)); break; case SOURCE_TMA_NEGATIVES: memset (value , 0, scanner->opts[option].size); memcpy (value, SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES, strlen (SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES)); break; case SOURCE_NONE: default: return SANE_STATUS_INVAL; } } if (option == HP5590_OPT_RESOLUTION) { *(SANE_Int *) value = scanner->dpi; } if (option == HP5590_OPT_LAMP_TIMEOUT) { *(SANE_Bool *) value = scanner->extend_lamp_timeout; } if (option == HP5590_OPT_WAIT_FOR_BUTTON) { *(SANE_Bool *) value = scanner->wait_for_button; } if (option == HP5590_OPT_PREVIEW) { *(SANE_Bool *) value = scanner->preview; } } if (action == SANE_ACTION_SET_VALUE) { if (option == HP5590_OPT_NUM) return SANE_STATUS_INVAL; if (option == HP5590_OPT_BR_X) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val <= scanner->tl_x) return SANE_STATUS_GOOD; scanner->br_x = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_BR_Y) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val <= scanner->tl_y) return SANE_STATUS_GOOD; scanner->br_y = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_TL_X) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val >= scanner->br_x) return SANE_STATUS_GOOD; scanner->tl_x = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_TL_Y) { float val = SANE_UNFIX(*(SANE_Fixed *) value) / 25.4; if (val >= scanner->br_y) return SANE_STATUS_GOOD; scanner->tl_y = val; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_MODE) { if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_LINEART) == 0) { scanner->depth = DEPTH_BW; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_GRAY) == 0) { scanner->depth = DEPTH_GRAY; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_24) == 0) { scanner->depth = DEPTH_COLOR_24; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_MODE_COLOR_48) == 0) { scanner->depth = DEPTH_COLOR_48; } if (info) *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } if (option == HP5590_OPT_SOURCE) { range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_FLATBED) == 0) { scanner->source = SOURCE_FLATBED; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(scanner->info->max_size_y * 25.4); scanner->br_x = scanner->info->max_size_x; scanner->br_y = scanner->info->max_size_y; } /* In ADF modes the device can scan up to ADF_MAX_Y_INCHES, which is usually * bigger than what scanner reports back during initialization */ if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF) == 0) { scanner->source = SOURCE_ADF; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4); scanner->br_x = scanner->info->max_size_x; scanner->br_y = ADF_MAX_Y_INCHES * 25.4; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX) == 0) { scanner->source = SOURCE_ADF_DUPLEX; range_x.max = SANE_FIX(scanner->info->max_size_x * 25.4); range_y.max = SANE_FIX(ADF_MAX_Y_INCHES * 25.4 * 2); scanner->br_y = ADF_MAX_Y_INCHES * 25.4 * 2; scanner->br_x = scanner->info->max_size_x; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_SLIDES) == 0) { scanner->source = SOURCE_TMA_SLIDES; range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); scanner->br_x = TMA_MAX_X_INCHES * 25.4; scanner->br_y = TMA_MAX_Y_INCHES * 25.4; } if (strcmp ((char *) value, (char *) SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES) == 0) { scanner->source = SOURCE_TMA_NEGATIVES; range_x.max = SANE_FIX(TMA_MAX_X_INCHES * 25.4); range_y.max = SANE_FIX(TMA_MAX_Y_INCHES * 25.4); scanner->br_x = TMA_MAX_X_INCHES * 25.4; scanner->br_y = TMA_MAX_Y_INCHES * 25.4; } if (info) *info = SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } if (option == HP5590_OPT_RESOLUTION) { scanner->dpi = *(SANE_Int *) value; if (info) *info = SANE_INFO_RELOAD_PARAMS; } if (option == HP5590_OPT_LAMP_TIMEOUT) { scanner->extend_lamp_timeout = *(SANE_Bool *) value; } if (option == HP5590_OPT_WAIT_FOR_BUTTON) { scanner->wait_for_button = *(SANE_Bool *) value; } if (option == HP5590_OPT_PREVIEW) { scanner->preview = *(SANE_Bool *) value; } } return SANE_STATUS_GOOD; }
SANE_Status sane_open (SANE_String_Const devicename, SANE_Handle * handle) { struct hp5590_scanner *ptr; SANE_Option_Descriptor *opts; unsigned int available_sources; SANE_String_Const *sources_list; unsigned int source_idx; DBG (DBG_proc, "%s: device name: %s\n", __FUNCTION__, devicename); if (!handle) return SANE_STATUS_INVAL; /* Allow to open the first available device by specifying zero-length name */ if (!devicename || !devicename[0]) { ptr = scanners_list; } else { for (ptr = scanners_list; ptr && strcmp (ptr->sane.name, devicename) != 0; ptr = ptr->next); } if (!ptr) return SANE_STATUS_INVAL; ptr->tl_x = 0; ptr->tl_y = 0; ptr->br_x = ptr->info->max_size_x; ptr->br_y = ptr->info->max_size_y; ptr->dpi = res_list[1]; ptr->depth = DEPTH_BW; ptr->source = SOURCE_FLATBED; ptr->extend_lamp_timeout = SANE_FALSE; ptr->wait_for_button = SANE_FALSE; ptr->preview = SANE_FALSE; ptr->quality = 4; ptr->image_size = 0; ptr->scanning = SANE_FALSE; *handle = ptr; opts = malloc (sizeof (SANE_Option_Descriptor) * HP5590_OPT_LAST); if (!opts) return SANE_STATUS_NO_MEM; opts[HP5590_OPT_NUM].name = SANE_NAME_NUM_OPTIONS; opts[HP5590_OPT_NUM].title = SANE_TITLE_NUM_OPTIONS; opts[HP5590_OPT_NUM].desc = SANE_DESC_NUM_OPTIONS; opts[HP5590_OPT_NUM].type = SANE_TYPE_INT; opts[HP5590_OPT_NUM].unit = SANE_UNIT_NONE; opts[HP5590_OPT_NUM].size = sizeof(SANE_Word); opts[HP5590_OPT_NUM].cap = SANE_CAP_INACTIVE | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_NUM].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_NUM].constraint.string_list = NULL; range_x.min = SANE_FIX(0); range_x.max = SANE_FIX(ptr->info->max_size_x * 25.4); range_x.quant = SANE_FIX(0.1); range_y.min = SANE_FIX(0); range_y.max = SANE_FIX(ptr->info->max_size_y * 25.4); range_y.quant = SANE_FIX(0.1); range_qual.min = SANE_FIX(4); range_qual.max = SANE_FIX(16); range_qual.quant = SANE_FIX(1); opts[HP5590_OPT_TL_X].name = SANE_NAME_SCAN_TL_X; opts[HP5590_OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; opts[HP5590_OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; opts[HP5590_OPT_TL_X].type = SANE_TYPE_FIXED; opts[HP5590_OPT_TL_X].unit = SANE_UNIT_MM; opts[HP5590_OPT_TL_X].size = sizeof(SANE_Fixed); opts[HP5590_OPT_TL_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_TL_X].constraint.range = &range_x; opts[HP5590_OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; opts[HP5590_OPT_TL_Y].type = SANE_TYPE_FIXED; opts[HP5590_OPT_TL_Y].unit = SANE_UNIT_MM; opts[HP5590_OPT_TL_Y].size = sizeof(SANE_Fixed); opts[HP5590_OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_TL_Y].constraint.range = &range_y; opts[HP5590_OPT_BR_X].name = SANE_NAME_SCAN_BR_X; opts[HP5590_OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; opts[HP5590_OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; opts[HP5590_OPT_BR_X].type = SANE_TYPE_FIXED; opts[HP5590_OPT_BR_X].unit = SANE_UNIT_MM; opts[HP5590_OPT_BR_X].size = sizeof(SANE_Fixed); opts[HP5590_OPT_BR_X].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_BR_X].constraint.range = &range_x; opts[HP5590_OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; opts[HP5590_OPT_BR_Y].type = SANE_TYPE_FIXED; opts[HP5590_OPT_BR_Y].unit = SANE_UNIT_MM; opts[HP5590_OPT_BR_Y].size = sizeof(SANE_Fixed); opts[HP5590_OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; opts[HP5590_OPT_BR_Y].constraint.range = &range_y; opts[HP5590_OPT_MODE].name = SANE_NAME_SCAN_MODE; opts[HP5590_OPT_MODE].title = SANE_TITLE_SCAN_MODE; opts[HP5590_OPT_MODE].desc = SANE_DESC_SCAN_MODE; opts[HP5590_OPT_MODE].type = SANE_TYPE_STRING; opts[HP5590_OPT_MODE].unit = SANE_UNIT_NONE; opts[HP5590_OPT_MODE].size = MAX_SCAN_MODE_VALUE_LEN; opts[HP5590_OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; opts[HP5590_OPT_MODE].constraint.string_list = mode_list; available_sources = 1; /* Flatbed is always available */ if (ptr->info->features & FEATURE_ADF) available_sources += 2; if (ptr->info->features & FEATURE_TMA) available_sources += 2; available_sources++; /* Count terminating NULL */ sources_list = malloc (available_sources * sizeof (SANE_String_Const)); if (!sources_list) return SANE_STATUS_NO_MEM; source_idx = 0; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_FLATBED; if (ptr->info->features & FEATURE_ADF) { sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_ADF; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_ADF_DUPLEX; } if (ptr->info->features & FEATURE_TMA) { sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_TMA_SLIDES; sources_list[source_idx++] = SANE_VALUE_SCAN_SOURCE_TMA_NEGATIVES; } sources_list[source_idx] = NULL; opts[HP5590_OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE; opts[HP5590_OPT_SOURCE].type = SANE_TYPE_STRING; opts[HP5590_OPT_SOURCE].unit = SANE_UNIT_NONE; opts[HP5590_OPT_SOURCE].size = MAX_SCAN_SOURCE_VALUE_LEN; opts[HP5590_OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST; opts[HP5590_OPT_SOURCE].constraint.string_list = sources_list; opts[HP5590_OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; opts[HP5590_OPT_RESOLUTION].type = SANE_TYPE_INT; opts[HP5590_OPT_RESOLUTION].unit = SANE_UNIT_DPI; opts[HP5590_OPT_RESOLUTION].size = sizeof(SANE_Int); opts[HP5590_OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; opts[HP5590_OPT_RESOLUTION].constraint.word_list = res_list; opts[HP5590_OPT_LAMP_TIMEOUT].name = SANE_NAME_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].title = SANE_TITLE_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].desc = SANE_DESC_LAMP_TIMEOUT; opts[HP5590_OPT_LAMP_TIMEOUT].type = SANE_TYPE_BOOL; opts[HP5590_OPT_LAMP_TIMEOUT].unit = SANE_UNIT_NONE; opts[HP5590_OPT_LAMP_TIMEOUT].size = sizeof(SANE_Bool); opts[HP5590_OPT_LAMP_TIMEOUT].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; opts[HP5590_OPT_LAMP_TIMEOUT].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_LAMP_TIMEOUT].constraint.string_list = NULL; opts[HP5590_OPT_WAIT_FOR_BUTTON].name = SANE_NAME_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].title = SANE_TITLE_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].desc = SANE_DESC_WAIT_FOR_BUTTON; opts[HP5590_OPT_WAIT_FOR_BUTTON].type = SANE_TYPE_BOOL; opts[HP5590_OPT_WAIT_FOR_BUTTON].unit = SANE_UNIT_NONE; opts[HP5590_OPT_WAIT_FOR_BUTTON].size = sizeof(SANE_Bool); opts[HP5590_OPT_WAIT_FOR_BUTTON].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_WAIT_FOR_BUTTON].constraint.string_list = NULL; opts[HP5590_OPT_PREVIEW].name = SANE_NAME_PREVIEW; opts[HP5590_OPT_PREVIEW].title = SANE_TITLE_PREVIEW; opts[HP5590_OPT_PREVIEW].desc = SANE_DESC_PREVIEW; opts[HP5590_OPT_PREVIEW].type = SANE_TYPE_BOOL; opts[HP5590_OPT_PREVIEW].unit = SANE_UNIT_NONE; opts[HP5590_OPT_PREVIEW].size = sizeof(SANE_Bool); opts[HP5590_OPT_PREVIEW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; opts[HP5590_OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE; opts[HP5590_OPT_PREVIEW].constraint.string_list = NULL; ptr->opts = opts; return SANE_STATUS_GOOD; }
void create_options(SANE_Virtual_Device* device) { SANE_Option_Descriptor* option; option = &device->option[ALL_OPTIONS]; option->name = ""; option->title = SANE_TITLE_NUM_OPTIONS; option->desc = SANE_DESC_NUM_OPTIONS; option->type = SANE_TYPE_INT; option->unit = SANE_UNIT_NONE; option->size = sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT; option->constraint_type = SANE_CONSTRAINT_NONE; option->constraint.range = 0; device->value[ALL_OPTIONS].word = OPTION_COUNT; option = &device->option[STRING_OPTION]; option->name = "string_test"; option->title = SANE_I18N("String Test"); option->desc = SANE_I18N("Test string option"); option->type = SANE_TYPE_STRING; option->unit = SANE_UNIT_NONE; option->size = string_list_size(); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_STRING_LIST; option->constraint.string_list = string_list; device->value[STRING_OPTION].str = malloc(option->size); strcpy(device->value[STRING_OPTION].str, SANE_I18N("First String Option")); option = &device->option[WORD_OPTION_INT]; option->name = "word_test_integer"; option->title = SANE_I18N("Word Test Integer"); option->desc = SANE_I18N("Test word option with integer values"); option->type = SANE_TYPE_INT; option->unit = SANE_UNIT_BIT; option->size = sizeof(word_list_int) / sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_WORD_LIST; option->constraint.word_list = word_list_int; device->value[WORD_OPTION_INT].word = 20; option = &device->option[WORD_OPTION_FIXED]; option->name = "word_test_fixed"; option->title = SANE_I18N("Word Test Fixed"); option->desc = SANE_I18N("Test word option with fixed values"); option->type = SANE_TYPE_FIXED; option->unit = SANE_UNIT_MM; option->size = sizeof(word_list_fixed) / sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_WORD_LIST; option->constraint.word_list = word_list_fixed; device->value[WORD_OPTION_FIXED].word = SANE_FIX(30.2); option = &device->option[RANGE_OPTION]; option->name = "range_test"; option->title = SANE_I18N("Range Test"); option->desc = SANE_I18N("Test range option"); option->type = SANE_TYPE_FIXED; option->unit = SANE_UNIT_BIT; option->size = sizeof(range) / sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_RANGE; option->constraint.range = ⦥ device->value[RANGE_OPTION].word = SANE_FIX(15.0); option = &device->option[BOOL_OPTION_TRUE]; option->name = "bool_test_true"; option->title = SANE_I18N("Boolean Test True"); option->desc = SANE_I18N("Test boolean true option"); option->type = SANE_TYPE_BOOL; option->unit = SANE_UNIT_NONE; option->size = sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_NONE; device->value[BOOL_OPTION_TRUE].word = SANE_TRUE; option = &device->option[BOOL_OPTION_FALSE]; option->name = "bool_test_false"; option->title = SANE_I18N("Boolean Test False"); option->desc = SANE_I18N("Test boolean false option"); option->type = SANE_TYPE_BOOL; option->unit = SANE_UNIT_NONE; option->size = sizeof(SANE_Word); option->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; option->constraint_type = SANE_CONSTRAINT_NONE; device->value[BOOL_OPTION_FALSE].word = SANE_FALSE; }
sizeof (SANE_Word), 0, SANE_CONSTRAINT_NONE, {NULL} }; /* range for int constraint */ static const SANE_Range int_range = { 3, /* minimum */ 18, /* maximum */ 3 /* quantization */ }; /* range for sane fixed constraint */ static const SANE_Range fixed_range = { SANE_FIX(1.0), /* minimum */ SANE_FIX(431.8), /* maximum */ SANE_FIX(0.01) /* quantization */ }; static SANE_Option_Descriptor int_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, SANE_DESC_SCAN_TL_X, SANE_TYPE_FIXED, SANE_UNIT_MM, sizeof (SANE_Word), 0, SANE_CONSTRAINT_RANGE, {NULL} };
SANE_Status kv_control_option (PKV_DEV dev, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SANE_Status status; SANE_Word cap; SANE_String_Const name; int i; SANE_Word value; DBG (DBG_proc, "sane_control_option: enter, option %s, action %s\n", go_option_name[option], action == SANE_ACTION_GET_VALUE ? "R" : "W"); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_UNSUPPORTED; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_UNSUPPORTED; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_DUPLEX: case OPT_LANDSCAPE: case OPT_AUTOMATIC_SEPARATION: case OPT_INVERSE: case OPT_MIRROR: case OPT_FEED_TIMEOUT: case OPT_JPEG: case OPT_FIT_TO_PAGE: *(SANE_Word *) val = dev->val[option].w; DBG (DBG_error, "opt value = %d\n", *(SANE_Word *) val); return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_FEEDER_MODE: case OPT_SCAN_SOURCE: case OPT_MANUALFEED: case OPT_HALFTONE_PATTERN: case OPT_PAPER_SIZE: case OPT_AUTOMATIC_THRESHOLD: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: strcpy (val, dev->val[option].s); DBG (DBG_error, "opt value = %s\n", (char *) val); return SANE_STATUS_GOOD; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option %s, not settable\n", go_option_name[option]); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; if (option == OPT_RESOLUTION) { if (round_to_boundry (&(dev->val[option].w), dev->support_info. step_resolution, 100, 600)) { if (info) { *info |= SANE_INFO_INEXACT; } } } else if (option == OPT_TL_Y) { if (dev->val[option].w > dev->val[OPT_BR_Y].w) { dev->val[option].w = dev->val[OPT_BR_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (dev->val[option].w < dev->val[OPT_TL_Y].w) { dev->val[option].w = dev->val[OPT_TL_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; /* The length of X must be rounded (up). */ case OPT_TL_X: case OPT_BR_X: { SANE_Word xr = dev->val[OPT_RESOLUTION].w; SANE_Word tl_x = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)) * xr; SANE_Word br_x = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)) * xr; value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)) * xr; /* XR * W */ if (option == OPT_TL_X) { SANE_Word max = KV_PIXEL_MAX * xr - KV_PIXEL_ROUND; if (br_x < max) max = br_x; if (round_to_boundry (&value, KV_PIXEL_ROUND, 0, max)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (round_to_boundry (&value, KV_PIXEL_ROUND, tl_x, KV_PIXEL_MAX * xr)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } dev->val[option].w = SANE_FIX (iluToMm ((double) value / xr)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; } case OPT_LANDSCAPE: dev->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; /* Side-effect free options */ case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_DUPLEX: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_INVERSE: case OPT_MIRROR: case OPT_AUTOMATIC_SEPARATION: case OPT_JPEG: case OPT_FIT_TO_PAGE: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_FEED_TIMEOUT: dev->val[option].w = *(SANE_Word *) val; return CMD_set_timeout (dev, *(SANE_Word *) val); /* String mode */ case OPT_SCAN_SOURCE: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: case OPT_HALFTONE_PATTERN: case OPT_FEEDER_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (option == OPT_FEEDER_MODE && get_string_list_index (go_feeder_mode_list, dev->val[option].s) == 1) /* continuous mode */ { free (dev->val[OPT_SCAN_SOURCE].s); dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]); dev->opt[OPT_LONGPAPER].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } else { dev->opt[OPT_LONGPAPER].cap |= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } if (option == OPT_SCAN_SOURCE && get_string_list_index (go_scan_source_list, dev->val[option].s) == 1) /* flatbed */ { free (dev->val[OPT_FEEDER_MODE].s); dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[0]); } return SANE_STATUS_GOOD; case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_String) strdup (val); /* Set default options for the scan modes. */ dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[0]) == 0) /* binary */ { dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) /* halftone */ { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[2]) == 0) /* grayscale */ { dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_MANUALFEED: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (strcmp (dev->val[option].s, go_manual_feed_list[0]) == 0) /* off */ dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; else dev->opt[OPT_FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAPER_SIZE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_PAPER_SIZE].s); dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val); i = get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE].s); if (i == 0) { /*user def */ dev->opt[OPT_TL_X].cap &= dev->opt[OPT_TL_Y].cap &= dev->opt[OPT_BR_X].cap &= dev->opt[OPT_BR_Y].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } else { dev->opt[OPT_TL_X].cap |= dev->opt[OPT_TL_Y].cap |= dev->opt[OPT_BR_X].cap |= dev->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE; if (i == 4 || i == 5 || i == 7) { /*A5, A6 or B6 */ dev->opt[OPT_LANDSCAPE].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_AUTOMATIC_THRESHOLD: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_Char *) strdup (val); /* If the threshold is not set to none, some option must * disappear. */ dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (val, go_automatic_threshold_list[0]) == 0) { dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; }
static SANE_Status attach (const char *devname, Tamarack_Device **devp) { char result[INQ_LEN]; int fd; Tamarack_Device *dev; SANE_Status status; size_t size; char *mfg, *model; char *p; for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; return SANE_STATUS_GOOD; } DBG(3, "attach: opening %s\n", devname); status = sanei_scsi_open (devname, &fd, sense_handler, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "attach: open failed (%s)\n", sane_strstatus (status)); return SANE_STATUS_INVAL; } DBG(3, "attach: sending INQUIRY\n"); size = sizeof (result); status = sanei_scsi_cmd (fd, inquiry, sizeof (inquiry), result, &size); if (status != SANE_STATUS_GOOD || size != INQ_LEN) { DBG(1, "attach: inquiry failed (%s)\n", sane_strstatus (status)); sanei_scsi_close (fd); return status; } status = wait_ready (fd); sanei_scsi_close (fd); if (status != SANE_STATUS_GOOD) return status; result[33]= '\0'; p = strchr(result+16,' '); if (p) *p = '\0'; model = strdup (result+16); result[16]= '\0'; p = strchr(result+8,' '); if (p) *p = '\0'; mfg = strdup (result+8); DBG(1, "attach: Inquiry gives mfg=%s, model=%s.\n", mfg, model); if (strcmp (mfg, "TAMARACK") != 0) { DBG(1, "attach: device doesn't look like a Tamarack scanner " "(result[0]=%#02x)\n", result[0]); return SANE_STATUS_INVAL; } dev = malloc (sizeof (*dev)); if (!dev) return SANE_STATUS_NO_MEM; memset (dev, 0, sizeof (*dev)); dev->sane.name = strdup (devname); dev->sane.vendor = "Tamarack"; dev->sane.model = model; dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->y_range.min = 0; dev->x_range.quant = 0; dev->y_range.quant = 0; dev->dpi_range.min = SANE_FIX (1); dev->dpi_range.quant = SANE_FIX (1); dev->x_range.max = SANE_FIX (8.5 * MM_PER_INCH); dev->y_range.max = SANE_FIX (11.0 * MM_PER_INCH); dev->dpi_range.max = SANE_FIX (600); DBG(3, "attach: found Tamarack scanner model %s (%s)\n", dev->sane.model, dev->sane.type); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; return SANE_STATUS_GOOD; }
#include "brother_misc.c" #include "brother_modelinf.c" #include "brother_scanner.c" #include "brother_bugchk.c" #include "brother_log.c" /* ====================================================================== Initialise SANE options ====================================================================== */ #define DEBUG_MODELINF static const SANE_Range rangeLumi = { SANE_FIX(-50.0), SANE_FIX(50.0), SANE_FIX(1.0) }; #define NUM_SCANMODE (5+1) #define NUM_RESO (10+1) #define NUM_SCANSRC (2+1) static SANE_String_Const * scanModeList = 0; static SANE_Int *scanResoList = 0; static SANE_String_Const * scanSrcList = 0; static SANE_Range rangeXmm; static SANE_Range rangeYmm;
SANE_Status sanei_configure_attach (const char *config_file, SANEI_Config * config, SANE_Status (*attach) (SANEI_Config * config, const char *devname)) { SANE_Char line[PATH_MAX]; SANE_Char *token, *string; SANE_Int len; const char *lp, *lp2; FILE *fp; SANE_Status status = SANE_STATUS_GOOD; int i, j, count; void *value = NULL; int size=0; SANE_Bool found; SANE_Word *wa; SANE_Bool *ba; DBG (3, "sanei_configure_attach: start\n"); /* open configuration file */ fp = sanei_config_open (config_file); if (!fp) { DBG (2, "sanei_configure_attach: couldn't access %s\n", config_file); DBG (3, "sanei_configure_attach: exit\n"); return SANE_STATUS_ACCESS_DENIED; } /* loop reading the configuration file, all line beginning by "option " are * parsed for value to store in configuration structure, other line are * used are device to try to attach */ while (sanei_config_read (line, PATH_MAX, fp) && status == SANE_STATUS_GOOD) { /* skip white spaces at beginning of line */ lp = sanei_config_skip_whitespace (line); /* skip empty lines */ if (*lp == 0) continue; /* skip comment line */ if (line[0] == '#') continue; len = strlen (line); /* delete newline characters at end */ if (line[len - 1] == '\n') line[--len] = '\0'; lp2 = lp; /* to ensure maximum compatibility, we accept line like: * option "option_name" "option_value" * "option_name" "option_value" * So we parse the line 2 time to find an option */ /* check if it is an option */ lp = sanei_config_get_string (lp, &token); if (strncmp (token, "option", 6) == 0) { /* skip the "option" token */ free (token); lp = sanei_config_get_string (lp, &token); } /* search for a matching descriptor */ i = 0; found = SANE_FALSE; while (config!=NULL && i < config->count && !found) { if (strcmp (config->descriptors[i]->name, token) == 0) { found = SANE_TRUE; switch (config->descriptors[i]->type) { case SANE_TYPE_INT: size=config->descriptors[i]->size; value = malloc (size); wa = (SANE_Word *) value; count = config->descriptors[i]->size / sizeof (SANE_Word); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } wa[j] = strtol (string, NULL, 0); free (string); } break; case SANE_TYPE_BOOL: size=config->descriptors[i]->size; value = malloc (size); ba = (SANE_Bool *) value; count = config->descriptors[i]->size / sizeof (SANE_Bool); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } if ((strcmp (string, "1") == 0) || (strcmp (string, "true") == 0)) { ba[j] = SANE_TRUE; } else { if ((strcmp (string, "0") == 0) || (strcmp (string, "false") == 0)) ba[j] = SANE_FALSE; else { DBG (2, "sanei_configure_attach: couldn't find a valid boolean value"); return SANE_STATUS_INVAL; } } free (string); } break; case SANE_TYPE_FIXED: size=config->descriptors[i]->size; value = malloc (size); wa = (SANE_Word *) value; count = config->descriptors[i]->size / sizeof (SANE_Word); for (j = 0; j < count; j++) { lp = sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string to parse"); return SANE_STATUS_INVAL; } wa[j] = SANE_FIX(strtod (string, NULL)); free (string); } break; case SANE_TYPE_STRING: sanei_config_get_string (lp, &string); if (string == NULL) { DBG (2, "sanei_configure_attach: couldn't find a string value to parse"); return SANE_STATUS_INVAL; } value = string; size=strlen(string)+1; if(size>config->descriptors[i]->size) { size=config->descriptors[i]->size-1; string[size]=0; } break; default: DBG (1, "sanei_configure_attach: incorrect type %d for option %s, skipping option ...\n", config->descriptors[i]->type, config->descriptors[i]->name); } /* check decoded value */ status = sanei_check_value (config->descriptors[i], value); /* if value OK, copy it in configuration struct */ if (status == SANE_STATUS_GOOD) { memcpy (config->values[i], value, size); } if (value != NULL) { free (value); value = NULL; } } if (status != SANE_STATUS_GOOD) { DBG (1, "sanei_configure_attach: failed to parse option '%s', line '%s'\n", token, line); } i++; } free (token); /* not detected as an option, so we call the attach function * with it */ if (!found && status == SANE_STATUS_GOOD) { /* if not an option, try to attach */ /* to avoid every backend to depend on scsi and usb functions * we call back the backend for attach. In turn it will call * sanei_usb_attach_matching_devices, sanei_config_attach_matching_devices * or other. This means 2 callback functions per backend using this * function. */ DBG (3, "sanei_configure_attach: trying to attach with '%s'\n", lp2); if(attach!=NULL) attach (config, lp2); } } fclose (fp); DBG (3, "sanei_configure_attach: exit\n"); return status; }
static const SANE_Range u8_range = { 0, /* minimum */ 255, /* maximum */ 0 /* quantization */ }; /* David used " 100 << SANE_FIXED_SCALE_SHIFT ". This assumes that * it is implemented that way. I want to hide the datatype. */ static const SANE_Range percentage_range = { SANE_FIX(-100), /* minimum */ SANE_FIX( 100), /* maximum */ SANE_FIX( 1 ) /* quantization */ }; /* David used " 100 << SANE_FIXED_SCALE_SHIFT ". This assumes that * it is implemented that way. I want to hide the datatype. */ static const SANE_Range abs_percentage_range = { SANE_FIX( 0), /* minimum */ SANE_FIX( 100), /* maximum */ SANE_FIX( 1 ) /* quantization */ };
static void st400_init_options( ST400_Device *dev ) { static const SANE_Int depth_list[] = { 2, 1, 8 }; static const SANE_Int dpi_list[] = { 3, 200, 300, 400 }; static const SANE_Range thres_range = { SANE_FIX(0.0), SANE_FIX(100.0), SANE_FIX(0.0) }; static const SANE_Range x_range = { SANE_FIX(0.0), SANE_FIX(ST400_MAX_X * MM_PER_INCH), SANE_FIX(0.0) }; static const SANE_Range y_range = { SANE_FIX(0.0), SANE_FIX(ST400_MAX_Y * MM_PER_INCH), SANE_FIX(0.0) }; DBG(DCODE, "st400_init_options(%p)\n", (void *)dev); dev->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; dev->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; dev->opt[OPT_NUM_OPTS].unit = SANE_UNIT_NONE; dev->opt[OPT_NUM_OPTS].size = sizeof(SANE_Word); dev->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; dev->opt[OPT_NUM_OPTS].constraint_type = SANE_CONSTRAINT_NONE; dev->opt[OPT_MODE_GROUP].title= "Scan Mode"; dev->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].title= SANE_TITLE_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT; dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; dev->opt[OPT_RESOLUTION].size = sizeof(SANE_Word); dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_RESOLUTION].constraint.word_list = dpi_list; dev->opt[OPT_DEPTH].name = SANE_NAME_BIT_DEPTH; dev->opt[OPT_DEPTH].title = SANE_TITLE_BIT_DEPTH; dev->opt[OPT_DEPTH].desc = SANE_DESC_BIT_DEPTH; dev->opt[OPT_DEPTH].type = SANE_TYPE_INT; dev->opt[OPT_DEPTH].unit = SANE_UNIT_BIT; dev->opt[OPT_DEPTH].size = sizeof(SANE_Word); dev->opt[OPT_DEPTH].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST; dev->opt[OPT_DEPTH].constraint.word_list = depth_list; dev->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; dev->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; dev->opt[OPT_THRESHOLD].size = sizeof(SANE_Word); dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_THRESHOLD].constraint.range = &thres_range; dev->opt[OPT_GEOMETRY_GROUP].title= "Geometry"; dev->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; dev->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; dev->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; dev->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; dev->opt[OPT_TL_X].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_X].unit = SANE_UNIT_MM; dev->opt[OPT_TL_X].size = sizeof(SANE_Word); dev->opt[OPT_TL_X].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_X].constraint.range = &x_range; dev->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; dev->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; dev->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; dev->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_TL_Y].unit = SANE_UNIT_MM; dev->opt[OPT_TL_Y].size = sizeof(SANE_Word); dev->opt[OPT_TL_Y].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_TL_Y].constraint.range = &y_range; dev->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; dev->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; dev->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; dev->opt[OPT_BR_X].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_X].unit = SANE_UNIT_MM; dev->opt[OPT_BR_X].size = sizeof(SANE_Word); dev->opt[OPT_BR_X].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_X].constraint.range = &x_range; dev->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; dev->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; dev->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; dev->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; dev->opt[OPT_BR_Y].unit = SANE_UNIT_MM; dev->opt[OPT_BR_Y].size = sizeof(SANE_Word); dev->opt[OPT_BR_Y].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT; dev->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; dev->opt[OPT_BR_Y].constraint.range = &y_range; st400_reset_options(dev); }
static SANE_Status init_options (Tamarack_Scanner *s) { int i; memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = "Scan Mode"; s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = "Select the scan mode"; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[OPT_MODE_DEFAULT]); /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = SANE_FIX (OPT_RESOLUTION_DEFAULT); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->val[OPT_PREVIEW].w = 0; /* gray preview */ s->opt[OPT_GRAY_PREVIEW].name = SANE_NAME_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].title = SANE_TITLE_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].desc = SANE_DESC_GRAY_PREVIEW; s->opt[OPT_GRAY_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_GRAY_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* transparency adapter. */ s->opt[OPT_TRANS].name = "transparency"; s->opt[OPT_TRANS].title = "transparency"; s->opt[OPT_TRANS].desc = "Turn on the transparency adapter."; s->opt[OPT_TRANS].type = SANE_TYPE_BOOL; s->opt[OPT_TRANS].unit = SANE_UNIT_NONE; s->val[OPT_TRANS].w = SANE_FALSE; /* brightness */ s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS " This option is active for lineart/halftone modes only. " "For multibit modes (grey/color) use the gamma-table(s)."; s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED; s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT; s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BRIGHTNESS].constraint.range = &percentage_range; s->val[OPT_BRIGHTNESS].w = SANE_FIX(0); /* contrast */ s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST " This option is active for lineart/halftone modes only. " "For multibit modes (grey/color) use the gamma-table(s)."; s->opt[OPT_CONTRAST].type = SANE_TYPE_FIXED; s->opt[OPT_CONTRAST].unit = SANE_UNIT_PERCENT; s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_CONTRAST].constraint.range = &percentage_range; s->val[OPT_CONTRAST].w = SANE_FIX(0); /* Threshold */ s->opt[OPT_THRESHOLD].name = "Threshold"; s->opt[OPT_THRESHOLD].title = "Threshold"; s->opt[OPT_THRESHOLD].desc = "Threshold: below this level is black, above is white" " This option is active for bitmap modes only. "; s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &abs_percentage_range; s->val[OPT_THRESHOLD].w = SANE_FIX(50); s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; #if 0 /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* grayscale gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gamma_table[0][0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->gamma_table[1][0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->gamma_table[2][0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->gamma_table[3][0]; #endif return SANE_STATUS_GOOD; }
static SANE_Status calc_parameters (Mustek_Usb_Scanner * s) { SANE_String val; SANE_Status status = SANE_STATUS_GOOD; SANE_Int max_x, max_y; DBG (5, "calc_parameters: start\n"); val = s->val[OPT_MODE].s; s->params.last_frame = SANE_TRUE; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->bpp = 1; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->bpp = 8; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) { s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->bpp = 24; s->channels = 3; } else { DBG (1, "calc_parameters: invalid mode %s\n", (SANE_Char *) val); status = SANE_STATUS_INVAL; } s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; s->width = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->tl_x; s->height = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->tl_y; if (s->width < 0) { DBG (1, "calc_parameters: warning: tl_x > br_x\n"); } if (s->height < 0) { DBG (1, "calc_parameters: warning: tl_y > br_y\n"); } max_x = s->hw->max_width * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; max_y = s->hw->max_height * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; s->tl_x_dots = s->tl_x * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->width_dots = s->width * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->tl_y_dots = s->tl_y * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->height_dots = s->height * SANE_UNFIX (s->val[OPT_RESOLUTION].w); if (s->width_dots > max_x) s->width_dots = max_x; if (s->height_dots > max_y) s->height_dots = max_y; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->width_dots = (s->width_dots / 8) * 8; if (s->width_dots == 0) s->width_dots = 8; } if (s->tl_x_dots < 0) s->tl_x_dots = 0; if (s->tl_y_dots < 0) s->tl_y_dots = 0; if (s->tl_x_dots + s->width_dots > max_x) s->tl_x_dots = max_x - s->width_dots; if (s->tl_y_dots + s->height_dots > max_y) s->tl_y_dots = max_y - s->height_dots; s->val[OPT_TL_X].w = SANE_FIX (s->tl_x * MM_PER_INCH); s->val[OPT_TL_Y].w = SANE_FIX (s->tl_y * MM_PER_INCH); s->val[OPT_BR_X].w = SANE_FIX ((s->tl_x + s->width) * MM_PER_INCH); s->val[OPT_BR_Y].w = SANE_FIX ((s->tl_y + s->height) * MM_PER_INCH); s->params.pixels_per_line = s->width_dots; if (s->params.pixels_per_line < 0) s->params.pixels_per_line = 0; s->params.lines = s->height_dots; if (s->params.lines < 0) s->params.lines = 0; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8 * s->channels; DBG (4, "calc_parameters: format=%d\n", s->params.format); DBG (4, "calc_parameters: last frame=%d\n", s->params.last_frame); DBG (4, "calc_parameters: lines=%d\n", s->params.lines); DBG (4, "calc_parameters: pixels per line=%d\n", s->params.pixels_per_line); DBG (4, "calc_parameters: bytes per line=%d\n", s->params.bytes_per_line); DBG (4, "calc_parameters: Pixels %dx%dx%d\n", s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); DBG (5, "calc_parameters: exit\n"); return status; }
break; case SANE_ACTION_SET_VALUE: optionAGainValue = *(SANE_Int *) value; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: *(SANE_Int *) value = optionAGainValue; break; } return SANE_STATUS_GOOD; } /*-----------------------------------------------------------------*/ /* Scanner gamma setting */ static SANE_Fixed optionGammaValue = SANE_FIX (1.6); static SANE_Option_Descriptor optionGammaDescriptor = { "gamma", SANE_I18N ("Gamma Correction"), SANE_I18N ("Selects the gamma corrected transfer curve"), SANE_TYPE_FIXED, SANE_UNIT_NONE, sizeof (SANE_Int), SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED, SANE_CONSTRAINT_NONE, {NULL} }; static SANE_Status
static SANE_Status init_options (Mustek_Usb_Scanner * s) { SANE_Int option; SANE_Status status; DBG (5, "init_options: start\n"); memset (s->opt, 0, sizeof (s->opt)); memset (s->val, 0, sizeof (s->val)); for (option = 0; option < NUM_OPTIONS; ++option) { s->opt[option].size = sizeof (SANE_Word); s->opt[option].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->val[OPT_NUM_OPTS].w = NUM_OPTIONS; /* "Mode" group: */ s->opt[OPT_MODE_GROUP].title = SANE_I18N ("Scan Mode"); s->opt[OPT_MODE_GROUP].desc = ""; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* scan mode */ mode_list[0] = SANE_VALUE_SCAN_MODE_COLOR; mode_list[1] = SANE_VALUE_SCAN_MODE_GRAY; mode_list[2] = SANE_VALUE_SCAN_MODE_LINEART; mode_list[3] = NULL; s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; s->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE; s->opt[OPT_MODE].type = SANE_TYPE_STRING; s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST; s->opt[OPT_MODE].size = max_string_size (mode_list); s->opt[OPT_MODE].constraint.string_list = mode_list; s->val[OPT_MODE].s = strdup (mode_list[1]); /* resolution */ s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION; s->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED; s->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI; s->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_RESOLUTION].constraint.range = &s->hw->dpi_range; s->val[OPT_RESOLUTION].w = s->hw->dpi_range.min; if (s->hw->chip->scanner_type == MT_600CU) s->hw->dpi_range.max = SANE_FIX (600); else s->hw->dpi_range.max = SANE_FIX (1200); /* preview */ s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW; s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW; s->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW; s->opt[OPT_PREVIEW].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; s->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL; s->val[OPT_PREVIEW].w = SANE_FALSE; /* "Geometry" group: */ s->opt[OPT_GEOMETRY_GROUP].title = SANE_I18N ("Geometry"); s->opt[OPT_GEOMETRY_GROUP].desc = ""; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* top-left x */ s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; s->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X; s->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X; s->opt[OPT_TL_X].type = SANE_TYPE_FIXED; s->opt[OPT_TL_X].unit = SANE_UNIT_MM; s->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_X].constraint.range = &s->hw->x_range; s->val[OPT_TL_X].w = 0; /* top-left y */ s->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y; s->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y; s->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y; s->opt[OPT_TL_Y].type = SANE_TYPE_FIXED; s->opt[OPT_TL_Y].unit = SANE_UNIT_MM; s->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_TL_Y].constraint.range = &s->hw->y_range; s->val[OPT_TL_Y].w = 0; /* bottom-right x */ s->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X; s->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X; s->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X; s->opt[OPT_BR_X].type = SANE_TYPE_FIXED; s->opt[OPT_BR_X].unit = SANE_UNIT_MM; s->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_X].constraint.range = &s->hw->x_range; s->val[OPT_BR_X].w = s->hw->x_range.max; /* bottom-right y */ s->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y; s->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y; s->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y; s->opt[OPT_BR_Y].type = SANE_TYPE_FIXED; s->opt[OPT_BR_Y].unit = SANE_UNIT_MM; s->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BR_Y].constraint.range = &s->hw->y_range; s->val[OPT_BR_Y].w = s->hw->y_range.max; /* "Enhancement" group: */ s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; /* threshold */ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_THRESHOLD].constraint.range = &u8_range; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->val[OPT_THRESHOLD].w = 128; /* custom-gamma table */ s->opt[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA; s->opt[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL; s->val[OPT_CUSTOM_GAMMA].w = SANE_FALSE; /* gray gamma vector */ s->opt[OPT_GAMMA_VECTOR].name = SANE_NAME_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].title = SANE_TITLE_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].desc = SANE_DESC_GAMMA_VECTOR; s->opt[OPT_GAMMA_VECTOR].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR].wa = &s->gray_gamma_table[0]; /* red gamma vector */ s->opt[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R; s->opt[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_R].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_R].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_R].wa = &s->red_gamma_table[0]; /* green gamma vector */ s->opt[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G; s->opt[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_G].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_G].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_G].wa = &s->green_gamma_table[0]; /* blue gamma vector */ s->opt[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B; s->opt[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE; s->opt[OPT_GAMMA_VECTOR_B].size = 256 * sizeof (SANE_Word); s->opt[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_GAMMA_VECTOR_B].constraint.range = &u8_range; s->val[OPT_GAMMA_VECTOR_B].wa = &s->blue_gamma_table[0]; RIE (calc_parameters (s)); DBG (5, "init_options: exit\n"); return SANE_STATUS_GOOD; }
static SANE_Status attach (SANE_String_Const devname, Mustek_Usb_Device ** devp, SANE_Bool may_wait) { Mustek_Usb_Device *dev; SANE_Status status; Mustek_Type scanner_type; SANE_Int fd; DBG (5, "attach: start: devp %s NULL, may_wait = %d\n", devp ? "!=" : "==", may_wait); if (!devname) { DBG (1, "attach: devname == NULL\n"); return SANE_STATUS_INVAL; } for (dev = first_dev; dev; dev = dev->next) if (strcmp (dev->sane.name, devname) == 0) { if (devp) *devp = dev; DBG (4, "attach: device `%s' was already in device list\n", devname); return SANE_STATUS_GOOD; } DBG (4, "attach: trying to open device `%s'\n", devname); status = sanei_usb_open (devname, &fd); if (status != SANE_STATUS_GOOD) { DBG (3, "attach: couldn't open device `%s': %s\n", devname, sane_strstatus (status)); return status; } DBG (4, "attach: device `%s' successfully opened\n", devname); /* try to identify model */ DBG (4, "attach: trying to identify device `%s'\n", devname); status = usb_low_identify_scanner (fd, &scanner_type); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: device `%s' doesn't look like a supported scanner\n", devname); sanei_usb_close (fd); return status; } sanei_usb_close (fd); if (scanner_type == MT_UNKNOWN) { DBG (3, "attach: warning: couldn't identify device `%s', must set " "type manually\n", devname); } dev = malloc (sizeof (Mustek_Usb_Device)); if (!dev) { DBG (1, "attach: couldn't malloc Mustek_Usb_Device\n"); return SANE_STATUS_NO_MEM; } memset (dev, 0, sizeof (*dev)); dev->name = strdup (devname); dev->sane.name = (SANE_String_Const) dev->name; dev->sane.vendor = "Mustek"; switch (scanner_type) { case MT_1200CU: dev->sane.model = "1200 CU"; break; case MT_1200CU_PLUS: dev->sane.model = "1200 CU Plus"; break; case MT_1200USB: dev->sane.model = "1200 USB (unsupported)"; break; case MT_1200UB: dev->sane.model = "1200 UB"; break; case MT_600CU: dev->sane.model = "600 CU"; break; case MT_600USB: dev->sane.model = "600 USB (unsupported)"; break; default: dev->sane.model = "(unidentified)"; break; } dev->sane.type = "flatbed scanner"; dev->x_range.min = 0; dev->x_range.max = SANE_FIX (8.4 * MM_PER_INCH); dev->x_range.quant = 0; dev->y_range.min = 0; dev->y_range.max = SANE_FIX (11.7 * MM_PER_INCH); dev->y_range.quant = 0; dev->max_height = 11.7 * 300; dev->max_width = 8.4 * 300; dev->dpi_range.min = SANE_FIX (50); dev->dpi_range.max = SANE_FIX (600); dev->dpi_range.quant = SANE_FIX (1); status = usb_high_scan_init (dev); if (status != SANE_STATUS_GOOD) { DBG (1, "attach: usb_high_scan_init returned status: %s\n", sane_strstatus (status)); free (dev); return status; } dev->chip->scanner_type = scanner_type; dev->chip->max_block_size = max_block_size; DBG (2, "attach: found %s %s %s at %s\n", dev->sane.vendor, dev->sane.type, dev->sane.model, dev->sane.name); ++num_devices; dev->next = first_dev; first_dev = dev; if (devp) *devp = dev; DBG (5, "attach: exit\n"); return SANE_STATUS_GOOD; }
}; static SANE_String_Const scan_modes[] = { SANE_VALUE_SCAN_MODE_LINEART, SANE_VALUE_SCAN_MODE_HALFTONE, SANE_VALUE_SCAN_MODE_GRAY, SANE_VALUE_SCAN_MODE_COLOR, NULL }; static int scan_mode_to_code[] = { 0x00, 0x01, 0x03, 0x05 }; static SANE_Range threshold = { SANE_FIX(30), SANE_FIX(70), SANE_FIX(10) }; static void reset_options(struct device *dev) { dev->val[OPT_RESOLUTION].w = 150; dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR); /* if docs loaded in adf use it as default source, flatbed oterwise */ dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]); dev->val[OPT_THRESHOLD].w = SANE_FIX(50); /* this is reported maximum window size, will be fixed later */ dev->win_x_range.min = SANE_FIX(0); dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM);