Merge branch '646-scanimage-hangs-on-exit' into 'master'

Resolve "scanimage hangs on exit"

See merge request sane-project/backends!783
666-epsonds-has-issues-with-saned
Ralph Little 2023-02-20 20:31:18 +00:00
commit 8ac72560ff
3 zmienionych plików z 310 dodań i 123 usunięć

Wyświetl plik

@ -3769,7 +3769,7 @@ static SANE_Status
get_accessories_info (Avision_Scanner* s) get_accessories_info (Avision_Scanner* s)
{ {
Avision_Device* dev = s->hw; Avision_Device* dev = s->hw;
int try = 3; int try = 1;
/* read stuff */ /* read stuff */
struct command_read rcmd; struct command_read rcmd;
@ -3811,47 +3811,84 @@ get_accessories_info (Avision_Scanner* s)
result [2], result [2],
adf_model[ (result[2] < adf_models) ? result[2] : adf_models ]); adf_model[ (result[2] < adf_models) ? result[2] : adf_models ]);
dev->inquiry_adf |= result [0]; /*
* Cope with ADF presence flag being present but the device *not* reporting
* ADF capability. Maybe there are some devices that do that? [RL]
*
*/
dev->inquiry_adf_present = result [0];
/*
* Note: this feature_type check is a bit of a hack.
* Only the HP Scanjet 8200 series supports this so it is code
* specific to this family of scanners. [RL]
*
*/
if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) if (dev->hw->feature_type & AV_ADF_FLIPPING_DUPLEX)
{ {
if (result[0] == 1) if (result[0] == 1)
{ {
dev->inquiry_duplex = 1; dev->inquiry_duplex = 1;
dev->inquiry_duplex_interlaced = 0; dev->inquiry_duplex_interlaced = 0;
} else if (result[0] == 0 && result[2] != 0 && !skip_adf) { }
else if (result[0] == 0 && result[2] != 0 && !skip_adf)
{
/* Sometimes the scanner will report that there is no ADF attached, yet /* Sometimes the scanner will report that there is no ADF attached, yet
* an ADF model number will still be reported. This happens on the * an ADF model number will still be reported. This happens on the
* HP8200 series and possibly others. In this case we need to reset the * HP8200 series and possibly others. In this case we need to reset the
* the adf and try reading it again. Skip this if the configuration says * the adf and try reading it again. Skip this if the configuration says
* to do so, so that we don't fail out the scanner as being broken and * to do so, so that we don't fail out the scanner as being broken and
* unsupported if there isn't actually an ADF present. * unsupported if there isn't actually an ADF present.
*
* Note further: Some models (like the ScanJet 8300) report that they have ADF
* *capability* in the INQUIRY response but that doesn't necessarily mean that
* an ADF is plugged in. In my case it has the lightbox accessory instead and
* result[0] == FALSE.
* Trying to reset the ADF 3 times is excessive and takes an unreasonable amount
* of time on the 8300 with no ADF plugged in, so let's do it just once and if
* it fails to report presence, then don't assume it is an error, just that
* there is no ADF. [RL]
*
*/ */
DBG (3, "get_accessories_info: Found ADF model number but the ADF-present flag is not set. Trying to recover...\n"); if (!try)
{
DBG (
1,
"get_accessories_info: Maximum retries attempted, ADF unresponsive.\n");
dev->inquiry_adf_present = SANE_FALSE;
//return SANE_STATUS_UNSUPPORTED;
}
else
{
try--;
DBG(3,
"get_accessories_info: Found ADF model number but the ADF-present flag is not set. "
"Trying to reset the ADF just in case it is there but unresponsive...\n");
status = adf_reset (s); status = adf_reset (s);
if (status != SANE_STATUS_GOOD) { if (status != SANE_STATUS_GOOD)
{
DBG (3, "get_accessories_info: Failed to reset ADF: %s\n", sane_strstatus (status)); DBG (3, "get_accessories_info: Failed to reset ADF: %s\n", sane_strstatus (status));
return status; return status;
} }
DBG(1,"get_accessories_info: Waiting while ADF firmware resets...\n"); DBG(1,"get_accessories_info: Waiting while ADF firmware resets...\n");
sleep (3); sleep (3);
status = wait_ready (&s->av_con, 1); status = wait_ready (&s->av_con, 1);
if (status != SANE_STATUS_GOOD) { if (status != SANE_STATUS_GOOD)
DBG (1, "get_accessories_info: wait_ready() failed: %s\n", sane_strstatus (status)); {
DBG (1, "get_accessories_info: wait_ready() failed: %s\n",
sane_strstatus (status));
return status; return status;
} }
if (try) {
try--;
goto RETRY; goto RETRY;
} }
DBG (1, "get_accessories_info: Maximum retries attempted, ADF unresponsive.\n");
return SANE_STATUS_UNSUPPORTED;
} }
} }
/* only honor a 1, some scanner without adapter set 0xff */ /* only honor a 1, some scanner without adapter set 0xff */
if (result[1] == 1) if (result[1] == 1)
dev->inquiry_light_box = 1; dev->inquiry_light_box_present = 1;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -4336,33 +4373,74 @@ attach (SANE_String_Const devname, Avision_ConnectionType con_type,
model_num = 0; model_num = 0;
found = 0; found = 0;
/*
* Search for a matching device in the device list.
* Primarily we need two matches for SCSI devices.
* However, multiple USB device entries share the same
* SCSI info. For USB devices, we will also do a mandatory
* USB Product/Vendor check to pick the right one. Otherwise
* at the very least the device name is incorrect.
*
*/
SANE_Word usb_vendor = 0;
SANE_Word usb_product = 0;
if (con_type == AV_USB)
{
status = sanei_usb_get_vendor_product_byname (devname, &usb_vendor, &usb_product);
if (status != SANE_STATUS_GOOD)
{
DBG (0, "attach: Could not retrieve USB vendor nor product for USB device.\n");
status = SANE_STATUS_INVAL;
goto close_scanner_and_return;
}
}
/* while not at at end of list NULL terminator */ /* while not at at end of list NULL terminator */
while (Avision_Device_List[model_num].real_mfg != NULL || while (Avision_Device_List[model_num].real_mfg != NULL
Avision_Device_List[model_num].scsi_mfg != NULL) || Avision_Device_List[model_num].scsi_mfg != NULL)
{ {
int matches = 0, match_count = 0; /* count number of matches */ int matches = 0, match_count = 0; /* count number of matches */
DBG (1, "attach: Checking model: %d\n", model_num); DBG (1, "attach: Checking model: %d\n", model_num);
if (Avision_Device_List[model_num].scsi_mfg) { if (Avision_Device_List[model_num].scsi_mfg)
{
++match_count; ++match_count;
if (strcmp (mfg, Avision_Device_List[model_num].scsi_mfg) == 0) if (strcmp (mfg, Avision_Device_List[model_num].scsi_mfg) == 0)
++matches; ++matches;
} }
if (Avision_Device_List[model_num].scsi_model) { if (Avision_Device_List[model_num].scsi_model)
{
++match_count; ++match_count;
if (strcmp (model, Avision_Device_List[model_num].scsi_model) == 0) if (strcmp (model, Avision_Device_List[model_num].scsi_model) == 0)
++matches; ++matches;
} }
/*
* Must match on USB vendor product also for USB devices.
* We will *always* know the vendor and product for USB devices.
*
*/
if (con_type == AV_USB)
{
++match_count;
if ((Avision_Device_List[model_num].usb_product == usb_product)
&& (Avision_Device_List[model_num].usb_vendor == usb_vendor))
{
++matches;
}
}
/* we need 2 matches (mfg, model) for SCSI entries, or the ones available /* we need 2 matches (mfg, model) for SCSI entries, or the ones available
for "we know what we are looking for" USB entries */ for "we know what we are looking for" USB entries */
if ((attaching_hw == &(Avision_Device_List [model_num]) && if ((attaching_hw == &(Avision_Device_List[model_num]))
matches == match_count) || && (matches == match_count))
matches == 2)
{ {
DBG (1, "attach: Scanner matched entry: %d: \"%s\", \"%s\", 0x%.4x, 0x%.4x\n", DBG (
model_num, 1,
Avision_Device_List[model_num].scsi_mfg, "attach: Scanner matched entry: %d: \"%s\", \"%s\", 0x%.4x, 0x%.4x\n",
model_num, Avision_Device_List[model_num].scsi_mfg,
Avision_Device_List[model_num].scsi_model, Avision_Device_List[model_num].scsi_model,
Avision_Device_List[model_num].usb_vendor, Avision_Device_List[model_num].usb_vendor,
Avision_Device_List[model_num].usb_product); Avision_Device_List[model_num].usb_product);
@ -4543,7 +4621,7 @@ get_double ( &(result[48] ) ));
DBG (3, "attach: [62] scanner type:%s%s%s%s%s%s\n", DBG (3, "attach: [62] scanner type:%s%s%s%s%s%s\n",
BIT(result[62],7)?" Flatbed":"", BIT(result[62],7)?" Flatbed":"",
BIT(result[62],6)?" Roller (ADF)":"", BIT(result[62],6)?" Roller (ADF)":"",
BIT(result[62],5)?" Flatbed (ADF)":"", BIT(result[62],5)?" Flatbed (ADF/Lightbox)":"",
BIT(result[62],4)?" Roller":"", /* does not feed multiple pages, AV25 */ BIT(result[62],4)?" Roller":"", /* does not feed multiple pages, AV25 */
BIT(result[62],3)?" Film scanner":"", BIT(result[62],3)?" Film scanner":"",
BIT(result[62],2)?" Duplex":""); BIT(result[62],2)?" Duplex":"");
@ -4643,7 +4721,7 @@ get_double ( &(result[48] ) ));
dev->inquiry_nvram_read = BIT(result[52],0); dev->inquiry_nvram_read = BIT(result[52],0);
dev->inquiry_power_save_time = BIT(result[52],1); dev->inquiry_power_save_time = BIT(result[52],1);
dev->inquiry_adf = BIT (result[62], 5); dev->inquiry_adf_capability = BIT (result[62], 5);
dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5); dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5);
dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4); dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4);
/* the first avision scanners (AV3200) do not set the interlaced bit */ /* the first avision scanners (AV3200) do not set the interlaced bit */
@ -5147,10 +5225,10 @@ additional_probe (Avision_Scanner* s)
{ {
add_source_mode (dev, AV_NORMAL, "Normal"); add_source_mode (dev, AV_NORMAL, "Normal");
if (dev->inquiry_light_box) if (dev->inquiry_light_box_present)
add_source_mode (dev, AV_TRANSPARENT, "Transparency"); add_source_mode (dev, AV_TRANSPARENT, "Transparency");
if (dev->inquiry_adf) if (dev->inquiry_adf_present)
add_source_mode (dev, AV_ADF, "ADF Front"); add_source_mode (dev, AV_ADF, "ADF Front");
} }
@ -6956,7 +7034,15 @@ init_options (Avision_Scanner* s)
memset (s->opt, 0, sizeof (s->opt)); memset (s->opt, 0, sizeof (s->opt));
memset (s->val, 0, sizeof (s->val)); memset (s->val, 0, sizeof (s->val));
for (i = 0; i < NUM_OPTIONS; ++ i) { /*
* Set defaults for all the options.
*
*/
for (i = 0; i < NUM_OPTIONS; ++i)
{
s->opt[i].name = "";
s->opt[i].desc = "";
s->opt[i].unit = SANE_UNIT_NONE;
s->opt[i].size = sizeof(SANE_Word); s->opt[i].size = sizeof(SANE_Word);
s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; s->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
} }
@ -6989,9 +7075,7 @@ init_options (Avision_Scanner* s)
dev->speed_range.max = (SANE_Int)4; dev->speed_range.max = (SANE_Int)4;
dev->speed_range.quant = (SANE_Int)1; dev->speed_range.quant = (SANE_Int)1;
s->opt[OPT_NUM_OPTS].name = "";
s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
s->opt[OPT_NUM_OPTS].desc = "";
s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT); s->opt[OPT_NUM_OPTS].size = sizeof(SANE_TYPE_INT);
@ -6999,7 +7083,6 @@ init_options (Avision_Scanner* s)
/* "Mode" group: */ /* "Mode" group: */
s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MODE_GROUP].title = SANE_TITLE_SCAN_MODE;
s->opt[OPT_MODE_GROUP].desc = ""; /* for groups only title and type are valid */
s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_MODE_GROUP].cap = 0; s->opt[OPT_MODE_GROUP].cap = 0;
s->opt[OPT_MODE_GROUP].size = 0; s->opt[OPT_MODE_GROUP].size = 0;
@ -7063,7 +7146,6 @@ init_options (Avision_Scanner* s)
/* "Geometry" group: */ /* "Geometry" group: */
s->opt[OPT_GEOMETRY_GROUP].title = "Geometry"; s->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
s->opt[OPT_GEOMETRY_GROUP].desc = ""; /* for groups only title and type are valid */
s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
s->opt[OPT_GEOMETRY_GROUP].size = 0; s->opt[OPT_GEOMETRY_GROUP].size = 0;
@ -7111,8 +7193,8 @@ init_options (Avision_Scanner* s)
/* overscan top */ /* overscan top */
s->opt[OPT_OVERSCAN_TOP].name = "overscan-top"; s->opt[OPT_OVERSCAN_TOP].name = "overscan-top";
s->opt[OPT_OVERSCAN_TOP].title = "Overscan top"; s->opt[OPT_OVERSCAN_TOP].title = SANE_TITLE_OVERSCAN_TOP;
s->opt[OPT_OVERSCAN_TOP].desc = "The top overscan controls the additional area to scan before the paper is detected."; s->opt[OPT_OVERSCAN_TOP].desc = SANE_DESC_OVERSCAN_TOP;
s->opt[OPT_OVERSCAN_TOP].type = SANE_TYPE_FIXED; s->opt[OPT_OVERSCAN_TOP].type = SANE_TYPE_FIXED;
s->opt[OPT_OVERSCAN_TOP].unit = SANE_UNIT_MM; s->opt[OPT_OVERSCAN_TOP].unit = SANE_UNIT_MM;
s->opt[OPT_OVERSCAN_TOP].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVERSCAN_TOP].constraint_type = SANE_CONSTRAINT_RANGE;
@ -7121,8 +7203,8 @@ init_options (Avision_Scanner* s)
/* overscan bottom */ /* overscan bottom */
s->opt[OPT_OVERSCAN_BOTTOM].name = "overscan-bottom"; s->opt[OPT_OVERSCAN_BOTTOM].name = "overscan-bottom";
s->opt[OPT_OVERSCAN_BOTTOM].title = "Overscan bottom"; s->opt[OPT_OVERSCAN_BOTTOM].title = SANE_TITLE_OVERSCAN_BOTTOM;
s->opt[OPT_OVERSCAN_BOTTOM].desc = "The bottom overscan controls the additional area to scan after the paper end is detected."; s->opt[OPT_OVERSCAN_BOTTOM].desc = SANE_DESC_OVERSCAN_BOTTOM;
s->opt[OPT_OVERSCAN_BOTTOM].type = SANE_TYPE_FIXED; s->opt[OPT_OVERSCAN_BOTTOM].type = SANE_TYPE_FIXED;
s->opt[OPT_OVERSCAN_BOTTOM].unit = SANE_UNIT_MM; s->opt[OPT_OVERSCAN_BOTTOM].unit = SANE_UNIT_MM;
s->opt[OPT_OVERSCAN_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_OVERSCAN_BOTTOM].constraint_type = SANE_CONSTRAINT_RANGE;
@ -7136,8 +7218,8 @@ init_options (Avision_Scanner* s)
/* background raster */ /* background raster */
s->opt[OPT_BACKGROUND].name = "background-lines"; s->opt[OPT_BACKGROUND].name = "background-lines";
s->opt[OPT_BACKGROUND].title = "Background raster lines"; s->opt[OPT_BACKGROUND].title = SANE_TITLE_BACKGROUND_LINES;
s->opt[OPT_BACKGROUND].desc = "The background raster controls the additional background lines to scan before the paper is feed through the scanner."; s->opt[OPT_BACKGROUND].desc = SANE_DESC_BACKGROUND_LINES;
s->opt[OPT_BACKGROUND].type = SANE_TYPE_INT; s->opt[OPT_BACKGROUND].type = SANE_TYPE_INT;
s->opt[OPT_BACKGROUND].unit = SANE_UNIT_PIXEL; s->opt[OPT_BACKGROUND].unit = SANE_UNIT_PIXEL;
s->opt[OPT_BACKGROUND].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_BACKGROUND].constraint_type = SANE_CONSTRAINT_RANGE;
@ -7149,8 +7231,7 @@ init_options (Avision_Scanner* s)
} }
/* "Enhancement" group: */ /* "Enhancement" group: */
s->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement"; s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_TITLE_ENHANCEMENT;
s->opt[OPT_ENHANCEMENT_GROUP].desc = ""; /* for groups only title and type are valid */
s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_ENHANCEMENT_GROUP].cap = 0; s->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
s->opt[OPT_ENHANCEMENT_GROUP].size = 0; s->opt[OPT_ENHANCEMENT_GROUP].size = 0;
@ -7182,8 +7263,8 @@ init_options (Avision_Scanner* s)
/* Quality Scan */ /* Quality Scan */
s->opt[OPT_QSCAN].name = "quality-scan"; s->opt[OPT_QSCAN].name = "quality-scan";
s->opt[OPT_QSCAN].title = "Quality scan"; s->opt[OPT_QSCAN].title = SANE_TITLE_QUALITY_SCAN;
s->opt[OPT_QSCAN].desc = "Turn on quality scanning (slower but better)."; s->opt[OPT_QSCAN].desc = SANE_DESC_QUALITY_SCAN;
s->opt[OPT_QSCAN].type = SANE_TYPE_BOOL; s->opt[OPT_QSCAN].type = SANE_TYPE_BOOL;
s->opt[OPT_QSCAN].unit = SANE_UNIT_NONE; s->opt[OPT_QSCAN].unit = SANE_UNIT_NONE;
s->val[OPT_QSCAN].w = SANE_TRUE; s->val[OPT_QSCAN].w = SANE_TRUE;
@ -7262,8 +7343,8 @@ init_options (Avision_Scanner* s)
/* exposure */ /* exposure */
s->opt[OPT_EXPOSURE].name = "exposure"; s->opt[OPT_EXPOSURE].name = "exposure";
s->opt[OPT_EXPOSURE].title = "Exposure"; s->opt[OPT_EXPOSURE].title = SANE_TITLE_MANUAL_EXPOSURE;
s->opt[OPT_EXPOSURE].desc = "Manual exposure adjustment."; s->opt[OPT_EXPOSURE].desc = SANE_DESC_MANUAL_EXPOSURE;
s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT;
s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT;
s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE;
@ -7276,8 +7357,8 @@ init_options (Avision_Scanner* s)
/* Multi sample */ /* Multi sample */
s->opt[OPT_MULTISAMPLE].name = "multi-sample"; s->opt[OPT_MULTISAMPLE].name = "multi-sample";
s->opt[OPT_MULTISAMPLE].title = "Multi-sample"; s->opt[OPT_MULTISAMPLE].title = SANE_TITLE_MULTI_SAMPLE;
s->opt[OPT_MULTISAMPLE].desc = "Enable multi-sample scan mode."; s->opt[OPT_MULTISAMPLE].desc = SANE_DESC_MULTI_SAMPLE;
s->opt[OPT_MULTISAMPLE].type = SANE_TYPE_BOOL; s->opt[OPT_MULTISAMPLE].type = SANE_TYPE_BOOL;
s->opt[OPT_MULTISAMPLE].unit = SANE_UNIT_NONE; s->opt[OPT_MULTISAMPLE].unit = SANE_UNIT_NONE;
s->val[OPT_MULTISAMPLE].w = SANE_FALSE; s->val[OPT_MULTISAMPLE].w = SANE_FALSE;
@ -7289,9 +7370,9 @@ init_options (Avision_Scanner* s)
} }
/* Infra-red */ /* Infra-red */
s->opt[OPT_IR].name = "infra-red"; s->opt[OPT_IR].name = SANE_NAME_INFRARED;
s->opt[OPT_IR].title = "Infra-red"; s->opt[OPT_IR].title = SANE_TITLE_INFRARED;
s->opt[OPT_IR].desc = "Enable infra-red scan mode."; s->opt[OPT_IR].desc = SANE_DESC_INFRARED;
s->opt[OPT_IR].type = SANE_TYPE_BOOL; s->opt[OPT_IR].type = SANE_TYPE_BOOL;
s->opt[OPT_IR].unit = SANE_UNIT_NONE; s->opt[OPT_IR].unit = SANE_UNIT_NONE;
s->val[OPT_IR].w = SANE_FALSE; s->val[OPT_IR].w = SANE_FALSE;
@ -7303,16 +7384,13 @@ init_options (Avision_Scanner* s)
} }
/* "MISC" group: */ /* "MISC" group: */
s->opt[OPT_MISC_GROUP].title = SANE_TITLE_SCAN_MODE; s->opt[OPT_MISC_GROUP].title = SANE_TITLE_MISC_GROUP;
s->opt[OPT_MISC_GROUP].desc = ""; /* for groups only title and type are valid */
s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP; s->opt[OPT_MISC_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_MISC_GROUP].cap = 0; s->opt[OPT_MISC_GROUP].cap = 0;
s->opt[OPT_MISC_GROUP].size = 0; s->opt[OPT_MISC_GROUP].size = 0;
s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_MISC_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
/* film holder control */ /* film holder control */
if (dev->scanner_type != AV_FILM)
s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_FRAME].name = SANE_NAME_FRAME; s->opt[OPT_FRAME].name = SANE_NAME_FRAME;
s->opt[OPT_FRAME].title = SANE_TITLE_FRAME; s->opt[OPT_FRAME].title = SANE_TITLE_FRAME;
s->opt[OPT_FRAME].desc = SANE_DESC_FRAME; s->opt[OPT_FRAME].desc = SANE_DESC_FRAME;
@ -7321,22 +7399,24 @@ init_options (Avision_Scanner* s)
s->opt[OPT_FRAME].constraint_type = SANE_CONSTRAINT_RANGE; s->opt[OPT_FRAME].constraint_type = SANE_CONSTRAINT_RANGE;
s->opt[OPT_FRAME].constraint.range = &dev->frame_range; s->opt[OPT_FRAME].constraint.range = &dev->frame_range;
s->val[OPT_FRAME].w = dev->current_frame; s->val[OPT_FRAME].w = dev->current_frame;
if (dev->scanner_type != AV_FILM)
s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE;
/* power save time */ /* power save time */
if (!dev->inquiry_power_save_time)
s->opt[OPT_POWER_SAVE_TIME].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_POWER_SAVE_TIME].name = "power-save-time"; s->opt[OPT_POWER_SAVE_TIME].name = "power-save-time";
s->opt[OPT_POWER_SAVE_TIME].title = "Power save timer control"; s->opt[OPT_POWER_SAVE_TIME].title = SANE_TITLE_POWER_SAVE_TIME;
s->opt[OPT_POWER_SAVE_TIME].desc = "Allows control of the scanner's power save timer, dimming or turning off the light."; s->opt[OPT_POWER_SAVE_TIME].desc = SANE_DESC_POWER_SAVE_TIME;
s->opt[OPT_POWER_SAVE_TIME].type = SANE_TYPE_INT; s->opt[OPT_POWER_SAVE_TIME].type = SANE_TYPE_INT;
s->opt[OPT_POWER_SAVE_TIME].unit = SANE_UNIT_NONE; s->opt[OPT_POWER_SAVE_TIME].unit = SANE_UNIT_NONE;
s->opt[OPT_POWER_SAVE_TIME].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_POWER_SAVE_TIME].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_POWER_SAVE_TIME].w = 0; s->val[OPT_POWER_SAVE_TIME].w = 0;
if (!dev->inquiry_power_save_time)
s->opt[OPT_POWER_SAVE_TIME].cap |= SANE_CAP_INACTIVE;
/* message, like options set on the scanner, LED no. & co */ /* message, like options set on the scanner, LED no. & co */
s->opt[OPT_MESSAGE].name = "message"; s->opt[OPT_MESSAGE].name = "message";
s->opt[OPT_MESSAGE].title = "message text from the scanner"; s->opt[OPT_MESSAGE].title = SANE_TITLE_OPTIONS_MSG;
s->opt[OPT_MESSAGE].desc = "This text contains device specific options controlled by the user on the scanner hardware."; s->opt[OPT_MESSAGE].desc = SANE_DESC_OPTIONS_MSG;
s->opt[OPT_MESSAGE].type = SANE_TYPE_STRING; s->opt[OPT_MESSAGE].type = SANE_TYPE_STRING;
s->opt[OPT_MESSAGE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED; s->opt[OPT_MESSAGE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
s->opt[OPT_MESSAGE].size = 129; s->opt[OPT_MESSAGE].size = 129;
@ -7345,44 +7425,73 @@ init_options (Avision_Scanner* s)
s->val[OPT_MESSAGE].s[0] = 0; s->val[OPT_MESSAGE].s[0] = 0;
/* NVRAM */ /* NVRAM */
s->opt[OPT_NVRAM].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
if (!dev->inquiry_nvram_read)
s->opt[OPT_NVRAM].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_NVRAM].name = "nvram-values"; s->opt[OPT_NVRAM].name = "nvram-values";
s->opt[OPT_NVRAM].title = "Obtain NVRAM values"; s->opt[OPT_NVRAM].title = SANE_TITLE_NVRAM;
s->opt[OPT_NVRAM].desc = "Allows access obtaining the scanner's NVRAM values as pretty printed text."; s->opt[OPT_NVRAM].desc = SANE_DESC_NVRAM;
s->opt[OPT_NVRAM].type = SANE_TYPE_STRING; s->opt[OPT_NVRAM].type = SANE_TYPE_STRING;
s->opt[OPT_NVRAM].unit = SANE_UNIT_NONE; s->opt[OPT_NVRAM].unit = SANE_UNIT_NONE;
s->opt[OPT_NVRAM].size = 1024; s->opt[OPT_NVRAM].size = 1024;
s->opt[OPT_NVRAM].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_NVRAM].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_NVRAM].s = malloc((size_t) s->opt[OPT_NVRAM].size); s->val[OPT_NVRAM].s = malloc((size_t) s->opt[OPT_NVRAM].size);
s->val[OPT_NVRAM].s[0] = 0; s->val[OPT_NVRAM].s[0] = 0;
s->opt[OPT_NVRAM].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
if (!dev->inquiry_nvram_read)
s->opt[OPT_NVRAM].cap |= SANE_CAP_INACTIVE;
/* paper_length */ /* paper_length */
s->opt[OPT_PAPERLEN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
if (!dev->inquiry_paper_length)
s->opt[OPT_PAPERLEN].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_PAPERLEN].name = "paper-length"; s->opt[OPT_PAPERLEN].name = "paper-length";
s->opt[OPT_PAPERLEN].title = "Use paper length"; s->opt[OPT_PAPERLEN].title = SANE_TITLE_PAPER_LENGTH;
s->opt[OPT_PAPERLEN].desc = "Newer scanners can utilize this paper length to detect double feeds. However some others (DM152) can get confused during media flush if it is set."; s->opt[OPT_PAPERLEN].desc = SANE_DESC_PAPER_LENGTH;
s->opt[OPT_PAPERLEN].type = SANE_TYPE_BOOL; s->opt[OPT_PAPERLEN].type = SANE_TYPE_BOOL;
s->opt[OPT_PAPERLEN].unit = SANE_UNIT_NONE; s->opt[OPT_PAPERLEN].unit = SANE_UNIT_NONE;
s->opt[OPT_PAPERLEN].size = sizeof(SANE_Word); s->opt[OPT_PAPERLEN].size = sizeof(SANE_Word);
s->opt[OPT_PAPERLEN].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_PAPERLEN].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_PAPERLEN].w = SANE_FALSE; s->val[OPT_PAPERLEN].w = SANE_FALSE;
s->opt[OPT_PAPERLEN].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
if (!dev->inquiry_paper_length)
s->opt[OPT_PAPERLEN].cap |= SANE_CAP_INACTIVE;
/* ADF page flipping */ /* ADF page flipping */
s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
if (!(s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX && s->source_mode == AV_ADF_DUPLEX))
s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
s->opt[OPT_ADF_FLIP].name = "flip-page"; s->opt[OPT_ADF_FLIP].name = "flip-page";
s->opt[OPT_ADF_FLIP].title = "Flip document after duplex scanning"; s->opt[OPT_ADF_FLIP].title = SANE_TITLE_FLIP_PAGE;
s->opt[OPT_ADF_FLIP].desc = "Tells page-flipping document scanners to flip the paper back to its original orientation before dropping it in the output tray. Turning this off might make scanning a little faster if you don't care about manually flipping the pages afterwards."; s->opt[OPT_ADF_FLIP].desc = SANE_DESC_FLIP_PAGE;
s->opt[OPT_ADF_FLIP].type = SANE_TYPE_BOOL; s->opt[OPT_ADF_FLIP].type = SANE_TYPE_BOOL;
s->opt[OPT_ADF_FLIP].unit = SANE_UNIT_NONE; s->opt[OPT_ADF_FLIP].unit = SANE_UNIT_NONE;
s->opt[OPT_ADF_FLIP].size = sizeof(SANE_Word); s->opt[OPT_ADF_FLIP].size = sizeof(SANE_Word);
s->opt[OPT_ADF_FLIP].constraint_type = SANE_CONSTRAINT_NONE; s->opt[OPT_ADF_FLIP].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_ADF_FLIP].w = SANE_TRUE; s->val[OPT_ADF_FLIP].w = SANE_TRUE;
s->opt[OPT_ADF_FLIP].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC | SANE_CAP_ADVANCED;
if (!((s->hw->hw->feature_type & AV_ADF_FLIPPING_DUPLEX) && (s->source_mode == AV_ADF_DUPLEX)))
s->opt[OPT_ADF_FLIP].cap |= SANE_CAP_INACTIVE;
/* "Options" group: */
s->opt[OPT_OPTIONS_GROUP].title = SANE_TITLE_INSTALLED_OPTS_GROUP;
s->opt[OPT_OPTIONS_GROUP].type = SANE_TYPE_GROUP;
s->opt[OPT_OPTIONS_GROUP].cap = 0;
s->opt[OPT_OPTIONS_GROUP].size = 0;
s->opt[OPT_OPTIONS_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
/* ADF Installed */
s->opt[OPT_OPTION_ADF].name = "adf-installed";
s->opt[OPT_OPTION_ADF].title = SANE_TITLE_ADF_INSTALLED;
s->opt[OPT_OPTION_ADF].desc = SANE_DESC_ADF_INSTALLED;
s->opt[OPT_OPTION_ADF].type = SANE_TYPE_BOOL;
s->opt[OPT_OPTION_ADF].unit = SANE_UNIT_NONE;
s->opt[OPT_OPTION_ADF].size = sizeof(SANE_Word);
s->opt[OPT_OPTION_ADF].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_OPTION_ADF].w = dev->inquiry_adf_present;
s->opt[OPT_OPTION_ADF].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
/* Lightbox Installed */
s->opt[OPT_OPTION_LIGHTBOX].name = "lightbox-installed";
s->opt[OPT_OPTION_LIGHTBOX].title = SANE_TITLE_LIGHTBOX_INSTALLED;
s->opt[OPT_OPTION_LIGHTBOX].desc = SANE_DESC_LIGHTBOX_INSTALLED;
s->opt[OPT_OPTION_LIGHTBOX].type = SANE_TYPE_BOOL;
s->opt[OPT_OPTION_LIGHTBOX].unit = SANE_UNIT_NONE;
s->opt[OPT_OPTION_LIGHTBOX].size = sizeof(SANE_Word);
s->opt[OPT_OPTION_LIGHTBOX].constraint_type = SANE_CONSTRAINT_NONE;
s->val[OPT_OPTION_LIGHTBOX].w = dev->inquiry_light_box_present;
s->opt[OPT_OPTION_LIGHTBOX].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -8908,6 +9017,12 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
strcpy (val, s->val[option].s); strcpy (val, s->val[option].s);
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
/* Boolean options. */
case OPT_OPTION_ADF:
case OPT_OPTION_LIGHTBOX:
*(SANE_Bool*) val = s->val[option].b;
return SANE_STATUS_GOOD;
} /* end switch option */ } /* end switch option */
} /* end if GET_ACTION_GET_VALUE */ } /* end if GET_ACTION_GET_VALUE */
else if (action == SANE_ACTION_SET_VALUE) else if (action == SANE_ACTION_SET_VALUE)

Wyświetl plik

@ -66,6 +66,65 @@ typedef enum Avision_ConnectionType {
AV_USB AV_USB
} Avision_ConnectionType; } Avision_ConnectionType;
/*
* Translatable custom options text.
*
*/
#define SANE_TITLE_MISC_GROUP SANE_I18N("Miscellaneous")
#define SANE_TITLE_INSTALLED_OPTS_GROUP SANE_I18N("Installed options")
#define SANE_TITLE_OVERSCAN_TOP SANE_I18N("Overscan top")
#define SANE_TITLE_OVERSCAN_BOTTOM SANE_I18N("Overscan bottom")
#define SANE_TITLE_BACKGROUND_LINES SANE_I18N("Background raster lines")
#define SANE_TITLE_QUALITY_SCAN SANE_I18N("Quality scan")
#define SANE_TITLE_MANUAL_EXPOSURE SANE_I18N("Exposure")
#define SANE_TITLE_MULTI_SAMPLE SANE_I18N("Multi-sample")
#define SANE_TITLE_POWER_SAVE_TIME SANE_I18N("Power save timer control")
#define SANE_TITLE_OPTIONS_MSG SANE_I18N("Message text from the scanner")
#define SANE_TITLE_NVRAM SANE_I18N("Obtain NVRAM values")
#define SANE_TITLE_PAPER_LENGTH SANE_I18N("Use paper length")
#define SANE_TITLE_FLIP_PAGE SANE_I18N("Flip document after duplex scanning")
#define SANE_TITLE_ADF_INSTALLED SANE_I18N("ADF installed")
#define SANE_TITLE_LIGHTBOX_INSTALLED SANE_I18N("Lightbox installed")
#define SANE_DESC_OVERSCAN_TOP \
SANE_I18N("The top overscan controls the additional area to scan before the "\
"paper is detected.")
#define SANE_DESC_OVERSCAN_BOTTOM \
SANE_I18N("The bottom overscan controls the additional area to scan after "\
"the paper end is detected.")
#define SANE_DESC_BACKGROUND_LINES \
SANE_I18N("The background raster controls the additional background lines to "\
"scan before the paper is feed through the scanner.")
#define SANE_DESC_QUALITY_SCAN \
SANE_I18N("Turn on quality scanning (slower but better).")
#define SANE_DESC_MANUAL_EXPOSURE \
SANE_I18N("Manual exposure adjustment.")
#define SANE_DESC_MULTI_SAMPLE \
SANE_I18N("Enable multi-sample scan mode.")
#define SANE_DESC_POWER_SAVE_TIME \
SANE_I18N("Allows control of the scanner's power save timer, dimming or "\
"turning off the light.")
#define SANE_DESC_OPTIONS_MSG \
SANE_I18N("This text contains device specific options controlled by the "\
"user on the scanner hardware.")
#define SANE_DESC_NVRAM \
SANE_I18N("Allows access obtaining the scanner's NVRAM values as pretty "\
"printed text.")
#define SANE_DESC_PAPER_LENGTH \
SANE_I18N("Newer scanners can utilize this paper length to detect double feeds. "\
"However some others (DM152) can get confused during media flush if it is set.")
#define SANE_DESC_FLIP_PAGE \
SANE_I18N("Tells page-flipping document scanners to flip the paper back to its "\
"original orientation before dropping it in the output tray. "\
"Turning this off might make scanning a little faster if you don't "\
"care about manually flipping the pages afterwards.")
#define SANE_DESC_ADF_INSTALLED \
SANE_I18N("ADF option is detected as installed.")
#define SANE_DESC_LIGHTBOX_INSTALLED \
SANE_I18N("Lightbox option is detected as installed.")
/* information needed for device access */ /* information needed for device access */
typedef struct Avision_Connection { typedef struct Avision_Connection {
Avision_ConnectionType connection_type; Avision_ConnectionType connection_type;
@ -336,6 +395,10 @@ enum Avision_Option
OPT_PAPERLEN, /* Use paper_length field to detect double feeds */ OPT_PAPERLEN, /* Use paper_length field to detect double feeds */
OPT_ADF_FLIP, /* For flipping duplex, reflip the document */ OPT_ADF_FLIP, /* For flipping duplex, reflip the document */
OPT_OPTIONS_GROUP,
OPT_OPTION_ADF, // ADF installed/detected?
OPT_OPTION_LIGHTBOX, // LightBox installed/detected?
NUM_OPTIONS /* must come last */ NUM_OPTIONS /* must come last */
}; };
@ -398,8 +461,7 @@ typedef struct Avision_Device
SANE_Bool inquiry_nvram_read; SANE_Bool inquiry_nvram_read;
SANE_Bool inquiry_power_save_time; SANE_Bool inquiry_power_save_time;
SANE_Bool inquiry_light_box; SANE_Bool inquiry_adf_capability;
SANE_Bool inquiry_adf;
SANE_Bool inquiry_duplex; SANE_Bool inquiry_duplex;
SANE_Bool inquiry_duplex_interlaced; SANE_Bool inquiry_duplex_interlaced;
SANE_Bool inquiry_paper_length; SANE_Bool inquiry_paper_length;
@ -419,6 +481,10 @@ typedef struct Avision_Device
SANE_Bool inquiry_light_control; SANE_Bool inquiry_light_control;
SANE_Bool inquiry_exposure_control; SANE_Bool inquiry_exposure_control;
// Determines from accessories query.
SANE_Bool inquiry_light_box_present;
SANE_Bool inquiry_adf_present;
int inquiry_max_shading_target; int inquiry_max_shading_target;
SANE_Bool inquiry_button_control; SANE_Bool inquiry_button_control;
unsigned int inquiry_buttons; unsigned int inquiry_buttons;

Wyświetl plik

@ -142,6 +142,7 @@
#define SANE_NAME_LAMP_OFF_AT_EXIT "lamp-off-at-exit" #define SANE_NAME_LAMP_OFF_AT_EXIT "lamp-off-at-exit"
#define SANE_NAME_FOCUS "focus" #define SANE_NAME_FOCUS "focus"
#define SANE_NAME_AUTOFOCUS "autofocus" #define SANE_NAME_AUTOFOCUS "autofocus"
#define SANE_NAME_INFRARED "infra-red"
/* well known options from 'SENSORS' group*/ /* well known options from 'SENSORS' group*/
#define SANE_NAME_SCAN "scan" #define SANE_NAME_SCAN "scan"
@ -233,6 +234,8 @@
#define SANE_TITLE_LAMP_OFF_AT_EXIT SANE_I18N("Lamp off at exit") #define SANE_TITLE_LAMP_OFF_AT_EXIT SANE_I18N("Lamp off at exit")
#define SANE_TITLE_FOCUS SANE_I18N("Focus position") #define SANE_TITLE_FOCUS SANE_I18N("Focus position")
#define SANE_TITLE_AUTOFOCUS SANE_I18N("Autofocus") #define SANE_TITLE_AUTOFOCUS SANE_I18N("Autofocus")
#define SANE_TITLE_INFRARED SANE_I18N("Infrared scan")
/* well known options from 'SENSORS' group*/ /* well known options from 'SENSORS' group*/
#define SANE_TITLE_SCAN "Scan button" #define SANE_TITLE_SCAN "Scan button"
@ -447,6 +450,9 @@ SANE_I18N("Turn off lamp when program exits")
SANE_I18N("Focus position for manual focus") SANE_I18N("Focus position for manual focus")
#define SANE_DESC_AUTOFOCUS \ #define SANE_DESC_AUTOFOCUS \
SANE_I18N("Perform autofocus before scan") SANE_I18N("Perform autofocus before scan")
#define SANE_DESC_INFRARED \
SANE_I18N("Perform infrared scan")
/* well known options from 'SENSORS' group*/ /* well known options from 'SENSORS' group*/
#define SANE_DESC_SCAN SANE_I18N("Scan button") #define SANE_DESC_SCAN SANE_I18N("Scan button")