summaryrefslogtreecommitdiff
path: root/backend/epson2.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/epson2.c')
-rw-r--r--backend/epson2.c141
1 files changed, 92 insertions, 49 deletions
diff --git a/backend/epson2.c b/backend/epson2.c
index e6f6786..a15a620 100644
--- a/backend/epson2.c
+++ b/backend/epson2.c
@@ -138,12 +138,6 @@ static const SANE_String_Const film_list[] = {
NULL
};
-static const SANE_String_Const focus_list[] = {
- SANE_I18N("Focus on glass"),
- SANE_I18N("Focus 2.5mm above glass"),
- NULL
-};
-
#define HALFTONE_NONE 0x01
#define HALFTONE_TET 0x03
@@ -239,7 +233,7 @@ enum {
* Gamma correction:
* The A and B level scanners work differently than the D level scanners,
* therefore I define two different sets of arrays, plus one set of
- * variables that get set to the actally used params and list arrays at runtime.
+ * variables that get set to the actually used params and list arrays at runtime.
*/
static int gamma_params_ab[] = {
@@ -302,12 +296,11 @@ static const SANE_String_Const bay_list[] = {
};
/* minimum, maximum, quantization */
+static const SANE_Range focus_range = { 0, 254, 0 };
static const SANE_Range u8_range = { 0, 255, 0 };
static const SANE_Range fx_range = { SANE_FIX(-2.0), SANE_FIX(2.0), 0 };
-
static const SANE_Range outline_emphasis_range = { -2, 2, 0 };
-
/*
* List of pointers to devices - will be dynamically allocated depending
* on the number of devices found.
@@ -813,10 +806,11 @@ attach_one_pio(const char *dev)
}
static SANE_Status
-attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
+attach_one_config(SANEI_Config __sane_unused__ *config, const char *line,
+ void *data)
{
int vendor, product;
-
+ SANE_Bool local_only = *(SANE_Bool*) data;
int len = strlen(line);
DBG(7, "%s: len = %d, line = %s\n", __func__, len, line);
@@ -847,13 +841,16 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)
} else if (strncmp(line, "net", 3) == 0) {
- /* remove the "net" sub string */
- const char *name = sanei_config_skip_whitespace(line + 3);
+ if (!local_only) {
+ /* remove the "net" sub string */
+ const char *name =
+ sanei_config_skip_whitespace(line + 3);
- if (strncmp(name, "autodiscovery", 13) == 0)
- e2_network_discovery();
- else
- attach_one_net(name);
+ if (strncmp(name, "autodiscovery", 13) == 0)
+ e2_network_discovery();
+ else
+ attach_one_net(name);
+ }
} else if (strncmp(line, "pio", 3) == 0) {
@@ -889,14 +886,14 @@ free_devices(void)
}
static void
-probe_devices(void)
+probe_devices(SANE_Bool local_only)
{
DBG(5, "%s\n", __func__);
free_devices();
sanei_configure_attach(EPSON2_CONFIG_FILE, NULL,
- attach_one_config);
+ attach_one_config, &local_only);
}
SANE_Status
@@ -926,14 +923,14 @@ sane_exit(void)
}
SANE_Status
-sane_get_devices(const SANE_Device ***device_list, SANE_Bool __sane_unused__ local_only)
+sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)
{
Epson_Device *dev;
int i;
DBG(5, "%s\n", __func__);
- probe_devices();
+ probe_devices(local_only);
devlist = malloc((num_devices + 1) * sizeof(devlist[0]));
if (!devlist) {
@@ -1336,6 +1333,39 @@ init_options(Epson_Scanner *s)
s->opt[OPT_BR_Y].constraint.range = s->hw->y_range;
s->val[OPT_BR_Y].w = s->hw->y_range->max;
+ /* "Focus" group: */
+ s->opt[OPT_FOCUS_GROUP].title = SANE_I18N("Focus");
+ s->opt[OPT_FOCUS_GROUP].desc = "";
+ s->opt[OPT_FOCUS_GROUP].type = SANE_TYPE_GROUP;
+ s->opt[OPT_FOCUS_GROUP].cap = SANE_CAP_ADVANCED;
+
+ /* autofocus */
+ s->opt[OPT_AUTOFOCUS].name = SANE_NAME_AUTOFOCUS;
+ s->opt[OPT_AUTOFOCUS].title = SANE_TITLE_AUTOFOCUS;
+ s->opt[OPT_AUTOFOCUS].desc = SANE_DESC_AUTOFOCUS;
+ s->opt[OPT_AUTOFOCUS].type = SANE_TYPE_BOOL;
+ s->val[OPT_AUTOFOCUS].w = SANE_FALSE;
+ s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_ADVANCED;
+
+ /* focus position */
+ s->opt[OPT_FOCUS_POS].name = SANE_NAME_FOCUS;
+ s->opt[OPT_FOCUS_POS].title = SANE_TITLE_FOCUS;
+ s->opt[OPT_FOCUS_POS].desc = SANE_DESC_FOCUS;
+ s->opt[OPT_FOCUS_POS].type = SANE_TYPE_INT;
+ s->opt[OPT_FOCUS_POS].unit = SANE_UNIT_NONE;
+ s->opt[OPT_FOCUS_POS].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_FOCUS_POS].constraint.range = &focus_range;
+ s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
+ s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_ADVANCED;
+
+ if (s->hw->focusSupport == SANE_TRUE) {
+ s->opt[OPT_FOCUS_POS].cap &= ~SANE_CAP_INACTIVE;
+ s->opt[OPT_AUTOFOCUS].cap &= ~SANE_CAP_INACTIVE;
+ } else {
+ s->opt[OPT_FOCUS_POS].cap |= SANE_CAP_INACTIVE;
+ s->opt[OPT_AUTOFOCUS].cap |= SANE_CAP_INACTIVE;
+ }
+
/* "Optional equipment" group: */
s->opt[OPT_EQU_GROUP].title = SANE_I18N("Optional equipment");
s->opt[OPT_EQU_GROUP].desc = "";
@@ -1372,22 +1402,6 @@ init_options(Epson_Scanner *s)
if (!s->hw->cmd->set_bay)
s->opt[OPT_FILM_TYPE].cap |= SANE_CAP_INACTIVE;
- /* focus position */
- s->opt[OPT_FOCUS].name = SANE_EPSON_FOCUS_NAME;
- s->opt[OPT_FOCUS].title = SANE_EPSON_FOCUS_TITLE;
- s->opt[OPT_FOCUS].desc = SANE_EPSON_FOCUS_DESC;
- s->opt[OPT_FOCUS].type = SANE_TYPE_STRING;
- s->opt[OPT_FOCUS].size = max_string_size(focus_list);
- s->opt[OPT_FOCUS].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- s->opt[OPT_FOCUS].constraint.string_list = focus_list;
- s->val[OPT_FOCUS].w = 0;
- s->opt[OPT_FOCUS].cap |= SANE_CAP_ADVANCED;
-
- if (s->hw->focusSupport == SANE_TRUE)
- s->opt[OPT_FOCUS].cap &= ~SANE_CAP_INACTIVE;
- else
- s->opt[OPT_FOCUS].cap |= SANE_CAP_INACTIVE;
-
/* forward feed / eject */
s->opt[OPT_EJECT].name = "eject";
s->opt[OPT_EJECT].title = SANE_I18N("Eject");
@@ -1470,7 +1484,7 @@ sane_open(SANE_String_Const name, SANE_Handle *handle)
/* probe if empty device name provided */
if (l == 0) {
- probe_devices();
+ probe_devices(SANE_FALSE);
if (first_dev == NULL) {
DBG(1, "no device detected\n");
@@ -1507,7 +1521,7 @@ sane_open(SANE_String_Const name, SANE_Handle *handle)
*/
if (first_dev == NULL)
- probe_devices();
+ probe_devices(SANE_FALSE);
s = device_detect(name, SANE_EPSON_NODEV, 0, &status);
if (s == NULL) {
@@ -1646,6 +1660,8 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
case OPT_THRESHOLD:
case OPT_BIT_DEPTH:
case OPT_WAIT_FOR_BUTTON:
+ case OPT_AUTOFOCUS:
+ case OPT_FOCUS_POS:
*((SANE_Word *) value) = sval->w;
break;
@@ -1659,7 +1675,6 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
case OPT_GAMMA_CORRECTION:
case OPT_COLOR_CORRECTION:
case OPT_BAY:
- case OPT_FOCUS:
strcpy((char *) value, sopt->constraint.string_list[sval->w]);
break;
@@ -1730,8 +1745,6 @@ change_source(Epson_Scanner *s, SANE_Int optindex, char *value)
if (s->hw->need_reset_on_source_change)
esci_reset(s);
- s->focusOnGlass = SANE_TRUE; /* this is the default */
-
if (s->val[OPT_SOURCE].w == optindex)
return;
@@ -1750,7 +1763,7 @@ change_source(Epson_Scanner *s, SANE_Int optindex, char *value)
s->hw->use_extension = SANE_TRUE;
/* disable film type option */
deactivateOption(s, OPT_FILM_TYPE, &dummy);
- s->val[OPT_FOCUS].w = 0;
+ s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
if (s->hw->duplex) {
activateOption(s, OPT_ADF_MODE, &dummy);
} else {
@@ -1782,10 +1795,8 @@ change_source(Epson_Scanner *s, SANE_Int optindex, char *value)
deactivateOption(s, OPT_FILM_TYPE, &dummy);
/* enable focus position if the scanner supports it */
- if (s->hw->cmd->set_focus_position != 0) {
- s->val[OPT_FOCUS].w = 1;
- s->focusOnGlass = SANE_FALSE;
- }
+ if (s->hw->focusSupport)
+ s->val[OPT_FOCUS_POS].w = FOCUS_ABOVE_25MM;
deactivateOption(s, OPT_ADF_MODE, &dummy);
deactivateOption(s, OPT_EJECT, &dummy);
@@ -1798,7 +1809,7 @@ change_source(Epson_Scanner *s, SANE_Int optindex, char *value)
/* disable film type option */
deactivateOption(s, OPT_FILM_TYPE, &dummy);
- s->val[OPT_FOCUS].w = 0;
+ s->val[OPT_FOCUS_POS].w = FOCUS_ON_GLASS;
deactivateOption(s, OPT_ADF_MODE, &dummy);
}
@@ -1872,7 +1883,6 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
case OPT_DROPOUT:
case OPT_FILM_TYPE:
case OPT_BAY:
- case OPT_FOCUS:
sval->w = optindex; /* Simple lists */
break;
@@ -1981,6 +1991,11 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
break;
}
+ case OPT_AUTOFOCUS:
+ sval->w = *((SANE_Word *) value);
+ setOptionState(s, !sval->w, OPT_FOCUS_POS, &reload);
+ break;
+
case OPT_MIRROR:
case OPT_AAS:
case OPT_PREVIEW: /* needed? */
@@ -1989,6 +2004,7 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
case OPT_AUTO_EJECT:
case OPT_THRESHOLD:
case OPT_WAIT_FOR_BUTTON:
+ case OPT_FOCUS_POS:
sval->w = *((SANE_Word *) value);
break;
@@ -2122,6 +2138,27 @@ sane_start(SANE_Handle handle)
if (status != SANE_STATUS_GOOD)
return status;
+ /*
+ * set focus after we set scanning parameters because the scanner will
+ * use the middle of the scanning area for autofocus. If we want to
+ * support a defined x,y position for autofocus, we'd need to send
+ * specific scanning paramters just for autofocus.
+ */
+ if (s->hw->focusSupport == SANE_TRUE) {
+ if (s->val[OPT_AUTOFOCUS].w) {
+ DBG(1, "setting autofocus\n");
+ status = esci_set_focus_position(s, 0xff);
+ } else {
+ DBG(1, "setting focus to %u\n", s->val[OPT_FOCUS_POS].w);
+ status = esci_set_focus_position(s, s->val[OPT_FOCUS_POS].w);
+ }
+
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "setting focus failed\n");
+ return status;
+ }
+ }
+
/* ESC z, user defined gamma table */
if (dev->cmd->set_gamma_table
&& gamma_userdefined[s->val[OPT_GAMMA_CORRECTION].w]) {
@@ -2227,6 +2264,12 @@ sane_start(SANE_Handle handle)
if (status != SANE_STATUS_GOOD)
return status;
+ if (s->hw->focusSupport == SANE_TRUE && s->val[OPT_AUTOFOCUS].w) {
+ status = esci_request_focus_position(s, &s->currentFocusPosition);
+ if (status == SANE_STATUS_GOOD)
+ s->val[OPT_FOCUS_POS].w = s->currentFocusPosition;
+ }
+
/* start scanning */
DBG(1, "%s: scanning...\n", __func__);