diff --git a/ChangeLog b/ChangeLog index 41d8e6e2b..6b6ed64a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2008-05-26 Rene Rebe + * backend/avision.{c,h}: merged latest upstream SVN changes, bug fixes + and device ID updates, including fixing uninitialized variables due + former defect merge and exposure control for film / dia scanners + 2008-05-26 Stéphane Voltz * backend/sane_strstatus.c: added new status and internationalization support diff --git a/backend/avision.c b/backend/avision.c index 17beca3c3..d1e357cf2 100644 --- a/backend/avision.c +++ b/backend/avision.c @@ -134,7 +134,7 @@ #include #define BACKEND_NAME avision -#define BACKEND_BUILD 264 /* avision backend BUILD version */ +#define BACKEND_BUILD 288 /* avision backend BUILD version */ #include #include @@ -179,63 +179,70 @@ static Avision_HWEntry Avision_Device_List [] = 0}, /* status="untested" */ - { "AVISION", "AV120", + { NULL, NULL, 0x0638, 0x0A27, "Avision", "AV120", AV_INT_STATUS}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "AVISION", "AV121", + { NULL, NULL, 0x0638, 0x0A3C, "Avision", "AV121", AV_INT_BUTTON | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA}, /* comment="sheetfed scanner" */ /* status="good" */ - { "AVISION", "AV122", + { NULL, NULL, 0x0638, 0x0A33, "Avision", "AV122", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed duplex scanner" */ /* status="good" */ - { "AVISION", "AV122 C2", + { NULL, NULL, 0x0638, 0x0A93, "Avision", "AV122 C2", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed duplex scanner" */ /* status="good" */ - { "AVISION", "AV210", + { NULL, NULL, 0x0638, 0x0A24, "Avision", "AV210", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "AVISION", "AV210", + { NULL, NULL, 0x0638, 0x0A25, "Avision", "AV210", - AV_INT_BUTTON | AV_ACCEL_TABLE}, + AV_INT_BUTTON | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "AVISION", "AVISION AV210C2", + { NULL, NULL, 0x0638, 0x0A3A, "Avision", "AV210C2", AV_INT_BUTTON | AV_GRAY_MODES}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "AVISION", "AV210C2", + { NULL, NULL, + 0x0638, 0x0A2F, + "Avision", "AV210C2-G", + AV_INT_BUTTON | AV_GRAY_MODES}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, 0x0638, 0x0A3A, "Avision", "AV210C2", AV_INT_BUTTON | AV_GRAY_MODES}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "AVISION", "AVISION AV220", + { NULL, NULL, 0x0638, 0x0A23, "Avision", "AV220", AV_INT_BUTTON}, @@ -249,6 +256,41 @@ static Avision_HWEntry Avision_Device_List [] = /* comment="duplex! sheetfed scanner" */ /* status="complete" */ + { NULL, NULL, + 0x0638, 0x0A2B, + "Avision", "AV220D2", + AV_INT_BUTTON | AV_CANCEL_BUTTON}, + /* comment="duplex! sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x0638, 0x0A2C, + "Avision", "AV220+", + AV_INT_BUTTON | AV_CANCEL_BUTTON}, + /* comment="duplex! sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x0638, 0x0A2D, + "Avision", "AV220C2-G", + AV_INT_BUTTON | AV_CANCEL_BUTTON}, + /* comment="duplex! sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x0638, 0x0A2E, + "Avision", "AV220C2-B", + AV_INT_BUTTON | AV_CANCEL_BUTTON}, + /* comment="duplex! sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x0638, 0x0A94, + "Avision", "AV220-G", + AV_INT_BUTTON}, + /* comment="duplex! sheetfed scanner" */ + /* status="complete" */ + { "AVISION", "AV240SC", 0, 0, "Avision", "AV240SC", @@ -285,26 +327,32 @@ static Avision_HWEntry Avision_Device_List [] = 0}, /* status="untested" */ - { "AVISION", "AV610", - 0x0638, 0x0a19, + { NULL, "AV610", + 0x0638, 0x0a18, "Avision", "AV610", AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_STATUS | AV_INT_BUTTON}, /* status="good" */ - { "AVISION", "AV610C2", - 0x0638, 0x0a5e, - "Avision", "AV610C2", - AV_INT_BUTTON}, /* cancel button -> sense abort! */ + { NULL, NULL, + 0x0638, 0x0a18, + "Avision", "AV600U Plus", + AV_GRAY_CALIB_BLUE | AV_ACCEL_TABLE | AV_NO_64BYTE_ALIGN | AV_INT_STATUS | AV_INT_BUTTON}, /* status="good" */ - { "AVISION", "AM3000 Series", + { NULL, NULL, + 0x0638, 0x0a5e, + "Avision", "AV610C2", + AV_NO_BACKGROUND | AV_INT_BUTTON}, /* cancel button -> sense abort! */ + /* status="good" */ + + { NULL, NULL, 0x0638, 0x0a41, "Avision", "AM3000 Series", 0}, /* comment="MFD" */ /* status="basic" */ - { "AVision", "DS610CU", + { NULL, NULL, 0x0638, 0x0a16, "Avision", "DS610CU Scancopier", AV_INT_STATUS}, @@ -346,20 +394,13 @@ static Avision_HWEntry Avision_Device_List [] = /* comment="1 pass, ??? dpi" */ /* status="complete" */ - { "AVISION", "AV600U", + { NULL, NULL, 0x0638, 0x0A13, "Avision", "AV600U", AV_MULTI_CALIB_CMD | AV_ADF_BGR_ORDER_INVERT | AV_SOFT_SCALE | AV_INT_STATUS | AV_NO_BUTTON}, /* comment="1 pass, 600 dpi" */ /* status="good" */ - { "AVISION", "AV600U Plus", - 0x0638, 0x0A18, - "Avision", "AV600U Plus", - 0}, - /* comment="1 pass, ??? dpi" */ - /* status="untested" */ - { "AVISION", "AV660S", 0, 0, "Avision", "AV660S", @@ -451,10 +492,31 @@ static Avision_HWEntry Avision_Device_List [] = /* comment="1 pass, ??? dpi" */ /* status="complete" */ + { "AVISION", "AV3200SU", + 0x0638, 0x0A4E, + "Avision", "AV3200SU", + 0}, + /* comment="1 pass, ??? dpi" */ + /* status="complete" */ + + { "AVISION", "AV3730SU", + 0x0638, 0x0A4F, + "Avision", "AV3730SU", + 0}, + /* comment="1 pass, ??? dpi" */ + /* status="complete" */ + + { "AVISION", "AV3750SU", + 0x0638, 0x0A65, + "Avision", "AV3750SU", + 0}, + /* comment="1 pass, ??? dpi" */ + /* status="complete" */ + { "AVISION", "AV3800C", 0, 0, "Avision", "AV3800C", - AV_NON_INTERLACED_DUPLEX_300}, + 0}, /* comment="1 pass, ??? dpi" */ /* status="complete" */ @@ -466,20 +528,20 @@ static Avision_HWEntry Avision_Device_List [] = /* status="complete" */ { "AVISION", "FB6000E", - 0, 0, + 0, 0, "Avision", "FB6000E", AV_NON_INTERLACED_DUPLEX_300}, /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */ /* status="complete" */ - { "AVISION", "FB6080E", - 0x0638, 0x0a82, + { NULL, NULL, + 0x0638, 0x0a82, "Avision", "FB6080E", AV_NON_INTERLACED_DUPLEX_300}, /* comment="1 pass, 1200 dpi, A3 - duplex! - zero edge!" */ /* status="complete" */ - { "AVISION", "FB2080E", + { NULL, NULL, 0x0638, 0xa84, "Avision", "FB2080E", 0}, @@ -494,43 +556,42 @@ static Avision_HWEntry Avision_Device_List [] = /* status="complete" */ { NULL, NULL, - 0x0638, 0x0a4d, + 0x0638, 0x0a4d, "Avision", "AV8050U", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ { "AVISION", "AV8300", - 0x0638, 0x0A40, + 0x0638, 0x0A40, "Avision", "AV8300", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ { "AVISION", "AV8350", - 0x0638, 0x0A68, + 0x0638, 0x0A68, "Avision", "AV8350", AV_NON_INTERLACED_DUPLEX_300 | AV_DOES_NOT_KEEP_GAMMA}, /* comment="1 pass, 1200 dpi, A3 - duplex!" */ /* status="complete" */ - { "AVISION", "IT8300", - 0x0638, 0x0A61, + { NULL, NULL, + 0x0638, 0x0A61, "Avision", "IT8300", AV_NON_INTERLACED_DUPLEX_300 | AV_ACCEL_TABLE}, /* comment="1 pass, 1200 dpi, A3 - duplex!, LCD screen, paper sensors" */ /* status="good" */ - { "AVISION", NULL, + { NULL, NULL, 0x0638, 0x0AA1, "Avision", "@V2500", 0}, /* comment="" */ /* status="untested" */ - - { "AVISION", NULL, - 0x0638, 0x0A45, + { NULL, NULL, + 0x0638, 0x0A45, "Avision", "@V5100", 0}, /* comment="" */ @@ -562,7 +623,7 @@ static Avision_HWEntry Avision_Device_List [] = { "hp", "scanjet 7400c", 0x03f0, 0x0801, "Hewlett-Packard", "ScanJet 7400c", - AV_NO_64BYTE_ALIGN | AV_INT_STATUS}, + AV_LIGHT_CHECK_BOGUS | AV_NO_64BYTE_ALIGN | AV_INT_STATUS}, /* comment="1 pass, 2400 dpi - dual USB/SCSI interface" */ /* status="good" */ @@ -626,6 +687,12 @@ static Avision_HWEntry Avision_Device_List [] = "Minolta", "Dimage Scan Dual I", AV_FORCE_FILM | AV_NO_START_SCAN}, /* not AV_FILMSCANNER (no frame control) */ /* status="basic" */ + + { "Minolta", "#2887", + 0, 0, + "Minolta", "Scan Multi Pro", + AV_FORCE_FILM | AV_NO_START_SCAN}, /* AV_FILMSCANNER (rame control)? */ + /* status="untested" */ { "MINOLTA", "FS-V1", 0x0638, 0x026a, @@ -644,16 +711,16 @@ static Avision_HWEntry Avision_Device_List [] = { "MINOLTA", "FS-V3", 0x0686, 0x400d, "Minolta", "Dimage Scan Dual III", - AV_FILMSCANNER | AV_ONE_CALIB_CMD}, + AV_FILMSCANNER | AV_ONE_CALIB_CMD | AV_ACCEL_TABLE }, /* comment="1 pass, film-scanner" */ - /* status="basic" */ + /* status="good" */ { "MINOLTA", "FS-V4", 0x0686, 0x400e, "Minolta", "Dimage Scan Elite 5400", AV_FILMSCANNER | AV_ONE_CALIB_CMD | /*AV_ACCEL_TABLE |*/ AV_NO_START_SCAN}, /* comment="1 pass, film-scanner" */ - /* status="untested" */ + /* status="good" */ { "QMS", "SC-110", 0x0638, 0x0a15, @@ -749,49 +816,49 @@ static Avision_HWEntry Avision_Device_List [] = 0}, /* status="untested" */ - { "FCPA", "fi-4010CU", + { NULL, NULL, 0x04c5, 0x1029, "Fujitsu", "fi-4010CU", 0}, /* status="untested" */ - { "KODAK", "i30 Scanner", + { NULL, NULL, 0x040a, 0x6001, "Kodak", "i30", - AV_NO_TUNE_BOTTOM | AV_INT_BUTTON}, + AV_INT_BUTTON}, /* status="untested" */ - { "KODAK", "i40 Scanner", + { NULL, NULL, 0x040a, 0x6002, "Kodak", "i40", - AV_LIGHT_CHECK_BOGUS | AV_NO_GAMMA | AV_NO_TUNE_BOTTOM | AV_INT_BUTTON}, + AV_INT_BUTTON}, /* status="basic" */ - { "KODAK", "i50 Scanner", + { NULL, NULL, 0x040a, 0x6003, "Kodak", "i50", AV_INT_BUTTON}, /* status="untested" */ - { "KODAK", "i55 Scanner", + { NULL, NULL, 0x040a, 0x6003, - "Kodak", "i50", + "Kodak", "i55", AV_INT_BUTTON}, /* status="untested" */ - { "KODAK", "i60 Scanner", + { NULL, NULL, 0x040a, 0x6004, "Kodak", "i60", AV_INT_BUTTON}, /* status="untested" */ - { "KODAK", "i65 Scanner", + { NULL, NULL, 0x040a, 0x6004, - "Kodak", "i60", + "Kodak", "i65", AV_INT_BUTTON}, /* status="untested" */ - { "KODAK", "KODAK i80", + { NULL, NULL, 0x040a, 0x6005, "Kodak", "i80", AV_INT_BUTTON}, @@ -803,117 +870,233 @@ static Avision_HWEntry Avision_Device_List [] = 0}, /* status="untested" */ - { "XEROX", "DocuMate152", - 0x04a7, 0x0477, - "Xerox", "DocuMate152", - AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, - /* status="good" */ - - { "XEROX", "DocuMate250", - 0x04a7, 0x0448, - "Xerox", "DocuMate250", - AV_INT_BUTTON}, - /* status="good" */ - - { "XEROX", "DocuMate252", - 0x04a7, 0x0449, - "Xerox", "DocuMate252", - AV_INT_BUTTON}, - /* status="good" */ - - { "XEROX", "DocuMate262", - 0x04a7, 0x044c, - "Xerox", "DocuMate262", - AV_INT_BUTTON}, - /* status="good" */ - - { "XEROX", "DocuMate272", - 0x04a7, 0x0475, - "Xerox", "DocuMate272", - AV_INT_BUTTON}, - /* status="untested" */ - - { "XEROX", "DocuMate510", - 0x04a7, 0x0, /* TODO */ - "Xerox", "DocuMate510", - AV_INT_BUTTON}, - /* status="untested" */ - - { "XEROX", "DocuMate520", - 0x04a7, 0x0447, - "Xerox", "DocuMate520", - AV_INT_BUTTON}, - /* status="untested" */ - - { "XEROX", "DocuMate632", - 0x04a7, 0x0498, - "Xerox", "DocuMate632", - AV_INT_BUTTON}, - /* status="untested" */ - - { "XEROX", "DocuMate752", - 0x04a7, 0x0478, - "Xerox", "DocuMate752", - AV_INT_BUTTON}, - /* status="untested" */ - - { "VISIONER", "Strobe XP 450", + { NULL, NULL, 0x04a7, 0x0424, "Visioneer", "Strobe XP 450", AV_INT_BUTTON | AV_ACCEL_TABLE}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, + 0x04a7, 0x0491, + "Visioneer", "Strobe XP 450-G", + AV_INT_BUTTON | AV_ACCEL_TABLE}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x0479, + "Visioneer", "Strobe XP 470", + AV_INT_BUTTON | AV_ACCEL_TABLE}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x048F, + "Visioneer", "Strobe XP 470-G", + AV_INT_BUTTON | AV_ACCEL_TABLE}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x0420, + "Visioneer", "9320", + 0}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x0421, + "Visioneer", "9450", + 0}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, 0x04a7, 0x047A, - "Visioneer", "9450 USB", + "Visioneer", "9450-G", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, + 0x04a7, 0x0422, + "Visioneer", "9550", + 0}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x0390, + "Visioneer", "9650", + 0}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, 0x04a7, 0x047B, - "Visioneer", "9650 USB", + "Visioneer", "9650-G", 0}, /* comment="sheetfed scanner" */ /* status="complete" */ - - { "VISIONER", NULL, - 0x04a7, 0x0493, - "Visioneer", "9750 PDF", + + { NULL, NULL, + 0x04a7, 0x0423, + "Visioneer", "9750", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, + 0x04a7, 0x0493, + "Visioneer", "9750-G", + AV_INT_BUTTON}, + /* comment="sheetfed scanner" */ + /* status="complete" */ + + { NULL, NULL, 0x04a7, 0x0497, "Visioneer", "Patriot 430", AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, 0x04a7, 0x048F, "Visioneer", "Patriot 470", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, 0x04a7, 0x0498, "Visioneer", "Patriot 680", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ - { "VISIONER", NULL, + { NULL, NULL, 0x04a7, 0x0499, "Visioneer", "Patriot 780", AV_INT_BUTTON}, /* comment="sheetfed scanner" */ /* status="complete" */ + + { NULL, NULL, + 0x04a7, 0x049C, + "Xerox", "DocuMate150", + AV_INT_BUTTON | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_BACKGROUND_QUIRK}, + /* status="good" */ - { "OKI", "S700 Scancopier", + { NULL, NULL, + 0x04a7, 0x0477, + "Xerox", "DocuMate152", + AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x049D, + "Xerox", "DocuMate162", + AV_INT_BUTTON | AV_2ND_LINE_INTERLACED | AV_NO_REAR | AV_SOFT_SCALE | AV_DOES_KEEP_WINDOW | AV_DOES_KEEP_GAMMA | AV_REAR_OFFSET | AV_BACKGROUND_QUIRK}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x0448, + "Xerox", "DocuMate250", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x0490, + "Xerox", "DocuMate250-G", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x0449, + "Xerox", "DocuMate252", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x048C, + "Xerox", "DocuMate252-G", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x044c, + "Xerox", "DocuMate262", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x048D, + "Xerox", "DocuMate262-G", + AV_INT_BUTTON}, + /* status="good" */ + + { NULL, NULL, + 0x04a7, 0x0475, + "Xerox", "DocuMate272", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x048E, + "Xerox", "DocuMate272-G", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0446, + "Xerox", "DocuMate510", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0495, + "Xerox", "DocuMate512", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x047c, + "Xerox", "DocuMate510-G", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0447, + "Xerox", "DocuMate520", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0492, + "Xerox", "DocuMate520-G", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0498, + "Xerox", "DocuMate632", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x0478, + "Xerox", "DocuMate752", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, + 0x04a7, 0x049A, + "Xerox", "DocuMate752", + AV_INT_BUTTON}, + /* status="untested" */ + + { NULL, NULL, 0x0638, 0x0a16, "OKI", "S700 Scancopier", 0}, @@ -927,9 +1110,9 @@ static Avision_HWEntry Avision_Device_List [] = /* comment="1 pass, ??? dpi, A4" */ /* status="basic" */ - { "Kyocera", "FS-1016MFP", + { NULL, NULL, 0x0482, 0x0335, - 0, 0, + "Kyocera", "FS-1016MFP", 0}, /* comment="1 pass, ??? dpi, A4" */ /* status="untested" */ @@ -1009,7 +1192,10 @@ Lexmark X4500 MFP #define DEFAULT_WHITE_SHADING 0xFFF0 #define MAX_WHITE_SHADING 0xFFFF -#define WHITE_MAP_RANGE 0x4000 +/* originally the WHITE_MAP_RANGE was 0x4000 - but this always + * resulted in slightly too dark images - thus I have choosen + * 0x4FFF ... */ +#define WHITE_MAP_RANGE 0x4FFF #define INVALID_DARK_SHADING 0xFFFF #define DEFAULT_DARK_SHADING 0x0000 @@ -1048,11 +1234,13 @@ static const int hw_res_list_c5[] = }; static const int hw_res_list_generic[] = { - /* tested on AV122/DM152 */ - 50, 75, /* work but are slower than 150 on the AV122/DM152, left for USB 1 hosts */ + 50, /* slower than 150 on the AV122/DM152, left for USB 1 host's preview */ + 75, /* slower than 150 on the AV122/DM152, left for USB 1 host's */ 150, 200, 300, - /* 400, */ /* worked mostly, y-scaling was wrong on AV122/DM152 */ - 600, 1200, 2400, 4800, /* ... */ 0 + /* 400,*/ /* AV122 simplex y-scaling and duplex interlacing corrupt */ + 600, 1200, 2400, 4800, + /* ... */ + 0 }; static SANE_Bool static_calib_list[3] = @@ -1081,6 +1269,13 @@ static const SANE_Range abs_percentage_range = SANE_FIX (1) /* quantization */ }; +static const SANE_Range exposure_range = + { + 0, /* minimum */ + 1000, /* maximum */ + 1 /* quantization */ + }; + static const SANE_Range overscan_range = { SANE_FIX (0), /* minimum */ @@ -1311,6 +1506,13 @@ static void debug_print_calib_format (int dbg_level, char* func, func, get_double ( &(result[17]) ) ); DBG (dbg_level, "%s: [19-20] B dark shading target: %x\n", func, get_double ( &(result[19]) ) ); + + DBG (dbg_level, "%s: [21] true-gray gain: %d\n", func, result[21]); + DBG (dbg_level, "%s: [22-23] true-gray shading target: %x\n", + func, get_double ( &(result[22]) ) ); + + DBG (dbg_level, "%s: [24-25] true-gray dark shading target: %x\n", + func, get_double ( &(result[24]) ) ); } static void debug_print_accel_info (int dbg_level, char* func, @@ -1827,8 +2029,11 @@ static SANE_Status avision_cmd (Avision_Connection* av_con, /* per command class timeout tweaks */ switch (m_cmd[0]) { case AVISION_SCSI_INQUIRY: + read_timeout = 1000; /* quickly timeout on initial detection */ + status_timeout = 1000; + break; case AVISION_SCSI_TEST_UNIT_READY: - read_timeout = 15000; /* quick timeout on initial detection */ + read_timeout = 15000; /* quickly timeout on initial detection */ status_timeout = 15000; break; } @@ -2197,7 +2402,36 @@ compute_parameters (Avision_Scanner* s) /* interlaced duplex (higher end) or flipping paper (HP8xxx)? */ s->avdimen.interlaced_duplex = s->source_mode == AV_ADF_DUPLEX && dev->inquiry_duplex_interlaced; + + /* for infra-red we use the same code path es for interlaced + duplex */ + if (s->val[OPT_IR].w) + s->avdimen.interlaced_duplex = 1; +#ifdef AVISION_ENHANCED_SANE + /* quick fix for Microsoft Office Products ... */ + switch (s->c_mode) + { + case AV_THRESHOLDED: + case AV_DITHERED: + /* our backend already has this restriction - so this line is for + documentation purposes only */ + boundary = boundary > 32 ? boundary : 32; + break; + case AV_GRAYSCALE: + case AV_GRAYSCALE12: + case AV_GRAYSCALE16: + boundary = boundary > 4 ? boundary : 4; + break; + case AV_TRUECOLOR: + case AV_TRUECOLOR12: + case AV_TRUECOLOR16: + /* 12 bytes for 24bit color - 48bit is untested w/ Office */ + boundary = boundary > 4 ? boundary : 4; + break; + } +#endif + DBG (3, "sane_compute_parameters:\n"); DBG (3, "sane_compute_parameters: boundary %d, gray_mode: %d, \n", @@ -2311,7 +2545,7 @@ compute_parameters (Avision_Scanner* s) s->avdimen.hw_lines = (s->avdimen.bry - s->avdimen.tly - 2 * s->avdimen.line_difference); - if (s->avdimen.interlaced_duplex) + if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) s->avdimen.hw_lines -= s->avdimen.hw_lines % dev->read_stripe_size; s->params.pixels_per_line = s->avdimen.hw_pixels_per_line * s->avdimen.xres / s->avdimen.hw_xres; @@ -2865,6 +3099,7 @@ get_accessories_info (Avision_Scanner* s) if (result [2] == 2) /* HP */ { dev->inquiry_duplex = 1; + dev->inquiry_duplex_interlaced = 0; dev->inquiry_adf_need_mirror_rear = 1; } @@ -2981,7 +3216,7 @@ get_button_status (Avision_Scanner* s) /* no SCSI equivalent */ /* either there was a button press and this completes quickly or there is no point waiting for a future press */ - sanei_usb_set_timeout (250); + sanei_usb_set_timeout (100); /* 10th of a second */ DBG (5, "==> (interrupt read) going down ...\n"); status = sanei_usb_read_int (s->av_con.usb_dn, (uint8_t*)&result, &size); @@ -3661,6 +3896,10 @@ get_double ( &(result[48] ) )); dev->inquiry_adf = BIT (result[62], 5); dev->inquiry_duplex = BIT (result[62], 2) || BIT (result[94], 5); dev->inquiry_duplex_interlaced = BIT(result[62],2) || BIT (result[94], 4); + /* the first avision scanners (AV3200) do not set the interlaced bit */ + if (dev->inquiry_duplex && dev->inquiry_asic_type < AV_ASIC_C6) + dev->inquiry_duplex_interlaced = 1; + dev->inquiry_paper_length = BIT (result[95], 5); dev->inquiry_batch_scan = BIT (result[95], 0); /* AV122, DM152 */ @@ -3695,6 +3934,7 @@ get_double ( &(result[48] ) )); dev->inquiry_light_control = BIT (result[50], 7); dev->inquiry_button_control = BIT (result[50], 6) | BIT (result[51],2); + dev->inquiry_exposure_control = BIT(result[51],7); dev->inquiry_max_shading_target = get_double ( &(result[75]) ); dev->inquiry_color_boundary = result[54]; @@ -3715,10 +3955,18 @@ get_double ( &(result[48] ) )); dev->inquiry_line_difference = result[53]; /* compensation according to real world hardware */ - if (dev->inquiry_asic_type == AV_ASIC_C2) - dev->inquiry_line_difference /= 2; /* HP 5300 */ - else if (dev->inquiry_asic_type == AV_ASIC_C7) - dev->inquiry_line_difference *= 2; /* AV610C2 */ + switch (dev->inquiry_asic_type) + { + case AV_ASIC_C2: /* HP 5300 */ + case AV_ASIC_C5: /* HP 53xx R2 */ + dev->inquiry_line_difference /= 2; /* HP 5300 */ + break; + case AV_ASIC_C7: + dev->inquiry_line_difference *= 2; /* AV610C2 */ + break; + default: + ; + } if (dev->inquiry_new_protocol) { dev->inquiry_optical_res = get_double ( &(result[89]) ); @@ -3824,6 +4072,10 @@ get_double ( &(result[48] ) )); dev->inquiry_tune_scan_length = BIT(result[94],2); dev->inquiry_background_raster = BIT(result[95],2); + + if (dev->hw->feature_type & AV_NO_BACKGROUND) + dev->inquiry_background_raster = 0; + if (dev->inquiry_background_raster) { dev->inquiry_background_raster_pixel = get_double(&(result[85])) * dev->inquiry_optical_res / AVISION_BASE_RES; @@ -3958,7 +4210,6 @@ get_tune_scan_length (Avision_Scanner* s) static SANE_Status send_tune_scan_length (Avision_Scanner* s) { - Avision_Device* dev = s->hw; int top, bottom; SANE_Status status; @@ -3966,7 +4217,7 @@ send_tune_scan_length (Avision_Scanner* s) struct command_send scmd; struct truncate_attach { uint8_t vertical [2]; - uint8_t horizontal [2]; + /* uint8_t horizontal [2]; not send by the Windows driver, yet */ } payload; DBG (3, "send_tune_scan_length:\n"); @@ -3985,7 +4236,7 @@ send_tune_scan_length (Avision_Scanner* s) set_double (scmd.datatypequal, 0x0001); /* attach, 0x000 is shorten */ set_double (payload.vertical, top); - set_double (payload.horizontal, 0); + /* set_double (payload.horizontal, 0); */ /* we alway send it, even for 0 as the scanner keeps it in RAM and previous runs could aleady have set something */ @@ -3996,19 +4247,14 @@ send_tune_scan_length (Avision_Scanner* s) if (status != SANE_STATUS_GOOD) { DBG (1, "send_tune_scan_length: send top/left failed (%s)\n", sane_strstatus (status)); return status; - } - - if (dev->hw->feature_type & AV_NO_TUNE_BOTTOM) { - DBG (1, "send_tune_scan_length: tune bottom disabled due device list\n"); - return SANE_STATUS_GOOD; } - + scmd.datatypecode = 0x95; /* Attach/Truncate tail(right) of scan length */ bottom = 1200 * SANE_UNFIX (s->val[OPT_OVERSCAN_BOTTOM].w) / MM_PER_INCH; DBG (3, "send_tune_scan_length: bottom: %d\n", bottom); set_double (payload.vertical, bottom); - set_double (payload.horizontal, 0); + /*set_double (payload.horizontal, 0); */ size = sizeof (payload); status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), @@ -4241,16 +4487,17 @@ set_calib_data (Avision_Scanner* s, struct calibration_format* format, { Avision_Device* dev = s->hw; - struct command_send scmd; + const int elements_per_line = format->pixel_per_line * format->channels; SANE_Status status; uint8_t send_type; uint16_t send_type_q; + struct command_send scmd; + int i; size_t out_size; - int elements_per_line = format->pixel_per_line * format->channels; DBG (3, "set_calib_data:\n"); @@ -4375,9 +4622,10 @@ set_calib_data (Avision_Scanner* s, struct calibration_format* format, static uint8_t* sort_and_average (struct calibration_format* format, uint8_t* data) { - int stride, i, line; - int elements_per_line; - + const int elements_per_line = format->pixel_per_line * format->channels; + const int stride = format->bytes_per_channel * elements_per_line; + int i, line; + uint8_t *sort_data, *avg_data; DBG (1, "sort_and_average:\n"); @@ -4474,7 +4722,7 @@ compute_white_shading_data (Avision_Scanner* s, { int i; uint16_t inquiry_mst = DEFAULT_WHITE_SHADING; - uint16_t mst[3], result; + uint16_t mst[3]; int elements_per_line = format->pixel_per_line * format->channels; @@ -4634,7 +4882,19 @@ normal_calibration (Avision_Scanner* s) free (calib_tmp_data); return status; } - + + if (0) /* debug */ + { + FILE* f = NULL; + f = fopen ("calibration-white.pnm", "w"); + write_pnm_header (f, AV_GRAYSCALE, calib_format.bytes_per_channel * 8, + calib_format.pixel_per_line, + calib_format.lines * calib_format.channels); + + fwrite (calib_tmp_data, 1, calib_data_size, f); + fclose (f); + } + if (s->white_avg_data) { free (s->white_avg_data); s->white_avg_data = 0; @@ -4890,27 +5150,28 @@ send_3x3_matrix (Avision_Scanner* s) #define SIGN_BIT 0x1000 #define INT_PART 10 - struct command_send scmd; - struct matrix_3x3 matrix; + struct matrix_cmd + { + struct command_send scmd; + struct matrix_3x3 matrix; + } cmd; /* 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 04 00 */ int i, a_i; - double c5_matrix[] = - { 1.3042, -0.1475, -0.1567, - -0.1413, 1.2007, -0.0594, - -0.0335, -0.1274, 1.1609 - }; + static const double c5_matrix[] = + { 1.000, 0.000, 0.000, + 0.000, 1.000, 0.000, + 0.000, 0.000, 1.000 }; double a_f, b_f; uint16_t m; DBG (3, "send_3x3_matrix:\n"); - memset (&scmd, 0, sizeof (scmd)); - memset (&matrix, 0, sizeof (matrix)); + memset (&cmd, 0, sizeof (cmd)); for (i = 0; i < 9; i++) { @@ -4921,18 +5182,27 @@ send_3x3_matrix (Avision_Scanner* s) a_f = -a_f; } - a_i = (int) a_f; /* integer */ - b_f = a_f - (double) a_i; /*float */ - m = m | ((a_i & 0x3) << INT_PART); - m = m | (uint16_t) (b_f * 1024); - set_double ( ((uint8_t*)(&matrix.v[i])), m); + a_i = (int) a_f; /* integer */ + b_f = a_f - (double) a_i; /* float */ + m |= ((a_i & 0x3) << INT_PART); + m |= (uint16_t) (b_f * 1024); + set_double (((u_int8_t*)(&cmd.matrix.v[i])), m); } - scmd.opc = AVISION_SCSI_SEND; - scmd.datatypecode = 0x83; /* 0x83 for 3x3 color matrix */ - set_triple (scmd.transferlen, sizeof (matrix)); - DBG (3, "send_3x3_matrix: sending matrix\n"); - status = avision_cmd (&s->av_con, &scmd, sizeof (scmd), &matrix, sizeof(matrix), 0, 0); + cmd.scmd.opc = AVISION_SCSI_SEND; + cmd.scmd.datatypecode = 0x83; /* 0x83 for 3x3 color matrix */ + set_triple (cmd.scmd.transferlen, sizeof (struct matrix_3x3)); + + if (1) { + DBG (3, "send_3x3_matrix: sending matrix split into two commands\n"); + status = avision_cmd (&s->av_con, &cmd.scmd, sizeof (cmd.scmd), + &cmd.matrix, sizeof(cmd.matrix), 0, 0); + } + else { + DBG (3, "send_3x3_matrix: sending matrix in one command\n"); + status = avision_cmd (&s->av_con, &cmd, sizeof (cmd), 0, 0, 0, 0); + } + return status; } @@ -5212,7 +5482,7 @@ set_window (Avision_Scanner* s) line_count * base_dpi_rel / s->avdimen.hw_yres + 1); /* interlaced duplex scans are twice as long */ - if (s->avdimen.interlaced_duplex) { + if (s->avdimen.interlaced_duplex && dev->scanner_type != AV_FILM) { DBG (2, "set_window: interlaced duplex scan, doubled line count\n"); line_count *= 2; } @@ -5304,9 +5574,17 @@ set_window (Avision_Scanner* s) } if (dev->scanner_type == AV_FILM) { - set_double (cmd.window.avision.type.normal.r_exposure_time, 0x016d); - set_double (cmd.window.avision.type.normal.g_exposure_time, 0x016d); - set_double (cmd.window.avision.type.normal.b_exposure_time, 0x016d); + /* TODO: wire to IR exposure option? */ + cmd.window.avision.type.normal.ir_exposure_time = 100; + set_double (cmd.window.avision.type.normal.r_exposure_time, s->val[OPT_EXPOSURE].w); + set_double (cmd.window.avision.type.normal.g_exposure_time, s->val[OPT_EXPOSURE].w); + set_double (cmd.window.avision.type.normal.b_exposure_time, s->val[OPT_EXPOSURE].w); + + if (s->val[OPT_IR].w) + cmd.window.avision.type.normal.bitset3 |= (1 << 0); + + if (s->val[OPT_MULTISAMPLE].w) + cmd.window.avision.type.normal.bitset3 |= (1 << 1); } } @@ -5399,13 +5677,19 @@ get_background_raster (Avision_Scanner* s) SANE_Status status; struct command_read rcmd; - size_t size, read_size; + size_t size; int bytes_per_line, i; const int bpp = color_mode_is_color (s->c_mode) ? 3 : 1; + const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); uint8_t* background = NULL; DBG (1, "get_background_raster:\n"); + + if (lines == 0) { + DBG (1, "get_background_raster: no background requested\n"); + return SANE_STATUS_GOOD; + } /* full width, always :-(, duplex *2 for front and rear */ bytes_per_line = dev->inquiry_background_raster_pixel * @@ -5416,17 +5700,11 @@ get_background_raster (Avision_Scanner* s) dev->inquiry_background_raster_pixel, bytes_per_line); /* according to spec only 8-bit gray or color, TODO: test for bi-level scans */ - size = bytes_per_line * s->val[OPT_BACKGROUND].w; + size = bytes_per_line * lines; - DBG (3, "get_background_raster: buffer size: %ld\n", size); + DBG (3, "get_background_raster: buffer size: %ld\n", (long)size); - if (size == 0) { - DBG (1, "get_background_raster: no background requested\n"); - return SANE_STATUS_GOOD; - } - - background = s->background_raster = realloc (s->background_raster, size * - (s->avdimen.interlaced_duplex ? 2 : 1)); + background = s->background_raster = realloc (s->background_raster, size); if (!background) return SANE_STATUS_NO_MEM; @@ -5435,60 +5713,65 @@ get_background_raster (Avision_Scanner* s) rcmd.datatypecode = 0x9b; /* get background raster */ set_double (rcmd.datatypequal, s->hw->data_dq); - /* so far either line by line, or stripe by stripe */ - if (s->avdimen.interlaced_duplex && dev->hw->feature_type & AV_2ND_LINE_INTERLACED) + /* Ok, well - this part is very messy. The AV122 and DM152 appear to + contain differently buggy ASICs. The only combination I found to + at least get a correct front raster out of them is to read it + line by line and then every second line appears to be valid front + data, ... */ + + /* read the raster data */ + for (i = 0; i < lines;) { - set_triple (rcmd.transferlen, bytes_per_line); + uint8_t* dst_raster = background + bytes_per_line * i; + /* read stripe by stripe, or all in one chunk */ + size_t this_read, read_size; + int this_lines; - for (i = 0; - i < s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); - ++i) - { - uint8_t* dst_raster = background + - bytes_per_line * (i / 2 + (i % 2) * s->val[OPT_BACKGROUND].w); - DBG (3, "get_background_raster: interlaced line: %d, %lu bytes\n", - i, (u_long) bytes_per_line); - - size = bytes_per_line; - read_size = size; - status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size); - if (status != SANE_STATUS_GOOD || read_size != size) { - DBG (1, "get_background_raster: read raster failed (%s)\n", - sane_strstatus (status) ); - return status; - } - } - } - else - { - set_triple (rcmd.transferlen, size); + if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) { + if (dev->hw->feature_type & AV_BACKGROUND_QUIRK) + this_lines = 1; + else + this_lines = lines; + } + else { + this_lines = s->val[OPT_BACKGROUND].w; + } + this_read = bytes_per_line * this_lines; - for (i = 0; - i < (s->avdimen.interlaced_duplex ? 2 : 1); - ++i) - { - uint8_t* dst_raster = background + size * i; - DBG (3, "get_background_raster: stripe: %d, %lu bytes\n", - i, (u_long) size); - - read_size = size; - status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size); - if (status != SANE_STATUS_GOOD || read_size != size) { - DBG (1, "get_background_raster: read raster failed (%s)\n", - sane_strstatus (status) ); - return status; - } - } + DBG (3, "get_background_raster: line: %d, lines: %d, %lu bytes\n", + i, this_lines, (u_long) this_read); + + set_triple (rcmd.transferlen, this_read); + + read_size = this_read; + status = avision_cmd (&s->av_con, &rcmd, sizeof (rcmd), 0, 0, dst_raster, &read_size); + if (status != SANE_STATUS_GOOD || read_size != this_read) { + DBG (1, "get_background_raster: read raster failed (%s)\n", + sane_strstatus (status) ); + return status; + } + + i += this_lines; } - size = 0; - + /* dump raw result while debugging */ + if (debug) + { + FILE* f = NULL; + f = fopen ("background-raw.pnm", "w"); + + write_pnm_header (f, (color_mode_is_color (s->c_mode) ? AV_TRUECOLOR : AV_GRAYSCALE), 8, + bytes_per_line / bpp, lines); + + fwrite (background, 1, bytes_per_line * lines, f); + fclose (f); + } + /* line-pack - move to unified processing flow, later */ if (dev->inquiry_needs_line_pack) { /* TODO: add 16bit per sample code? */ int l, p; - const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); uint8_t* tmp_data = malloc (bytes_per_line); for (l = 0; l < lines; ++l) @@ -5509,10 +5792,38 @@ get_background_raster (Avision_Scanner* s) free (tmp_data); } /* end line pack */ - + + /* deinterlace? */ + if (s->avdimen.interlaced_duplex && dev->hw->feature_type & AV_2ND_LINE_INTERLACED) + { + uint8_t* deinterlaced = malloc (size * 2); + if (!deinterlaced) + return SANE_STATUS_NO_MEM; + + for (i = 0; i < lines; ++i) + { + int dst_i = i / 2 + (i % 2) * (lines / 2); + uint8_t* dst_raster; /* just no C99 in SANE :-( */ + uint8_t* src_raster; + + /* for the quirky devices and some resolutions the interlacing differs */ + if (dev->hw->feature_type & AV_BACKGROUND_QUIRK && s->avdimen.hw_xres >= 150) + dst_i = i / 2 + ((i+1) % 2) * (lines / 2); + + dst_raster = deinterlaced + bytes_per_line * dst_i; + src_raster = background + bytes_per_line * i; + + DBG(3, "get_background_raster: deinterlaced %d -> %d\n", i, dst_i); + memcpy(dst_raster, src_raster, bytes_per_line); + } + + free (background); + background = s->background_raster = deinterlaced; + } + /* dump raw result while debugging */ for (i = 0; debug && i < (s->avdimen.interlaced_duplex ? 2 : 1); ++i) - { + { FILE* f = NULL; uint8_t* raster = background; if (i == 0) { @@ -5535,9 +5846,7 @@ get_background_raster (Avision_Scanner* s) uint8_t *dst_ptr, *src_ptr; dst_ptr = background; src_ptr = background + s->avdimen.tlx * bpp; - for (i = 0; - i < s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); - ++i) + for (i = 0; i < lines; ++i) { memmove (dst_ptr, src_ptr, s->avdimen.hw_bytes_per_line); dst_ptr += s->avdimen.hw_bytes_per_line; @@ -5548,7 +5857,6 @@ get_background_raster (Avision_Scanner* s) /* soft-scale - move to unified processing flow, later */ if (s->avdimen.hw_xres != s->avdimen.xres) { - const int lines = s->val[OPT_BACKGROUND].w * (s->avdimen.interlaced_duplex ? 2 : 1); const uint8_t* out_data = background; uint8_t* dst = background; @@ -5991,7 +6299,7 @@ init_options (Avision_Scanner* s) if (!dev->inquiry_tune_scan_length) s->opt[OPT_OVERSCAN_TOP].cap |= SANE_CAP_INACTIVE; - if (!dev->inquiry_tune_scan_length || dev->hw->feature_type & AV_NO_TUNE_BOTTOM) + if (!dev->inquiry_tune_scan_length) s->opt[OPT_OVERSCAN_BOTTOM].cap |= SANE_CAP_INACTIVE; /* background raster */ @@ -6115,7 +6423,49 @@ init_options (Avision_Scanner* s) s->opt[OPT_GAMMA_VECTOR].cap &= ~SANE_CAP_INACTIVE; } } + + /* exposure */ + s->opt[OPT_EXPOSURE].name = "exposure"; + s->opt[OPT_EXPOSURE].title = "Exposure"; + s->opt[OPT_EXPOSURE].desc = "Manual exposure adjustment."; + s->opt[OPT_EXPOSURE].type = SANE_TYPE_INT; + s->opt[OPT_EXPOSURE].unit = SANE_UNIT_PERCENT; + s->opt[OPT_EXPOSURE].constraint_type = SANE_CONSTRAINT_RANGE; + s->opt[OPT_EXPOSURE].constraint.range = &exposure_range; + s->val[OPT_EXPOSURE].w = 100; + + if (!dev->inquiry_exposure_control) { + s->opt[OPT_EXPOSURE].cap |= SANE_CAP_INACTIVE; + } + /* Multi sample */ + s->opt[OPT_MULTISAMPLE].name = "multi-sample"; + s->opt[OPT_MULTISAMPLE].title = "Multi-sample"; + s->opt[OPT_MULTISAMPLE].desc = "Enable multi-sample scan mode."; + s->opt[OPT_MULTISAMPLE].type = SANE_TYPE_BOOL; + s->opt[OPT_MULTISAMPLE].unit = SANE_UNIT_NONE; + s->val[OPT_MULTISAMPLE].w = SANE_FALSE; + + /* TODO: No idea how to detect, assume exosure control devices are + new enough to support this, for now. -ReneR */ + if (!dev->inquiry_exposure_control) { + s->opt[OPT_MULTISAMPLE].cap |= SANE_CAP_INACTIVE; + } + + /* Infra-red */ + s->opt[OPT_IR].name = "infra-red"; + s->opt[OPT_IR].title = "Infra-red"; + s->opt[OPT_IR].desc = "Enable infra-red scan mode."; + s->opt[OPT_IR].type = SANE_TYPE_BOOL; + s->opt[OPT_IR].unit = SANE_UNIT_NONE; + s->val[OPT_IR].w = SANE_FALSE; + + /* TODO: No idea how to detect, assume exosure control devices are + new enough to support this, for now. -ReneR */ + if (!dev->inquiry_exposure_control) { + s->opt[OPT_IR].cap |= SANE_CAP_INACTIVE; + } + /* film holder control */ if (dev->scanner_type != AV_FILM) s->opt[OPT_FRAME].cap |= SANE_CAP_INACTIVE; @@ -6258,6 +6608,9 @@ reader_process (void *data) deinterlace = HALF; if (dev->hw->feature_type & AV_2ND_LINE_INTERLACED) deinterlace = LINE; + + if (dev->scanner_type == AV_FILM) + deinterlace = LINE; } fp = fdopen (fd, "w"); @@ -7322,7 +7675,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle *handle) /* initilize the options */ init_options (s); - if (dev->inquiry_duplex_interlaced) { + if (dev->inquiry_duplex_interlaced || dev->scanner_type == AV_FILM) { /* Might need at least *DOS (Windows flavour and OS/2) portability fix However, I was was told Cygwin (et al.) does keep care of it. */ strncpy(s->duplex_rear_fname, "/tmp/avision-rear-XXXXXX", PATH_MAX); @@ -7459,6 +7812,12 @@ sane_control_option (SANE_Handle handle, SANE_Int option, DBG (3, "sane_control_option: option=%d, action=%d\n", (int)option, (int)action); + DBG (5, "sane_control_option: option=%s, action=%s\n", + s->opt[option].name, + action == SANE_ACTION_GET_VALUE ? "GET" : + (action == SANE_ACTION_SET_VALUE ? "SET" : + (action == SANE_ACTION_SET_AUTO ? "AUTO" : "UNKNOWN") ) ); + if (info) *info = 0; @@ -7493,6 +7852,9 @@ sane_control_option (SANE_Handle handle, SANE_Int option, case OPT_BRIGHTNESS: case OPT_CONTRAST: + case OPT_EXPOSURE: + case OPT_IR: + case OPT_MULTISAMPLE: case OPT_QSCAN: case OPT_QCALIB: *(SANE_Word*) val = s->val[option].w; @@ -7530,6 +7892,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, status = get_button_status (s); strcpy (val, s->val[option].s); + s->val[option].s[0] = 0; return SANE_STATUS_GOOD; case OPT_NVRAM: @@ -7556,6 +7919,9 @@ sane_control_option (SANE_Handle handle, SANE_Int option, case OPT_PREVIEW: case OPT_BRIGHTNESS: case OPT_CONTRAST: + case OPT_EXPOSURE: + case OPT_IR: + case OPT_MULTISAMPLE: case OPT_QSCAN: case OPT_QCALIB: case OPT_OVERSCAN_TOP: diff --git a/backend/avision.h b/backend/avision.h index 1ff8d951d..d0fb1963e 100644 --- a/backend/avision.h +++ b/backend/avision.h @@ -115,8 +115,8 @@ typedef struct Avision_HWEntry { /* if the scan area and resolution needs to be forced for films */ AV_FORCE_FILM = (1<<6), - /* does not support bottom overscan, sigh */ - AV_NO_TUNE_BOTTOM = (1<<7), + /* does not suport, or very broken background (added for AV610C2) */ + AV_NO_BACKGROUND = (1<<7), /* is film scanner - no detection yet */ AV_FILMSCANNER = (1<<8), @@ -160,8 +160,8 @@ typedef struct Avision_HWEntry { /* allows 12bit mode, though not flagged */ AV_12_BIT_MODE = (1<<21), - /* scanner always (mistakenly) advertises a transparency adapter */ - AV_NO_TRANSPARENCY = (1<<22), + /* very broken background raster */ + AV_BACKGROUND_QUIRK = (1<<22), /* though marked as GRAY only the scanner can do GRAY modes */ AV_GRAY_MODES = (1<<23), @@ -271,6 +271,10 @@ enum Avision_Option OPT_GAMMA_VECTOR_R, /* then r g b vector */ OPT_GAMMA_VECTOR_G, OPT_GAMMA_VECTOR_B, + + OPT_EXPOSURE, /* film exposure adjustment */ + OPT_IR, /* infra-red */ + OPT_MULTISAMPLE, /* multi-sample */ OPT_FRAME, /* Film holder control */ @@ -350,6 +354,8 @@ typedef struct Avision_Device SANE_Bool inquiry_adf_bgr_order; SANE_Bool inquiry_light_detect; SANE_Bool inquiry_light_control; + SANE_Bool inquiry_exposure_control; + int inquiry_max_shading_target; SANE_Bool inquiry_button_control; unsigned int inquiry_buttons;