diff --git a/dlls/sane.ds/capability.c b/dlls/sane.ds/capability.c index 4faab5975d9..7a37399c899 100644 --- a/dlls/sane.ds/capability.c +++ b/dlls/sane.ds/capability.c @@ -166,6 +166,7 @@ static TW_UINT16 TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability) { TW_ARRAY *a; static const UINT16 supported_caps[] = { CAP_SUPPORTEDCAPS, CAP_XFERCOUNT, CAP_UICONTROLLABLE, + CAP_AUTOFEED, ICAP_XFERMECH, ICAP_PIXELTYPE, ICAP_UNITS, ICAP_BITDEPTH, ICAP_COMPRESSION, ICAP_PIXELFLAVOR, ICAP_XRESOLUTION, ICAP_YRESOLUTION, ICAP_PHYSICALHEIGHT, ICAP_PHYSICALWIDTH }; @@ -815,6 +816,72 @@ static TW_UINT16 SANE_ICAPPixelFlavor (pTW_CAPABILITY pCapability, TW_UINT16 act return twCC; } +/* CAP_AUTOFEED */ +static TW_UINT16 SANE_CAPAutofeed (pTW_CAPABILITY pCapability, TW_UINT16 action) +{ + TW_UINT16 twCC = TWCC_BADCAP; +#ifdef SONAME_LIBSANE + TW_UINT32 val; + SANE_Bool autofeed; + SANE_Status status; + + TRACE("CAP_AUTOFEED\n"); + + if (sane_option_get_bool(activeDS.deviceHandle, "batch-scan", &autofeed, NULL) != SANE_STATUS_GOOD) + return TWCC_BADCAP; + + switch (action) + { + case MSG_QUERYSUPPORT: + twCC = set_onevalue(pCapability, TWTY_INT32, + TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET ); + break; + + case MSG_GET: + twCC = set_onevalue(pCapability, TWTY_BOOL, autofeed); + break; + + case MSG_SET: + twCC = msg_set(pCapability, &val); + if (twCC == TWCC_SUCCESS) + { + if (val) + autofeed = SANE_TRUE; + else + autofeed = SANE_FALSE; + + status = sane_option_set_bool(activeDS.deviceHandle, "batch-scan", autofeed, NULL); + if (status != SANE_STATUS_GOOD) + { + ERR("Error %s: Could not set batch-scan to %d\n", psane_strstatus(status), autofeed); + return sane_status_to_twcc(status); + } + } + break; + + case MSG_GETDEFAULT: + twCC = set_onevalue(pCapability, TWTY_BOOL, SANE_TRUE); + break; + + case MSG_RESET: + autofeed = SANE_TRUE; + status = sane_option_set_bool(activeDS.deviceHandle, "batch-scan", autofeed, NULL); + if (status != SANE_STATUS_GOOD) + { + ERR("Error %s: Could not reset batch-scan to SANE_TRUE\n", psane_strstatus(status)); + return sane_status_to_twcc(status); + } + /* .. fall through intentional .. */ + + case MSG_GETCURRENT: + twCC = set_onevalue(pCapability, TWTY_BOOL, autofeed); + break; + } +#endif + return twCC; +} + + TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) { @@ -839,6 +906,10 @@ TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) twCC = SANE_CAPUiControllable (pCapability, action); break; + case CAP_AUTOFEED: + twCC = SANE_CAPAutofeed (pCapability, action); + break; + case ICAP_PIXELTYPE: twCC = SANE_ICAPPixelType (pCapability, action); break; @@ -891,3 +962,17 @@ TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action) return twCC; } + +TW_UINT16 SANE_SaneSetDefaults (void) +{ + TW_CAPABILITY cap; + + memset(&cap, 0, sizeof(cap)); + cap.Cap = CAP_AUTOFEED; + cap.ConType = TWON_DONTCARE16; + + if (SANE_SaneCapability(&cap, MSG_RESET) == TWCC_SUCCESS) + GlobalFree(cap.hContainer); + + return TWCC_SUCCESS; +} diff --git a/dlls/sane.ds/options.c b/dlls/sane.ds/options.c index 47938831da8..1997abc792b 100644 --- a/dlls/sane.ds/options.c +++ b/dlls/sane.ds/options.c @@ -85,6 +85,33 @@ SANE_Status sane_option_set_int(SANE_Handle h, const char *option_name, SANE_Int return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); } +SANE_Status sane_option_get_bool(SANE_Handle h, const char *option_name, SANE_Bool *val, SANE_Int *status) +{ + SANE_Status rc; + int optno; + const SANE_Option_Descriptor *opt; + + rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_BOOL); + if (rc != SANE_STATUS_GOOD) + return rc; + + return psane_control_option(h, optno, SANE_ACTION_GET_VALUE, (void *) val, status); +} + +SANE_Status sane_option_set_bool(SANE_Handle h, const char *option_name, SANE_Bool val, SANE_Int *status) +{ + SANE_Status rc; + int optno; + const SANE_Option_Descriptor *opt; + + rc = sane_find_option(h, option_name, &opt, &optno, SANE_TYPE_BOOL); + if (rc != SANE_STATUS_GOOD) + return rc; + + return psane_control_option(h, optno, SANE_ACTION_SET_VALUE, (void *) &val, status); +} + + /* Important: SANE has the side effect of of overwriting val with the returned value */ SANE_Status sane_option_set_str(SANE_Handle h, const char *option_name, SANE_String val, SANE_Int *status) { diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 18fd8bbfa0a..81c9a9e7214 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -85,6 +85,7 @@ struct tagActiveDS /* Helper functions */ extern TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action); +extern TW_UINT16 SANE_SaneSetDefaults (void); /* Implementation of operation triplets * From Application to Source (Control Information) */ @@ -228,6 +229,8 @@ SANE_Status sane_option_probe_resolution(SANE_Handle h, const char *option_name, SANE_Status sane_option_probe_mode(SANE_Handle h, SANE_String_Const **choices, char *current, int current_size); SANE_Status sane_option_probe_scan_area(SANE_Handle h, const char *option_name, SANE_Fixed *val, SANE_Unit *unit, SANE_Fixed *min, SANE_Fixed *max, SANE_Fixed *quant); +SANE_Status sane_option_get_bool(SANE_Handle h, const char *option_name, SANE_Bool *val, SANE_Int *status); +SANE_Status sane_option_set_bool(SANE_Handle h, const char *option_name, SANE_Bool val, SANE_Int *status); #endif diff --git a/dlls/sane.ds/sane_main.c b/dlls/sane.ds/sane_main.c index 49a7cb3d285..d8ba9b5bdce 100644 --- a/dlls/sane.ds/sane_main.c +++ b/dlls/sane.ds/sane_main.c @@ -661,11 +661,16 @@ static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) { } status = psane_open(sane_devlist[i]->name,&activeDS.deviceHandle); if (status == SANE_STATUS_GOOD) { - activeDS.currentState = 4; - activeDS.twCC = TWRC_SUCCESS; - return TWRC_SUCCESS; + activeDS.twCC = SANE_SaneSetDefaults(); + if (activeDS.twCC == TWCC_SUCCESS) { + activeDS.currentState = 4; + return TWRC_SUCCESS; + } + else + psane_close(activeDS.deviceHandle); } - ERR("sane_open(%s): %s\n", sane_devlist[i]->name, psane_strstatus (status)); + else + ERR("sane_open(%s): %s\n", sane_devlist[i]->name, psane_strstatus (status)); return TWRC_FAILURE; } #endif diff --git a/dlls/twain_32/tests/dsm.c b/dlls/twain_32/tests/dsm.c index 46d0c5a80ad..c4744f9bdb3 100644 --- a/dlls/twain_32/tests/dsm.c +++ b/dlls/twain_32/tests/dsm.c @@ -578,6 +578,12 @@ static void test_single_source(TW_IDENTITY *appid, TW_IDENTITY *source) if (capabilities[ICAP_YRESOLUTION]) test_resolution(appid, source, ICAP_YRESOLUTION, TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET); + + /* Optional capabilities */ + if (capabilities[CAP_AUTOFEED]) + test_onevalue_cap(appid, source, CAP_AUTOFEED, TWTY_BOOL, + TWQC_GET | TWQC_SET | TWQC_GETDEFAULT | TWQC_GETCURRENT | TWQC_RESET); + } }