static SANE_Status optionResolutionCallback (SANE_Option * option, SANE_Handle handle, SANE_Action action, void *value, SANE_Int * info) { SANE_Status status; SANE_Word autoValue = 75; handle = handle; /* Eliminate warning about unused parameters */ switch (action) { case SANE_ACTION_SET_AUTO: status = sanei_constrain_value (option->descriptor, (void *) &autoValue, info); if (status != SANE_STATUS_GOOD) return status; optionResolutionValue = autoValue; *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_SET_VALUE: *info |= SANE_INFO_RELOAD_PARAMS; optionResolutionValue = *(SANE_Word *) value; break; case SANE_ACTION_GET_VALUE: *(SANE_Word *) value = optionResolutionValue; break; } return SANE_STATUS_GOOD; }
static void none_int (void) { SANE_Int value = 555; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&none_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); }
static void none_bool_ok (void) { SANE_Bool value = SANE_FALSE; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&none_bool_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); }
static void string_array_ok (void) { SANE_Char value[9] = "Lineart"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); }
static void wrong_string_array (void) { SANE_Char value[9] = "wrong"; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&string_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_INVAL); assert (info == 0); }
static void above_max_fixed_value (void) { SANE_Int value = fixed_range.max + 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == fixed_range.max); }
static void closest_300_word (void) { SANE_Word value = 251; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == 300); }
static void in_range_fixed_value (void) { SANE_Int value = fixed_range.min + fixed_range.quant; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&fixed_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == fixed_range.min + fixed_range.quant); }
/* rounded to higher value */ static void quant2_int_value (void) { SANE_Int value = int_range.min + int_range.quant - 1; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); assert (value == int_range.min + int_range.quant); }
static void max_int_value (void) { SANE_Int value = int_range.max; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&int_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == int_range.max); }
static void exact_400_word (void) { SANE_Word value = 400; SANE_Word info = 0; SANE_Status status; status = sanei_constrain_value (&word_array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); assert (value == 400); }
static void above_max_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.max + 1; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == SANE_INFO_INEXACT); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.max); } }
static void in_range_int_array (void) { SANE_Int value[ARRAY_SIZE]; SANE_Word info = 0; SANE_Status status; int i; for (i = 0; i < ARRAY_SIZE; i++) { value[i] = int_range.min + int_range.quant; } status = sanei_constrain_value (&array_opt, &value, &info); /* check results */ assert (status == SANE_STATUS_GOOD); assert (info == 0); for (i = 0; i < ARRAY_SIZE; i++) { assert (value[i] == int_range.min + int_range.quant); } }
/* This routine dispatches the control message to the appropriate callback routine, it outght to be called by sane_control_option after any driver specific validation. */ static SANE_Status dispatch_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Option *op = so + option; SANE_Int myinfo = 0; SANE_Status status = SANE_STATUS_GOOD; if (option < 0 || option >= NELEMS (so)) return SANE_STATUS_INVAL; /* Unknown option ... */ if ((action == SANE_ACTION_SET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_SELECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_GET_VALUE) && ((op->descriptor->cap & SANE_CAP_SOFT_DETECT) == 0)) return SANE_STATUS_INVAL; if ((action == SANE_ACTION_SET_AUTO) && ((op->descriptor->cap & SANE_CAP_AUTOMATIC) == 0)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_SET_VALUE) { status = sanei_constrain_value (op->descriptor, value, &myinfo); if (status != SANE_STATUS_GOOD) return status; } status = (op->callback) (op, handle, action, value, &myinfo); if (info) *info = myinfo; return status; }
SANE_Status sane_control_option( SANE_Handle handle, SANE_Int optnum, SANE_Action action, void *valP, SANE_Int *infoP) { ST400_Device *dev = handle; SANE_Status status; DBG(DCODE, "sane_control_option(%p, %d, %d, %p, %p)\n", (void *) handle, (int)optnum, (int)action, valP, (void *) infoP); if( infoP ) *infoP = 0; if( !dev->status.open ) return SANE_STATUS_INVAL; if( dev->status.scanning ) return SANE_STATUS_DEVICE_BUSY; if( optnum < 0 || optnum >= NUM_OPTIONS ) return SANE_STATUS_INVAL; switch( action ) { case SANE_ACTION_GET_VALUE: DBG(DOPT, "getting option %d (value=%d)\n", (int)optnum, (int)dev->val[optnum]); switch( optnum ) { case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_DEPTH: case OPT_THRESHOLD: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *)valP = dev->val[optnum]; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_VALUE: if( !SANE_OPTION_IS_SETTABLE(dev->opt[optnum].cap) ) return SANE_STATUS_INVAL; status = sanei_constrain_value(&dev->opt[optnum], valP, infoP); if( status != SANE_STATUS_GOOD ) return status; DBG(DOPT, "setting option %d to %d\n", (int)optnum, (int)*(SANE_Word *)valP); switch( optnum ) { case OPT_DEPTH: if( *(SANE_Word *)valP != 1 ) dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; else dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; if( infoP ) *infoP |= SANE_INFO_RELOAD_OPTIONS; /* fall through */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if( infoP ) *infoP |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_THRESHOLD: dev->val[optnum] = *(SANE_Word *)valP; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: DBG(DOPT, "automatic option setting\n"); return SANE_STATUS_UNSUPPORTED; default: return SANE_STATUS_INVAL; } return SANE_STATUS_GOOD; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Ricoh_Scanner *s = handle; SANE_Status status; SANE_Word cap; DBG (11, ">> sane_control_option\n"); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; /* fall through */ case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return (SANE_STATUS_GOOD); } } DBG (11, "<< sane_control_option\n"); return (SANE_STATUS_INVAL); }
static SANE_Status constrain_value (Tamarack_Scanner *s, SANE_Int option, void *value, SANE_Int *info) { return sanei_constrain_value (s->opt + option, value, info); }
static SANE_Status setvalue (SANE_Handle h, SANE_Int option, void *value, SANE_Int * info) { struct device_s *dev = (struct device_s *) h; SANE_Status status = SANE_STATUS_GOOD; int s_unit; int s_unit_2; if (option == 0) return SANE_STATUS_UNSUPPORTED; status = sanei_constrain_value (&(dev->optiond[option]), value, info); if (status != SANE_STATUS_GOOD) return status; if (info) *info |= SANE_INFO_RELOAD_PARAMS; switch (option) { case X1_OFFSET: dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_X_S)) * MAX_X_H); s_unit_2 = (int) round2 ((dev->optionw[X2_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 - MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_X_H)) * MAX_X_S); if (info) *info |= SANE_INFO_INEXACT; break; case X2_OFFSET: /* X units */ /* convert into "scanner" unit, then back into mm */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_X_S)) * MAX_X_H); s_unit_2 = (int) round2 ((dev->optionw[X1_OFFSET] / ((double) MAX_X_S)) * MAX_X_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 + MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_X_H)) * MAX_X_S); if (info) *info |= SANE_INFO_INEXACT; break; case Y1_OFFSET: /* Y units */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_Y_S)) * MAX_Y_H); s_unit_2 = (int) round2 ((dev->optionw[Y2_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 - MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_Y_H)) * MAX_Y_S); if (info) *info |= SANE_INFO_INEXACT; break; case Y2_OFFSET: /* Y units */ dev->optionw[option] = *((SANE_Word *) value); s_unit = (int) round2 ((dev->optionw[option] / ((double) MAX_Y_S)) * MAX_Y_H); s_unit_2 = (int) round2 ((dev->optionw[Y1_OFFSET] / ((double) MAX_Y_S)) * MAX_Y_H); if (abs (s_unit_2 - s_unit) < MIN_SCAN_ZONE) s_unit = s_unit_2 + MIN_SCAN_ZONE; dev->optionw[option] = round2 ((s_unit / ((double) MAX_Y_H)) * MAX_Y_S); if (info) *info |= SANE_INFO_INEXACT; break; case COLOR_OFFSET: if (!strcmp ((char *) value, mode_list[0])) dev->optionw[option] = GRAY; /* Gray */ else if (!strcmp ((char *) value, mode_list[1])) dev->optionw[option] = RGB; /* RGB */ else return SANE_STATUS_INVAL; break; default: dev->optionw[option] = *((SANE_Word *) value); } return SANE_STATUS_GOOD; }
/* Control option */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { int i; SANE_Status status; SANE_Word cap; struct scanner *s = (struct scanner *) handle; if (info) *info = 0; if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_UNSUPPORTED; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_UNSUPPORTED; if (action == SANE_ACTION_GET_VALUE) { if (s->opt[option].type == SANE_TYPE_STRING) { DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %s\n", option, s->val[option].s); strcpy (val, s->val[option].s); } else { *(SANE_Word *) val = s->val[option].w; DBG (DBG_INFO, "sane_control_option: reading opt[%d] = %d\n", option, s->val[option].w); } return SANE_STATUS_GOOD; } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; if (s->opt[option].type == SANE_TYPE_STRING) { if (!strcmp (val, s->val[option].s)) return SANE_STATUS_GOOD; DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %s\n", option, (SANE_String_Const) val); } else { if (*(SANE_Word *) val == s->val[option].w) return SANE_STATUS_GOOD; DBG (DBG_INFO, "sane_control_option: writing opt[%d] = %d\n", option, *(SANE_Word *) val); } switch (option) { /* Side-effect options */ case RESOLUTION: s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case TL_Y: if ((*(SANE_Word *) val) + MIN_LENGTH <= s->val[BR_Y].w && !check_area (s, s->val[TL_X].w, *(SANE_Word *) val, s->val[BR_X].w, s->val[BR_Y].w)) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case BR_Y: if ((*(SANE_Word *) val) >= s->val[TL_Y].w + MIN_LENGTH && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w, s->val[BR_X].w, *(SANE_Word *) val)) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case TL_X: if ((*(SANE_Word *) val) + MIN_WIDTH <= s->val[BR_X].w && !check_area (s, *(SANE_Word *) val, s->val[TL_Y].w, s->val[BR_X].w, s->val[BR_Y].w)) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case BR_X: if (*(SANE_Word *) val >= s->val[TL_X].w + MIN_WIDTH && !check_area (s, s->val[TL_X].w, s->val[TL_Y].w, *(SANE_Word *) val, s->val[BR_Y].w)) { s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; } else if (info) *info |= SANE_INFO_INEXACT | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case LANDSCAPE: s->val[option].w = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* Side-effect free options */ case CONTRAST: case BRIGHTNESS: case DUPLEX: case LENGTHCTL: case LONG_PAPER: case FIT_TO_PAGE: case THRESHOLD: case INVERSE: case COMPRESSION_PAR: case DFSTOP: case DFEED_L: case DFEED_C: case DFEED_R: case STOP_SKEW: case DESKEW: case MIRROR: case CROP: case TOPPOS: case BTMPOS: case RED_CHROMA: case BLUE_CHROMA: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case FEED_TIMEOUT: s->val[option].w = *(SANE_Word *) val; return kvs40xx_set_timeout (s, s->val[option].w); /* String mode */ case IMAGE_EMPHASIS: case GAMMA_CORRECTION: case LAMP: case HALFTONE_PATTERN: case DFEED_SENCE: case AUTOMATIC_THRESHOLD: case WHITE_LEVEL: case NOISE_REDUCTION: strcpy (s->val[option].s, val); return SANE_STATUS_GOOD; case SOURCE: strcpy (s->val[option].s, val); if (strcmp (s->val[option].s, SANE_I18N ("adf"))) { strcpy (s->val[FEEDER_MODE].s, feeder_mode_list[0]); strcpy (s->val[MANUALFEED].s, manual_feed_list[0]); s->val[DUPLEX].w = SANE_FALSE; s->val[DBLFEED].w = SANE_FALSE; s->val[BTMPOS].w = SANE_FALSE; s->val[TOPPOS].w = SANE_FALSE; s->val[STOP_SKEW].w = SANE_FALSE; s->val[LENGTHCTL].w = SANE_FALSE; s->val[LONG_PAPER].w = SANE_FALSE; s->opt[FEEDER_MODE].cap |= SANE_CAP_INACTIVE; s->opt[MANUALFEED].cap |= SANE_CAP_INACTIVE; s->opt[DUPLEX].cap |= SANE_CAP_INACTIVE; s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE; s->opt[BTMPOS].cap |= SANE_CAP_INACTIVE; s->opt[TOPPOS].cap |= SANE_CAP_INACTIVE; s->opt[STOP_SKEW].cap |= SANE_CAP_INACTIVE; s->opt[LENGTHCTL].cap |= SANE_CAP_INACTIVE; s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE; } else { s->opt[FEEDER_MODE].cap &= ~SANE_CAP_INACTIVE; s->opt[MANUALFEED].cap &= ~SANE_CAP_INACTIVE; s->opt[DUPLEX].cap &= ~SANE_CAP_INACTIVE; s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE; s->opt[BTMPOS].cap &= ~SANE_CAP_INACTIVE; s->opt[TOPPOS].cap &= ~SANE_CAP_INACTIVE; s->opt[STOP_SKEW].cap &= ~SANE_CAP_INACTIVE; s->opt[LENGTHCTL].cap &= ~SANE_CAP_INACTIVE; s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case FEEDER_MODE: strcpy (s->val[option].s, val); if (strcmp (s->val[option].s, SANE_I18N ("continuous"))) { s->opt[LONG_PAPER].cap |= SANE_CAP_INACTIVE; } else { s->opt[LONG_PAPER].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case MODE: strcpy (s->val[option].s, val); if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_LINEART)) { s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; s->opt[COMPRESSION].cap |= SANE_CAP_INACTIVE; s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE; s->opt[THRESHOLD].cap &= ~SANE_CAP_INACTIVE; s->opt[HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; s->opt[AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; s->opt[WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; s->opt[NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE; s->opt[RED_CHROMA].cap |= SANE_CAP_INACTIVE; s->opt[BLUE_CHROMA].cap |= SANE_CAP_INACTIVE; } else { s->opt[COMPRESSION].cap &= ~SANE_CAP_INACTIVE; s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE; s->opt[THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[INVERSE].cap |= SANE_CAP_INACTIVE; s->opt[HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; s->opt[AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; s->opt[NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; s->opt[RED_CHROMA].cap &= ~SANE_CAP_INACTIVE; s->opt[BLUE_CHROMA].cap &= ~SANE_CAP_INACTIVE; } if (!strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY)) { s->opt[INVERSE].cap &= ~SANE_CAP_INACTIVE; s->opt[GAMMA_CORRECTION].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[GAMMA_CORRECTION].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case MANUALFEED: strcpy (s->val[option].s, val); if (strcmp (s->val[option].s, manual_feed_list[0]) == 0) /* off */ s->opt[FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; else s->opt[FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case STAPELED_DOC: strcpy (s->val[option].s, val); if (strcmp (s->val[option].s, stapeled_list[0]) == 0) { s->opt[DBLFEED].cap &= ~SANE_CAP_INACTIVE; s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[DBLFEED].cap |= SANE_CAP_INACTIVE; s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case DBLFEED: s->val[option].w = *(SANE_Word *) val; if (!s->val[option].b) { s->opt[DFSTOP].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_L].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_C].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_R].cap |= SANE_CAP_INACTIVE; s->opt[DFEED_SENCE].cap |= SANE_CAP_INACTIVE; } else { s->opt[DFSTOP].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_L].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_C].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_R].cap &= ~SANE_CAP_INACTIVE; s->opt[DFEED_SENCE].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case PAPER_SIZE: strcpy (s->val[option].s, val); i = str_index (paper_list, s->val[option].s); if (i == 0) { /*user def */ s->opt[TL_X].cap &= s->opt[TL_Y].cap &= s->opt[BR_X].cap &= s->opt[BR_Y].cap &= ~SANE_CAP_INACTIVE; s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE; s->val[LANDSCAPE].w = 0; } else { s->opt[TL_X].cap |= s->opt[TL_Y].cap |= s->opt[BR_X].cap |= s->opt[BR_Y].cap |= SANE_CAP_INACTIVE; if ( /*i == 4 || */ i == 5 || i == 6 /*XXX*/ || i == 10 || i == 11) { /*A4, A5, A6, B5, B6 */ if ((s->id == KV_S4085CL || s->id == KV_S4065CL) && i == 4 && i == 10) { /*A4, B5 */ s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE; s->val[LANDSCAPE].w = 0; } else s->opt[LANDSCAPE].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[LANDSCAPE].cap |= SANE_CAP_INACTIVE; s->val[LANDSCAPE].w = 0; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case COMPRESSION: s->val[option].w = *(SANE_Word *) val; if (!s->val[option].b) { s->opt[COMPRESSION_PAR].cap |= SANE_CAP_INACTIVE; } else { s->opt[COMPRESSION_PAR].cap &= ~SANE_CAP_INACTIVE; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } } return SANE_STATUS_UNSUPPORTED; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_Word cap; SANE_Int myinfo = 0; DBG (5, "sane_control_option: start: action = %s, option = %s (%d)\n", (action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_SET_VALUE) ? "set" : (action == SANE_ACTION_SET_AUTO) ? "set_auto" : "unknown", s->opt[option].name, option); if (info) *info = 0; if (s->scanning) { DBG (1, "sane_control_option: don't call this function while " "scanning\n"); return SANE_STATUS_DEVICE_BUSY; } if (option >= NUM_OPTIONS || option < 0) { DBG (1, "sane_control_option: option %d >= NUM_OPTIONS || option < 0\n", option); return SANE_STATUS_INVAL; } cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (2, "sane_control_option: option %d is inactive\n", option); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_THRESHOLD: case OPT_CUSTOM_GAMMA: *(SANE_Word *) val = s->val[option].w; break; /* word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (val, s->val[option].wa, s->opt[option].size); break; /* string options: */ case OPT_MODE: strcpy (val, s->val[option].s); break; default: DBG (2, "sane_control_option: can't get unknown option %d\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (2, "sane_control_option: option %d is not settable\n", option); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (2, "sane_control_option: sanei_constrain_value returned %s\n", sane_strstatus (status)); return status; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; RIE (calc_parameters (s)); myinfo |= SANE_INFO_RELOAD_PARAMS; break; case OPT_THRESHOLD: s->val[option].w = *(SANE_Word *) val; break; /* Boolean */ case OPT_PREVIEW: s->val[option].w = *(SANE_Bool *) val; break; /* side-effect-free word-array options: */ case OPT_GAMMA_VECTOR: case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: memcpy (s->val[option].wa, val, s->opt[option].size); check_gamma_table (s->val[option].wa); break; case OPT_CUSTOM_GAMMA: s->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; myinfo |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->red_table = s->red_gamma_table; s->green_table = s->green_gamma_table; s->blue_table = s->blue_gamma_table; s->gray_table = s->gray_gamma_table; if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; else if (strcmp (s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { s->red_table = s->linear_gamma_table; s->green_table = s->linear_gamma_table; s->blue_table = s->linear_gamma_table; s->gray_table = s->linear_gamma_table; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; } break; case OPT_MODE: if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); RIE (calc_parameters (s)); s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; if (strcmp (val, SANE_VALUE_SCAN_MODE_LINEART) == 0) { s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; } else { s->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (s->val[OPT_CUSTOM_GAMMA].w == SANE_TRUE) { s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } myinfo |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; break; default: DBG (2, "sane_control_option: can't set unknown option %d\n", option); } } else { DBG (2, "sane_control_option: unknown action %d for option %d\n", action, option); return SANE_STATUS_INVAL; } if (info) *info = myinfo; DBG (5, "sane_control_option: exit\n"); return SANE_STATUS_GOOD; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Leo_Scanner *dev = handle; SANE_Status status; SANE_Word cap; int i; DBG (DBG_proc, "sane_control_option: enter, option %d, action %d\n", option, action); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_INVAL; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_CUSTOM_GAMMA: case OPT_PREVIEW: *(SANE_Word *) val = dev->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_HALFTONE_PATTERN: strcpy (val, dev->val[option].s); return SANE_STATUS_GOOD; /* Gamma */ case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (val, dev->val[option].wa, dev->opt[option].size); return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option, not settable\n"); 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) { /* Numeric side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* Numeric side-effect free options */ case OPT_PREVIEW: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* String side-effect options */ 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_Char *) strdup (val); dev->opt[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, BLACK_WHITE_STR) == 0) { i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == NULL) { dev->scan_mode = LEO_BW; } else { dev->scan_mode = LEO_HALFTONE; } dev->depth = 1; dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, GRAY_STR) == 0) { dev->scan_mode = LEO_GRAYSCALE; dev->depth = 8; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } } else if (strcmp (dev->val[OPT_MODE].s, COLOR_STR) == 0) { dev->scan_mode = LEO_COLOR; dev->depth = 8; dev->opt[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE; if (dev->val[OPT_CUSTOM_GAMMA].w) { dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_HALFTONE_PATTERN: free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); i = get_string_list_index (halftone_pattern_list, dev->val[OPT_HALFTONE_PATTERN].s); if (halftone_pattern_val[i] == NULL) { dev->scan_mode = LEO_BW; } else { dev->scan_mode = LEO_HALFTONE; } return SANE_STATUS_GOOD; case OPT_GAMMA_VECTOR_R: case OPT_GAMMA_VECTOR_G: case OPT_GAMMA_VECTOR_B: case OPT_GAMMA_VECTOR_GRAY: memcpy (dev->val[option].wa, val, dev->opt[option].size); return SANE_STATUS_GOOD; case OPT_CUSTOM_GAMMA: dev->val[OPT_CUSTOM_GAMMA].w = *(SANE_Word *) val; if (dev->val[OPT_CUSTOM_GAMMA].w) { /* use custom_gamma_table */ if (dev->scan_mode == LEO_GRAYSCALE) { dev->opt[OPT_GAMMA_VECTOR_GRAY].cap &= ~SANE_CAP_INACTIVE; } else { /* color mode */ dev->opt[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE; } } else { dev->opt[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA_VECTOR_GRAY].cap |= SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *value, SANE_Int * info) { SANE_Int myinfo = 0; SANE_Status status; DBG (127, "control_option(handle=%p,opt=%s,act=%s,val=%p,info=%p)\n", handle, sod[option].title, (action == SANE_ACTION_SET_VALUE ? "SET" : (action == SANE_ACTION_GET_VALUE ? "GET" : "SETAUTO")), value, (void *)info); if (handle != MAGIC || !is_open) return SANE_STATUS_INVAL; /* Unknown handle ... */ if (option < 0 || option >= NELEMS (sod)) return SANE_STATUS_INVAL; /* Unknown option ... */ switch (action) { case SANE_ACTION_SET_VALUE: status = sanei_constrain_value (sod + option, value, &myinfo); if (status != SANE_STATUS_GOOD) { DBG (1, "Constraint error in control_option\n"); return status; } switch (option) { case DC210_OPT_IMAGE_NUMBER: Camera.current_picture_number = *(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; /* get the image's resolution */ if (Camera.Pictures[Camera.current_picture_number - 1].low_res) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } break; case DC210_OPT_THUMBS: dc210_opt_thumbnails = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (dc210_opt_thumbnails) { /* * DC210 thumbnail are 96x72x8x3 */ parms.bytes_per_line = 96 * 3; parms.pixels_per_line = 96; parms.lines = 72; } else { if (Camera.Pictures[Camera.current_picture_number - 1].low_res) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } } break; case DC210_OPT_SNAP: dc210_opt_snap = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; /* if we are snapping a new one */ if (dc210_opt_snap) { /* activate the resolution setting */ sod[DC210_OPT_LOWRES].cap &= ~SANE_CAP_INACTIVE; /* and de-activate the image number selector */ sod[DC210_OPT_IMAGE_NUMBER].cap |= SANE_CAP_INACTIVE; } else { /* deactivate the resolution setting */ sod[DC210_OPT_LOWRES].cap |= SANE_CAP_INACTIVE; /* and activate the image number selector */ sod[DC210_OPT_IMAGE_NUMBER].cap &= ~SANE_CAP_INACTIVE; } /* set params according to resolution settings */ if (dc210_opt_lowres) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } break; case DC210_OPT_LOWRES: dc210_opt_lowres = !!*(SANE_Word *) value; myinfo |= SANE_INFO_RELOAD_PARAMS; if (!dc210_opt_thumbnails) { /* XXX - change the number of pictures left depending on resolution perhaps just call get_info again? */ if (dc210_opt_lowres) { parms.bytes_per_line = 640 * 3; parms.pixels_per_line = 640; parms.lines = 480; } else { parms.bytes_per_line = 1152 * 3; parms.pixels_per_line = 1152; parms.lines = 864; } } break; case DC210_OPT_ERASE: dc210_opt_erase = !!*(SANE_Word *) value; break; case DC210_OPT_DEFAULT: DBG (1, "Fixme: Set all defaults here!\n"); break; case DC210_OPT_INIT_DC210: if ((Camera.fd = init_dc210 (&Camera)) == -1) { return SANE_STATUS_INVAL; } break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_GET_VALUE: switch (option) { case 0: *(SANE_Word *) value = NELEMS (sod); break; case DC210_OPT_IMAGE_NUMBER: *(SANE_Word *) value = Camera.current_picture_number; break; case DC210_OPT_THUMBS: *(SANE_Word *) value = dc210_opt_thumbnails; break; case DC210_OPT_SNAP: *(SANE_Word *) value = dc210_opt_snap; break; case DC210_OPT_LOWRES: *(SANE_Word *) value = dc210_opt_lowres; break; case DC210_OPT_ERASE: *(SANE_Word *) value = dc210_opt_erase; break; default: return SANE_STATUS_INVAL; } break; case SANE_ACTION_SET_AUTO: switch (option) { default: return SANE_STATUS_UNSUPPORTED; /* We are DUMB */ } } if (info) *info = myinfo; return SANE_STATUS_GOOD; }
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; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Ibm_Scanner *s = handle; SANE_Status status; SANE_Word cap; DBG (11, ">> sane_control_option\n"); if (info) *info = 0; if (s->scanning) return (SANE_STATUS_DEVICE_BUSY); if (option >= NUM_OPTIONS) return (SANE_STATUS_INVAL); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return (SANE_STATUS_INVAL); if (action == SANE_ACTION_GET_VALUE) { DBG (11, "sane_control_option get_value\n"); switch (option) { /* word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: *(SANE_Word *) val = s->val[option].w; return (SANE_STATUS_GOOD); /* bool options: */ case OPT_ADF: *(SANE_Bool *) val = s->val[option].b; return (SANE_STATUS_GOOD); /* string options: */ case OPT_MODE: case OPT_PAPER: strcpy (val, s->val[option].s); return (SANE_STATUS_GOOD); } } else { DBG (11, "sane_control_option set_value\n"); if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return (SANE_STATUS_INVAL); status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* (mostly) side-effect-free word options: */ case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: if (info && s->val[option].w != *(SANE_Word *) val) *info |= SANE_INFO_RELOAD_PARAMS; s->val[option].w = *(SANE_Word *) val; /* resets the paper format to user defined */ if (strcmp(s->val[OPT_PAPER].s, paper_list[IBM_PAPER_USER_DEFINED]) != 0) { if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[OPT_PAPER].s) free (s->val[OPT_PAPER].s); s->val[OPT_PAPER].s = strdup (paper_list[IBM_PAPER_USER_DEFINED]); } return (SANE_STATUS_GOOD); case OPT_NUM_OPTS: case OPT_BRIGHTNESS: case OPT_CONTRAST: s->val[option].w = *(SANE_Word *) val; return (SANE_STATUS_GOOD); case OPT_MODE: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return (SANE_STATUS_GOOD); case OPT_ADF: s->val[option].b = *(SANE_Bool *) val; if (*(SANE_Bool *) val) s->adf_state = ADF_ARMED; else s->adf_state = ADF_UNUSED; return (SANE_STATUS_GOOD); case OPT_PAPER: if (info && strcmp (s->val[option].s, (SANE_String) val)) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (strcmp (s->val[OPT_PAPER].s, "User") != 0) { s->val[OPT_TL_X].w = 0; s->val[OPT_TL_Y].w = 0; if (strcmp (s->val[OPT_PAPER].s, "A3") == 0) { s->val[OPT_BR_X].w = PAPER_A3_W; s->val[OPT_BR_Y].w = PAPER_A3_H; } else if (strcmp (s->val[OPT_PAPER].s, "A4") == 0) { s->val[OPT_BR_X].w = PAPER_A4_W; s->val[OPT_BR_Y].w = PAPER_A4_H; } else if (strcmp (s->val[OPT_PAPER].s, "A4R") == 0) { s->val[OPT_BR_X].w = PAPER_A4R_W; s->val[OPT_BR_Y].w = PAPER_A4R_H; } else if (strcmp (s->val[OPT_PAPER].s, "A5") == 0) { s->val[OPT_BR_X].w = PAPER_A5_W; s->val[OPT_BR_Y].w = PAPER_A5_H; } else if (strcmp (s->val[OPT_PAPER].s, "A5R") == 0) { s->val[OPT_BR_X].w = PAPER_A5R_W; s->val[OPT_BR_Y].w = PAPER_A5R_H; } else if (strcmp (s->val[OPT_PAPER].s, "A6") == 0) { s->val[OPT_BR_X].w = PAPER_A6_W; s->val[OPT_BR_Y].w = PAPER_A6_H; } else if (strcmp (s->val[OPT_PAPER].s, "B4") == 0) { s->val[OPT_BR_X].w = PAPER_B4_W; s->val[OPT_BR_Y].w = PAPER_B4_H; } else if (strcmp (s->val[OPT_PAPER].s, "Legal") == 0) { s->val[OPT_BR_X].w = PAPER_LEGAL_W; s->val[OPT_BR_Y].w = PAPER_LEGAL_H; } else if (strcmp (s->val[OPT_PAPER].s, "Letter") == 0) { s->val[OPT_BR_X].w = PAPER_LETTER_W; s->val[OPT_BR_Y].w = PAPER_LETTER_H; } } return (SANE_STATUS_GOOD); } } } DBG (11, "<< sane_control_option\n"); return (SANE_STATUS_INVAL); }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { Abaton_Scanner *s = handle; SANE_Status status; SANE_Word cap; if (option < 0 || option >= NUM_OPTIONS) return SANE_STATUS_INVAL; if (info != NULL) *info = 0; if (s->scanning) return SANE_STATUS_DEVICE_BUSY; cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) return SANE_STATUS_INVAL; if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_X_RESOLUTION: case OPT_Y_RESOLUTION: case OPT_RESOLUTION_BIND: case OPT_PREVIEW: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_NEGATIVE: case OPT_MIRROR: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_HALFTONE_PATTERN: status = sanei_constrain_value (s->opt + option, s->val[option].s, info); strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) return SANE_STATUS_INVAL; status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) return status; switch (option) { /* resolution should be uniform for previews, or when the user says so. */ case OPT_PREVIEW: s->val[option].w = *(SANE_Word *) val; if (*(SANE_Word *) val) { s->val[OPT_Y_RESOLUTION].w = s->val[OPT_X_RESOLUTION].w; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } /* always recalculate! */ calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_RESOLUTION_BIND: s->val[option].w = *(SANE_Word *) val; if (*(SANE_Word *) val) { s->val[OPT_Y_RESOLUTION].w = s->val[OPT_X_RESOLUTION].w; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; } return SANE_STATUS_GOOD; case OPT_X_RESOLUTION: if (s->val[OPT_PREVIEW].w || s->val[OPT_RESOLUTION_BIND].w) { s->val[OPT_Y_RESOLUTION].w = *(SANE_Word *)val; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } s->val[option].w = *(SANE_Word *) val; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_Y_RESOLUTION: if (s->val[OPT_PREVIEW].w || s->val[OPT_RESOLUTION_BIND].w) { s->val[OPT_X_RESOLUTION].w = *(SANE_Word *)val; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } s->val[option].w = *(SANE_Word *) val; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* these ones don't have crazy side effects */ case OPT_TL_X: case OPT_TL_Y: case OPT_BR_Y: s->val[option].w = *(SANE_Word *) val; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; /* this one is somewhat imprecise */ case OPT_BR_X: s->val[option].w = *(SANE_Word *) val; calc_parameters (s); if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_INEXACT; return SANE_STATUS_GOOD; /* no side-effects whatsoever */ case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_THRESHOLD: case OPT_NEGATIVE: case OPT_MIRROR: s->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; /* string options */ case OPT_HALFTONE_PATTERN: if (info) *info |= SANE_INFO_RELOAD_OPTIONS; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); return SANE_STATUS_GOOD; case OPT_MODE: status = mode_update (s, val); if (status != SANE_STATUS_GOOD) return status; if (s->val[option].s) free (s->val[option].s); s->val[option].s = strdup (val); if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; } /* End of switch */ } /* End of SET_VALUE */ return SANE_STATUS_INVAL; }
/** * Gets or sets an option value. * * From the SANE spec: * This function is used to set or inquire the current value of option * number n of the device represented by handle h. The manner in which * the option is controlled is specified by parameter action. The * possible values of this parameter are described in more detail * below. The value of the option is passed through argument val. It * is a pointer to the memory that holds the option value. The memory * area pointed to by v must be big enough to hold the entire option * value (determined by member size in the corresponding option * descriptor). * * The only exception to this rule is that when setting the value of a * string option, the string pointed to by argument v may be shorter * since the backend will stop reading the option value upon * encountering the first NUL terminator in the string. If argument i * is not NULL, the value of *i will be set to provide details on how * well the request has been met. */ SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { struct scanner *s = (struct scanner *) handle; SANE_Int dummy = 0; /* Make sure that all those statements involving *info cannot break (better * than having to do "if (info) ..." everywhere!) */ if (info == 0) info = &dummy; if (option >= NUM_OPTIONS) { DBG (5, "sane_control_option: %d too big\n", option); return SANE_STATUS_INVAL; } if (!SANE_OPTION_IS_ACTIVE (s->opt[option].cap)) { DBG (5, "sane_control_option: %d inactive\n", option); return SANE_STATUS_INVAL; } /* * SANE_ACTION_GET_VALUE: We have to find out the current setting and * return it in a human-readable form (often, text). */ if (action == SANE_ACTION_GET_VALUE) { SANE_Word * val_p = (SANE_Word *) val; DBG (20, "sane_control_option: get value for '%s' (%d)\n", s->opt[option].name,option); switch (option) { case OPT_NUM_OPTS: *val_p = NUM_OPTIONS; return SANE_STATUS_GOOD; case OPT_MODE: if(s->mode == MODE_GRAYSCALE){ strcpy (val, STRING_GRAYSCALE); } else if(s->mode == MODE_COLOR){ strcpy (val, STRING_COLOR); } return SANE_STATUS_GOOD; } } else if (action == SANE_ACTION_SET_VALUE) { int tmp; SANE_Status status; DBG (20, "sane_control_option: set value for '%s' (%d)\n", s->opt[option].name,option); if ( s->started ) { DBG (5, "sane_control_option: cant set, device busy\n"); return SANE_STATUS_DEVICE_BUSY; } if (!SANE_OPTION_IS_SETTABLE (s->opt[option].cap)) { DBG (5, "sane_control_option: not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (5, "sane_control_option: bad value\n"); return status; } /* * Note - for those options which can assume one of a list of * valid values, we can safely assume that they will have * exactly one of those values because that's what * sanei_constrain_value does. Hence no "else: invalid" branches * below. */ switch (option) { /* Mode Group */ case OPT_MODE: if (!strcmp (val, STRING_GRAYSCALE)) { tmp = MODE_GRAYSCALE; } else{ tmp = MODE_COLOR; } if (tmp == s->mode) return SANE_STATUS_GOOD; s->mode = tmp; *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; } /* switch */ } /* else */ return SANE_STATUS_INVAL; }
SANE_Status sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { V4L_Scanner *s = handle; SANE_Status status; SANE_Word cap; if (info) *info = 0; if (option >= NUM_OPTIONS || option < 0) return SANE_STATUS_INVAL; DBG (4, "sane_control_option: %s option %d (%s)\n", action == SANE_ACTION_GET_VALUE ? "get" : action == SANE_ACTION_SET_VALUE ? "set" : action == SANE_ACTION_SET_AUTO ? "auto set" : "(unknow action with)", option, s->opt[option].name ? s->opt[option].name : s->opt[option].title); cap = s->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { DBG (1, "sane_control option: option is inactive\n"); return SANE_STATUS_INVAL; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options: */ case OPT_NUM_OPTS: case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: case OPT_BRIGHTNESS: case OPT_HUE: case OPT_COLOR: case OPT_CONTRAST: case OPT_WHITE_LEVEL: *(SANE_Word *) val = s->val[option].w; return SANE_STATUS_GOOD; case OPT_CHANNEL: /* string list options */ case OPT_MODE: strcpy (val, s->val[option].s); return SANE_STATUS_GOOD; default: DBG (1, "sane_control_option: option %d unknown\n", option); } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (1, "sane_control_option: option is not settable\n"); return SANE_STATUS_INVAL; } status = sanei_constrain_value (s->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (1, "sane_control_option: sanei_constarin_value failed: %s\n", sane_strstatus (status)); return status; } if (option >= OPT_TL_X && option <= OPT_BR_Y) { s->user_corner |= 1 << (option - OPT_TL_X); if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed " "(can not get window geometry)\n"); return SANE_STATUS_INVAL; } s->window.clipcount = 0; s->window.clips = 0; s->window.height = parms.lines; s->window.width = parms.pixels_per_line; } switch (option) { /* (mostly) side-effect-free word options: */ case OPT_TL_X: break; case OPT_TL_Y: break; case OPT_BR_X: s->window.width = *(SANE_Word *) val; parms.pixels_per_line = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_BR_Y: s->window.height = *(SANE_Word *) val; parms.lines = *(SANE_Word *) val; if (info) *info |= SANE_INFO_RELOAD_PARAMS; break; case OPT_MODE: if (info) *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; if (strcmp (s->val[option].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) s->pict.palette = VIDEO_PALETTE_GREY; else s->pict.palette = VIDEO_PALETTE_RGB24; update_parameters (s); break; case OPT_BRIGHTNESS: s->pict.brightness = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_HUE: s->pict.hue = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_COLOR: s->pict.colour = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_CONTRAST: s->pict.contrast = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_WHITE_LEVEL: s->pict.whiteness = *(SANE_Word *) val *256; s->val[option].w = *(SANE_Word *) val; break; case OPT_CHANNEL: { int i; struct video_channel channel; s->val[option].s = strdup (val); if (!s->val[option].s) return SANE_STATUS_NO_MEM; for (i = 0; i < MAX_CHANNELS; i++) { if (strcmp (s->channel[i], val) == 0) { channel.channel = i; if (-1 == v4l1_ioctl (s->fd, VIDIOCGCHAN, &channel)) { DBG (1, "sane_open: can't ioctl VIDIOCGCHAN %s: %s\n", s->devicename, strerror (errno)); return SANE_STATUS_INVAL; } if (-1 == v4l1_ioctl (s->fd, VIDIOCSCHAN, &channel)) { DBG (1, "sane_open: can't ioctl VIDIOCSCHAN %s: %s\n", s->devicename, strerror (errno)); return SANE_STATUS_INVAL; } break; } } return SANE_STATUS_GOOD; break; } default: DBG (1, "sane_control_option: option %d unknown\n", option); return SANE_STATUS_INVAL; } if (option >= OPT_TL_X && option <= OPT_BR_Y) { if (-1 == v4l1_ioctl (s->fd, VIDIOCSWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCSWIN failed (%s)\n", strerror (errno)); /* return SANE_STATUS_INVAL; */ } if (-1 == v4l1_ioctl (s->fd, VIDIOCGWIN, &s->window)) { DBG (1, "sane_control_option: ioctl VIDIOCGWIN failed (%s)\n", strerror (errno)); return SANE_STATUS_INVAL; } } if (option >= OPT_BRIGHTNESS && option <= OPT_WHITE_LEVEL) { if (-1 == v4l1_ioctl (s->fd, VIDIOCSPICT, &s->pict)) { DBG (1, "sane_control_option: ioctl VIDIOCSPICT failed (%s)\n", strerror (errno)); /* return SANE_STATUS_INVAL; */ } } return SANE_STATUS_GOOD; } else if (action == SANE_ACTION_SET_AUTO) { if (!(cap & SANE_CAP_AUTOMATIC)) { DBG (1, "sane_control_option: option can't be set automatically\n"); return SANE_STATUS_INVAL; } switch (option) { case OPT_BRIGHTNESS: /* not implemented yet */ return SANE_STATUS_GOOD; default: break; } } return SANE_STATUS_INVAL; }