From ccfc476a07e396d78b4a3579373b775d724e78ab Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 12:08:29 +0100 Subject: [PATCH 01/49] Prepare backend build files --- .gitignore | 4 ++ backend/Makefile.am | 25 +++++++++-- backend/lexmark_x2600.c | 81 +++++++++++++++++++++++++++++++++++ backend/lexmark_x2600.conf.in | 2 + backend/lexmark_x2600.h | 5 +++ configure.ac | 3 +- doc/Makefile.am | 4 +- doc/sane-lexmark_x2600.man | 0 8 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 backend/lexmark_x2600.c create mode 100644 backend/lexmark_x2600.conf.in create mode 100644 backend/lexmark_x2600.h create mode 100644 doc/sane-lexmark_x2600.man diff --git a/.gitignore b/.gitignore index bd3b38363..e5451942c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,7 @@ test-suite.log # `make dist` artifacts /sane-backends-*.tar.gz + +# editor temp files +*~ +\#*\# diff --git a/backend/Makefile.am b/backend/Makefile.am index 35ad206f9..5f2587bf9 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -75,8 +75,8 @@ BACKEND_CONFS= abaton.conf agfafocus.conf apple.conf artec.conf \ epson.conf epsonds.conf escl.conf fujitsu.conf genesys.conf \ gphoto2.conf gt68xx.conf hp3900.conf hp4200.conf hp5400.conf \ hp.conf hpsj5s.conf hs2p.conf ibm.conf kodak.conf kodakaio.conf\ - kvs1025.conf \ - leo.conf lexmark.conf ma1509.conf magicolor.conf \ + kvs1025.conf leo.conf lexmark.conf lexmark_x2600.conf \ + ma1509.conf magicolor.conf \ matsushita.conf microtek2.conf microtek.conf mustek.conf \ mustek_pp.conf mustek_usb.conf nec.conf net.conf \ p5.conf \ @@ -173,7 +173,7 @@ be_convenience_libs = libabaton.la libagfafocus.la \ libhp5400.la libhp5590.la libhpljm1005.la \ libhpsj5s.la libhs2p.la libibm.la libkodak.la libkodakaio.la\ libkvs1025.la libkvs20xx.la libkvs40xx.la \ - libleo.la liblexmark.la libma1509.la libmagicolor.la \ + libleo.la liblexmark.la liblexmark_x2600.la libma1509.la libmagicolor.la \ libmatsushita.la libmicrotek.la libmicrotek2.la \ libmustek.la libmustek_pp.la libmustek_usb.la \ libmustek_usb2.la libnec.la libnet.la \ @@ -208,7 +208,7 @@ be_dlopen_libs = libsane-abaton.la libsane-agfafocus.la \ libsane-hpsj5s.la libsane-hs2p.la libsane-ibm.la libsane-kodak.la libsane-kodakaio.la\ libsane-kvs1025.la libsane-kvs20xx.la libsane-kvs40xx.la \ libsane-leo.la \ - libsane-lexmark.la libsane-ma1509.la libsane-magicolor.la \ + libsane-lexmark.la libsane-lexmark_x2600.la libsane-ma1509.la libsane-magicolor.la \ libsane-matsushita.la libsane-microtek.la libsane-microtek2.la \ libsane-mustek.la libsane-mustek_pp.la libsane-mustek_usb.la \ libsane-mustek_usb2.la libsane-nec.la libsane-net.la \ @@ -1147,6 +1147,23 @@ EXTRA_DIST += lexmark.conf.in # TODO: Why are these distributed but not compiled? EXTRA_DIST += lexmark_models.c lexmark_sensors.c +liblexmark_x2600_la_SOURCES = lexmark_x2600.c lexmark_x2600.h +liblexmark_x2600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark_x2600 + +nodist_libsane_lexmark_x2600_la_SOURCES = lexmark_x2600-s.c +libsane_lexmark_x2600_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=lexmark_x2600 +libsane_lexmark_x2600_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) +libsane_lexmark_x2600_la_LIBADD = $(COMMON_LIBS) \ + liblexmark_x2600.la \ + ../sanei/sanei_init_debug.lo \ + ../sanei/sanei_constrain_value.lo \ + ../sanei/sanei_config.lo \ + ../sanei/sanei_config2.lo \ + sane_strstatus.lo \ + ../sanei/sanei_scsi.lo \ + $(SCSI_LIBS) $(RESMGR_LIBS) +EXTRA_DIST += lexmark_x2600.conf.in + libma1509_la_SOURCES = ma1509.c ma1509.h libma1509_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=ma1509 diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c new file mode 100644 index 000000000..9ae918dee --- /dev/null +++ b/backend/lexmark_x2600.c @@ -0,0 +1,81 @@ +#include "lexmark_x2600.h" +#include "../include/sane/sanei_backend.h" + +SANE_Status +sane_init (SANE_Int *vc, SANE_Auth_Callback cb) +{ + return ENTRY(init) (vc, cb); +} + +SANE_Status +sane_get_devices (const SANE_Device ***dl, SANE_Bool local) +{ + return ENTRY(get_devices) (dl, local); +} + +SANE_Status +sane_open (SANE_String_Const name, SANE_Handle *h) +{ + return ENTRY(open) (name, h); +} + +const SANE_Option_Descriptor * +sane_get_option_descriptor (SANE_Handle h, SANE_Int opt) +{ + return ENTRY(get_option_descriptor) (h, opt); +} + +SANE_Status +sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, + void *val, SANE_Word *info) +{ + return ENTRY(control_option) (h, opt, act, val, info); +} + +SANE_Status +sane_get_parameters (SANE_Handle h, SANE_Parameters *parms) +{ + return ENTRY(get_parameters) (h, parms); +} + +SANE_Status +sane_start (SANE_Handle h) +{ + return ENTRY(start) (h); +} + +SANE_Status +sane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) +{ + return ENTRY(read) (h, buf, maxlen, lenp); +} + +SANE_Status +sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) +{ + return ENTRY(set_io_mode) (h, non_blocking); +} + +SANE_Status +sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) +{ + return ENTRY(get_select_fd) (h, fdp); +} + +void +sane_cancel (SANE_Handle h) +{ + ENTRY(cancel) (h); +} + +void +sane_close (SANE_Handle h) +{ + ENTRY(close) (h); +} + +void +sane_exit (void) +{ + ENTRY(exit) (); +} diff --git a/backend/lexmark_x2600.conf.in b/backend/lexmark_x2600.conf.in new file mode 100644 index 000000000..c0308228a --- /dev/null +++ b/backend/lexmark_x2600.conf.in @@ -0,0 +1,2 @@ +# X26xx series +usb 0x043d 0x011d diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h new file mode 100644 index 000000000..69499d0b3 --- /dev/null +++ b/backend/lexmark_x2600.h @@ -0,0 +1,5 @@ +#ifndef LEXMARK_X2600_H +#define LEXMARK_X2600_H + + +#endif /* LEXMARK_X2600_H */ diff --git a/configure.ac b/configure.ac index a763be518..85a611e1d 100644 --- a/configure.ac +++ b/configure.ac @@ -645,7 +645,7 @@ ALL_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e \ dell1600n_net dmc epjitsu epson epson2 epsonds escl fujitsu \ genesys gphoto2 gt68xx hp hp3500 hp3900 hp4200 hp5400 \ hp5590 hpsj5s hpljm1005 hs2p ibm kodak kodakaio kvs1025 kvs20xx \ - kvs40xx leo lexmark ma1509 magicolor \ + kvs40xx leo lexmark lexmark_x2600 ma1509 magicolor \ matsushita microtek microtek2 mustek mustek_pp \ mustek_usb mustek_usb2 nec net niash pie pieusb pint \ pixma plustek plustek_pp qcam ricoh ricoh2 rts8891 s9036 \ @@ -707,6 +707,7 @@ AC_SUBST(BACKEND_LIBS_ENABLED) AM_CONDITIONAL(WITH_GENESYS_TESTS, test xyes = x$with_genesys_tests) AM_CONDITIONAL(INSTALL_UMAX_PP_TOOLS, test xyes = x$install_umax_pp_tools) + AC_ARG_VAR(PRELOADABLE_BACKENDS, [list of backends to preload into single DLL]) if test "${enable_preload}" = "auto"; then if test "${enable_shared}" = "no" || test "${enable_dynamic}" != "yes"; then diff --git a/doc/Makefile.am b/doc/Makefile.am index 7dbbfaf15..083a0f4c7 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -38,7 +38,7 @@ BACKEND_5MANS = sane-abaton.5 sane-agfafocus.5 sane-apple.5 sane-as6e.5 \ sane-hp5590.5 sane-hpljm1005.5 sane-cardscan.5 sane-hp3900.5 \ sane-epjitsu.5 sane-hs2p.5 sane-canon_dr.5 sane-xerox_mfp.5 \ sane-rts8891.5 sane-coolscan3.5 sane-kvs1025.5 sane-kvs20xx.5 \ - sane-kvs40xx.5 sane-p5.5 sane-magicolor.5 + sane-kvs40xx.5 sane-p5.5 sane-magicolor.5 sane-lexmark_x2600.5 EXTRA_DIST += sane-abaton.man sane-agfafocus.man sane-apple.man sane-as6e.man \ sane-canon_lide70.man \ @@ -64,7 +64,7 @@ EXTRA_DIST += sane-abaton.man sane-agfafocus.man sane-apple.man sane-as6e.man \ sane-cardscan.man sane-hp3900.man sane-epjitsu.man sane-hs2p.man \ sane-canon_dr.man sane-xerox_mfp.man sane-rts8891.man \ sane-coolscan3.man sane-kvs1025.man sane-kvs20xx.man sane-kvs40xx.man \ - sane-p5.man sane-magicolor.man + sane-p5.man sane-magicolor.man sane-lexmark_x2600.man man7_MANS = sane.7 EXTRA_DIST += sane.man diff --git a/doc/sane-lexmark_x2600.man b/doc/sane-lexmark_x2600.man new file mode 100644 index 000000000..e69de29bb From b19b324bf736f31360342fc14cd6bfbbb71dc1c1 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 12:49:58 +0100 Subject: [PATCH 02/49] remove warnings --- backend/lexmark_x2600.c | 53 +++++++++++++++++++++-------------------- backend/lexmark_x2600.h | 9 +++++++ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 9ae918dee..620a61fb6 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1,81 +1,82 @@ #include "lexmark_x2600.h" -#include "../include/sane/sanei_backend.h" SANE_Status -sane_init (SANE_Int *vc, SANE_Auth_Callback cb) +sane_init (SANE_Int __sane_unused__ *vc, SANE_Auth_Callback __sane_unused__ cb) { - return ENTRY(init) (vc, cb); + DBG_INIT (); + DBG (1, "SANE Lexmark_x2600 backend "); + return SANE_STATUS_GOOD; } SANE_Status -sane_get_devices (const SANE_Device ***dl, SANE_Bool local) +sane_get_devices (const SANE_Device __sane_unused__ ***dl, SANE_Bool __sane_unused__ local) { - return ENTRY(get_devices) (dl, local); + return SANE_STATUS_GOOD; } SANE_Status -sane_open (SANE_String_Const name, SANE_Handle *h) +sane_open (SANE_String_Const __sane_unused__ name, SANE_Handle __sane_unused__ *h) { - return ENTRY(open) (name, h); + return SANE_STATUS_GOOD; } const SANE_Option_Descriptor * -sane_get_option_descriptor (SANE_Handle h, SANE_Int opt) +sane_get_option_descriptor (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt) { return ENTRY(get_option_descriptor) (h, opt); } SANE_Status -sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act, - void *val, SANE_Word *info) +sane_control_option (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt, SANE_Action __sane_unused__ act, + void __sane_unused__ *val, SANE_Word __sane_unused__ *info) { - return ENTRY(control_option) (h, opt, act, val, info); + return SANE_STATUS_GOOD; } SANE_Status -sane_get_parameters (SANE_Handle h, SANE_Parameters *parms) +sane_get_parameters (SANE_Handle __sane_unused__ h, SANE_Parameters __sane_unused__ *parms) { - return ENTRY(get_parameters) (h, parms); + return SANE_STATUS_GOOD; } SANE_Status -sane_start (SANE_Handle h) +sane_start (SANE_Handle __sane_unused__ h) { - return ENTRY(start) (h); + return SANE_STATUS_GOOD; } SANE_Status -sane_read (SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp) +sane_read (SANE_Handle __sane_unused__ h, SANE_Byte __sane_unused__ *buf, SANE_Int __sane_unused__ maxlen, SANE_Int __sane_unused__ *lenp) { - return ENTRY(read) (h, buf, maxlen, lenp); + return SANE_STATUS_GOOD; } SANE_Status -sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking) +sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ non_blocking) { - return ENTRY(set_io_mode) (h, non_blocking); + return SANE_STATUS_GOOD; } SANE_Status -sane_get_select_fd (SANE_Handle h, SANE_Int *fdp) +sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ *fdp) { - return ENTRY(get_select_fd) (h, fdp); + return SANE_STATUS_GOOD; } void -sane_cancel (SANE_Handle h) +sane_cancel (SANE_Handle __sane_unused__ h) { - ENTRY(cancel) (h); + } void -sane_close (SANE_Handle h) +sane_close (SANE_Handle __sane_unused__ h) { - ENTRY(close) (h); + } void sane_exit (void) { - ENTRY(exit) (); + } diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index 69499d0b3..e42c4c5a2 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -1,5 +1,14 @@ #ifndef LEXMARK_X2600_H #define LEXMARK_X2600_H +#include "../include/sane/config.h" + +#include "../include/sane/sane.h" +#include "../include/sane/sanei.h" +#include "../include/sane/saneopts.h" +#include "../include/sane/sanei_config.h" +#include "../include/sane/sanei_usb.h" +#include "../include/sane/sanei_backend.h" + #endif /* LEXMARK_X2600_H */ From 8509c9dff4aceb3d8ac3e0504a5708b9a8d0437b Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 12:52:32 +0100 Subject: [PATCH 03/49] trailing white space --- backend/lexmark_x2600.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 620a61fb6..ce2721092 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -66,17 +66,17 @@ sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ *fdp void sane_cancel (SANE_Handle __sane_unused__ h) { - + } void sane_close (SANE_Handle __sane_unused__ h) { - + } void sane_exit (void) { - + } From 179257160bf10ea90ddb73fc43da646f4028ed20 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 13:05:06 +0100 Subject: [PATCH 04/49] fix fedora build --- backend/lexmark_x2600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index ce2721092..8cb54ffb9 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -23,7 +23,7 @@ sane_open (SANE_String_Const __sane_unused__ name, SANE_Handle __sane_unused__ * const SANE_Option_Descriptor * sane_get_option_descriptor (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt) { - return ENTRY(get_option_descriptor) (h, opt); + return NULL; } SANE_Status From ba3fd1dc4c49326011b0e0d079252ada3cd033f3 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 17:36:37 +0100 Subject: [PATCH 05/49] remove new line --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index 85a611e1d..b254e1d23 100644 --- a/configure.ac +++ b/configure.ac @@ -707,7 +707,6 @@ AC_SUBST(BACKEND_LIBS_ENABLED) AM_CONDITIONAL(WITH_GENESYS_TESTS, test xyes = x$with_genesys_tests) AM_CONDITIONAL(INSTALL_UMAX_PP_TOOLS, test xyes = x$install_umax_pp_tools) - AC_ARG_VAR(PRELOADABLE_BACKENDS, [list of backends to preload into single DLL]) if test "${enable_preload}" = "auto"; then if test "${enable_shared}" = "no" || test "${enable_dynamic}" != "yes"; then From a9c3cfa4d74be6f6d96750e350cc27c17fd2b111 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 18:01:04 +0100 Subject: [PATCH 06/49] fix usb dependancies --- backend/Makefile.am | 5 ++--- backend/lexmark_x2600.c | 15 +++++++++++++-- backend/lexmark_x2600.h | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/backend/Makefile.am b/backend/Makefile.am index 5f2587bf9..86b1d1f08 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -1158,10 +1158,9 @@ libsane_lexmark_x2600_la_LIBADD = $(COMMON_LIBS) \ ../sanei/sanei_init_debug.lo \ ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_config.lo \ - ../sanei/sanei_config2.lo \ sane_strstatus.lo \ - ../sanei/sanei_scsi.lo \ - $(SCSI_LIBS) $(RESMGR_LIBS) + ../sanei/sanei_usb.lo \ + $(USB_LIBS) $(RESMGR_LIBS) EXTRA_DIST += lexmark_x2600.conf.in libma1509_la_SOURCES = ma1509.c ma1509.h diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 8cb54ffb9..adf4c8ac3 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1,10 +1,21 @@ +#define BUILD 1 #include "lexmark_x2600.h" SANE_Status -sane_init (SANE_Int __sane_unused__ *vc, SANE_Auth_Callback __sane_unused__ cb) +sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) { DBG_INIT (); - DBG (1, "SANE Lexmark_x2600 backend "); + DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", + version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); + DBG (1, "sane_init: SANE lexmark_x2600 backend version %d.%d.%d from %s\n", + SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); + + if (version_code) + *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); + + sanei_usb_init (); + + return SANE_STATUS_GOOD; } diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index e42c4c5a2..5826b7469 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -3,6 +3,7 @@ #include "../include/sane/config.h" +#include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" #include "../include/sane/saneopts.h" From 175a8b004240cf1eb5bc666a46bc670e0052b331 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Thu, 24 Nov 2022 18:05:42 +0100 Subject: [PATCH 07/49] fix usb dependancies --- backend/lexmark_x2600.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index adf4c8ac3..85221cd9f 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -15,8 +15,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) sanei_usb_init (); - - return SANE_STATUS_GOOD; + return probe_lexmark_devices (); } SANE_Status @@ -91,3 +90,9 @@ sane_exit (void) { } + +static SANE_Status +probe_lexmark_devices (void) +{ + return SANE_STATUS_GOOD; +} From 51ba313173baaf19f4352e3657afd93c736fb7ee Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Fri, 25 Nov 2022 17:35:10 +0100 Subject: [PATCH 08/49] backend in progress --- backend/lexmark.c | 7 +- backend/lexmark_x2600.c | 638 ++++++++++++++++++++++++++++++++++++++-- backend/lexmark_x2600.h | 84 ++++++ 3 files changed, 698 insertions(+), 31 deletions(-) diff --git a/backend/lexmark.c b/backend/lexmark.c index ba0311d83..124056eef 100644 --- a/backend/lexmark.c +++ b/backend/lexmark.c @@ -827,10 +827,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, break; case SANE_ACTION_SET_VALUE: - + if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) - return SANE_STATUS_INVAL; - + { + return SANE_STATUS_INVAL; + } /* Make sure boolean values are only TRUE or FALSE */ if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) { diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 85221cd9f..7847549e1 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1,9 +1,256 @@ -#define BUILD 1 #include "lexmark_x2600.h" +#define BUILD 1 +#define LEXMARK_X2600_CONFIG_FILE "lexmark_x2600.conf" +#define MAX_OPTION_STRING_SIZE 255 + +static Lexmark_Device *first_device = 0; +static SANE_Int num_devices = 0; +static const SANE_Device **devlist = 0; + +static SANE_Bool initialized = SANE_FALSE; + +static SANE_Int dpi_list[] = { + 5, 75, 100, 200, 300, 600 +}; + +static SANE_String_Const mode_list[] = { + SANE_VALUE_SCAN_MODE_COLOR, + SANE_VALUE_SCAN_MODE_GRAY, + NULL +}; + +static SANE_Range x_range = { + 1, /* minimum */ + 5078, /* maximum */ + 2 /* quantization : 16 is required so we + never have an odd width */ +}; + +static SANE_Range y_range = { + 1, /* minimum */ + 7015, /* maximum */ + /* 7032, for X74 */ + 2 /* quantization */ +}; + SANE_Status -sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) +usb_write_then_read_twice (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) { + size_t buf_size; + SANE_Byte buf[3]; + SANE_Status status; + + status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + return status; +} + +SANE_Status +init_options (Lexmark_Device * dev) +{ + + SANE_Option_Descriptor *od; + + DBG (2, "init_options: dev = %p\n", (void *) dev); + + /* number of options */ + od = &(dev->opt[OPT_NUM_OPTS]); + od->name = SANE_NAME_NUM_OPTIONS; + od->title = SANE_TITLE_NUM_OPTIONS; + od->desc = SANE_DESC_NUM_OPTIONS; + od->type = SANE_TYPE_INT; + od->unit = SANE_UNIT_NONE; + od->size = sizeof (SANE_Word); + od->cap = SANE_CAP_SOFT_DETECT; + od->constraint_type = SANE_CONSTRAINT_NONE; + od->constraint.range = 0; + dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; + + /* mode - sets the scan mode: Color, Gray, or Line Art */ + od = &(dev->opt[OPT_MODE]); + od->name = SANE_NAME_SCAN_MODE; + od->title = SANE_TITLE_SCAN_MODE; + od->desc = SANE_DESC_SCAN_MODE;; + od->type = SANE_TYPE_STRING; + od->unit = SANE_UNIT_NONE; + od->size = MAX_OPTION_STRING_SIZE; + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->constraint_type = SANE_CONSTRAINT_STRING_LIST; + od->constraint.string_list = mode_list; + dev->val[OPT_MODE].s = malloc (od->size); + if (!dev->val[OPT_MODE].s) + return SANE_STATUS_NO_MEM; + strcpy (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR); + + /* resolution */ + od = &(dev->opt[OPT_RESOLUTION]); + od->name = SANE_NAME_SCAN_RESOLUTION; + od->title = SANE_TITLE_SCAN_RESOLUTION; + od->desc = SANE_DESC_SCAN_RESOLUTION; + od->type = SANE_TYPE_INT; + od->unit = SANE_UNIT_DPI; + od->size = sizeof (SANE_Word); + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->constraint_type = SANE_CONSTRAINT_WORD_LIST; + od->constraint.word_list = dpi_list; + dev->val[OPT_RESOLUTION].w = 200; + + /* preview mode */ + od = &(dev->opt[OPT_PREVIEW]); + od->name = SANE_NAME_PREVIEW; + od->title = SANE_TITLE_PREVIEW; + od->desc = SANE_DESC_PREVIEW; + od->size = sizeof (SANE_Word); + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->type = SANE_TYPE_BOOL; + od->constraint_type = SANE_CONSTRAINT_NONE; + dev->val[OPT_PREVIEW].w = SANE_FALSE; + + /* "Geometry" group: */ + od = &(dev->opt[OPT_GEOMETRY_GROUP]); + od->name = ""; + od->title = SANE_I18N ("Geometry"); + od->desc = ""; + od->type = SANE_TYPE_GROUP; + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->size = 0; + od->constraint_type = SANE_CONSTRAINT_NONE; + + /* top-left x */ + od = &(dev->opt[OPT_TL_X]); + od->name = SANE_NAME_SCAN_TL_X; + od->title = SANE_TITLE_SCAN_TL_X; + od->desc = SANE_DESC_SCAN_TL_X; + od->type = SANE_TYPE_INT; + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->size = sizeof (SANE_Word); + od->unit = SANE_UNIT_PIXEL; + od->constraint_type = SANE_CONSTRAINT_RANGE; + od->constraint.range = &x_range; + dev->val[OPT_TL_X].w = 0; + + /* top-left y */ + od = &(dev->opt[OPT_TL_Y]); + od->name = SANE_NAME_SCAN_TL_Y; + od->title = SANE_TITLE_SCAN_TL_Y; + od->desc = SANE_DESC_SCAN_TL_Y; + od->type = SANE_TYPE_INT; + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->size = sizeof (SANE_Word); + od->unit = SANE_UNIT_PIXEL; + od->constraint_type = SANE_CONSTRAINT_RANGE; + od->constraint.range = &y_range; + dev->val[OPT_TL_Y].w = 0; + + /* bottom-right x */ + od = &(dev->opt[OPT_BR_X]); + od->name = SANE_NAME_SCAN_BR_X; + od->title = SANE_TITLE_SCAN_BR_X; + od->desc = SANE_DESC_SCAN_BR_X; + od->type = SANE_TYPE_INT; + od->size = sizeof (SANE_Word); + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->unit = SANE_UNIT_PIXEL; + od->constraint_type = SANE_CONSTRAINT_RANGE; + od->constraint.range = &x_range; + dev->val[OPT_BR_X].w = 1700; + + /* bottom-right y */ + od = &(dev->opt[OPT_BR_Y]); + od->name = SANE_NAME_SCAN_BR_Y; + od->title = SANE_TITLE_SCAN_BR_Y; + od->desc = SANE_DESC_SCAN_BR_Y; + od->type = SANE_TYPE_INT; + od->size = sizeof (SANE_Word); + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->unit = SANE_UNIT_PIXEL; + od->constraint_type = SANE_CONSTRAINT_RANGE; + od->constraint.range = &y_range; + dev->val[OPT_BR_Y].w = 2338; + + return SANE_STATUS_GOOD; +} + +/* callback function for sanei_usb_attach_matching_devices +*/ +static SANE_Status +attach_one (SANE_String_Const devname) +{ + Lexmark_Device *lexmark_device; + SANE_Int dn; + SANE_Status status; + + DBG (2, "attachLexmark: devname=%s\n", devname); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + /* already attached devices */ + if (strcmp (lexmark_device->sane.name, devname) == 0) + { + lexmark_device->missing = SANE_FALSE; + return SANE_STATUS_GOOD; + } + } + + lexmark_device = (Lexmark_Device *) malloc (sizeof (Lexmark_Device)); + if (lexmark_device == NULL) + return SANE_STATUS_NO_MEM; + + status = sanei_usb_open (devname, &dn); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, + sane_strstatus (status)); + return status; + } + else + DBG (2, "attachLexmark: device `%s' successfully opened\n", devname); + + lexmark_device->sane.name = strdup (devname); + lexmark_device->sane.vendor = "Lexmark"; + lexmark_device->sane.model = "X2600 series"; + lexmark_device->sane.type = "flat bed"; + + /* Make the pointer to the read buffer null here */ + lexmark_device->read_buffer = NULL; + /* mark device as present */ + lexmark_device->missing = SANE_FALSE; + + sanei_usb_close (lexmark_device->devnum); + + /* insert it a the start of the chained list */ + lexmark_device->next = first_device; + first_device = lexmark_device; + num_devices++; + + return status; +} + +SANE_Status +sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) +{ + FILE *fp; + SANE_Char config_line[PATH_MAX]; + const char *lp; + DBG_INIT (); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); @@ -14,85 +261,420 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback __sane_unused__ authorize) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); sanei_usb_init (); + + fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); + if (!fp) + { + return SANE_STATUS_GOOD; + } + while (sanei_config_read (config_line, sizeof (config_line), fp)) + { + if (config_line[0] == '#') + continue; /* ignore line comments */ + + lp = sanei_config_skip_whitespace (config_line); + /* skip empty lines */ + if (*lp == 0) + continue; + + DBG (4, "attach_matching_devices(%s)\n", config_line); + sanei_usb_attach_matching_devices (config_line, attach_one); + } - return probe_lexmark_devices (); -} - -SANE_Status -sane_get_devices (const SANE_Device __sane_unused__ ***dl, SANE_Bool __sane_unused__ local) -{ + DBG (4, "finished reading configure file\n"); + fclose (fp); + initialized = SANE_TRUE; return SANE_STATUS_GOOD; } SANE_Status -sane_open (SANE_String_Const __sane_unused__ name, SANE_Handle __sane_unused__ *h) +sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { + SANE_Int index; + Lexmark_Device *lexmark_device; + + DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", + (void *) device_list, local_only); + + if (devlist) + free (devlist); + + devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); + if (!devlist) + return (SANE_STATUS_NO_MEM); + + index = 0; + lexmark_device = first_device; + while (lexmark_device != NULL) + { + if (lexmark_device->missing == SANE_FALSE) + { + devlist[index] = &(lexmark_device->sane); + index++; + } + lexmark_device = lexmark_device->next; + } + devlist[index] = 0; + + *device_list = devlist; + return SANE_STATUS_GOOD; } +SANE_Status +sane_open (SANE_String_Const devicename, SANE_Handle * handle) +{ + Lexmark_Device *lexmark_device; + SANE_Status status; + + DBG (2, "sane_open: devicename=\"%s\", handle=%p\n", devicename, + (void *) handle); + + /* walk the linked list of scanner device until there is a match + * with the device name */ + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + DBG (2, "sane_open: devname from list: %s\n", + lexmark_device->sane.name); + if (strcmp (devicename, "") == 0 + || strcmp (devicename, "lexmark") == 0 + || strcmp (devicename, lexmark_device->sane.name) == 0) + break; + } + + + *handle = lexmark_device; + + status = init_options (lexmark_device); + if (status != SANE_STATUS_GOOD) + return status; + + return status; +} + const SANE_Option_Descriptor * -sane_get_option_descriptor (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt) +sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { - return NULL; + Lexmark_Device *lexmark_device; + + DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", + (void *) handle, option); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + if (!lexmark_device) + return NULL; + + if (lexmark_device->opt[option].name) + { + DBG (2, "sane_get_option_descriptor: name=%s\n", + lexmark_device->opt[option].name); + } + + return &(lexmark_device->opt[option]); } SANE_Status -sane_control_option (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ opt, SANE_Action __sane_unused__ act, - void __sane_unused__ *val, SANE_Word __sane_unused__ *info) +sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, + void * value, SANE_Word * info) { + Lexmark_Device *lexmark_device; + SANE_Status status; + SANE_Word w; + + DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", + (void *) handle, option, action, (void *) value, (void *) info); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + + if (value == NULL) + return SANE_STATUS_INVAL; + + switch (action) + { + case SANE_ACTION_SET_VALUE: + if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) + { + return SANE_STATUS_INVAL; + } + /* Make sure boolean values are only TRUE or FALSE */ + if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) + { + if (! + ((*(SANE_Bool *) value == SANE_FALSE) + || (*(SANE_Bool *) value == SANE_TRUE))) + return SANE_STATUS_INVAL; + } + + /* Check range constraints */ + if (lexmark_device->opt[option].constraint_type == + SANE_CONSTRAINT_RANGE) + { + status = + sanei_constrain_value (&(lexmark_device->opt[option]), value, + info); + if (status != SANE_STATUS_GOOD) + { + DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); + return SANE_STATUS_INVAL; + } + } + switch (option) + { + case OPT_NUM_OPTS: + case OPT_RESOLUTION: + case OPT_TL_X: + case OPT_TL_Y: + case OPT_BR_X: + case OPT_BR_Y: + DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, + lexmark_device->opt[option].name); + lexmark_device->val[option].w = *(SANE_Word *) value; + if (lexmark_device->val[OPT_TL_X].w > + lexmark_device->val[OPT_BR_X].w) + { + w = lexmark_device->val[OPT_TL_X].w; + lexmark_device->val[OPT_TL_X].w = + lexmark_device->val[OPT_BR_X].w; + lexmark_device->val[OPT_BR_X].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } + if (lexmark_device->val[OPT_TL_Y].w > + lexmark_device->val[OPT_BR_Y].w) + { + w = lexmark_device->val[OPT_TL_Y].w; + lexmark_device->val[OPT_TL_Y].w = + lexmark_device->val[OPT_BR_Y].w; + lexmark_device->val[OPT_BR_Y].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } + break; + case OPT_MODE: + strcpy (lexmark_device->val[option].s, value); + if (info) + *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + return SANE_STATUS_GOOD; + } + + if (info != NULL) + *info |= SANE_INFO_RELOAD_PARAMS; + + break; + case SANE_ACTION_GET_VALUE: + + switch (option) + { + 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: + *(SANE_Word *) value = lexmark_device->val[option].w; + DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, + lexmark_device->opt[option].name); + break; + case OPT_MODE: + strcpy (value, lexmark_device->val[option].s); + break; + } + break; + + default: + return SANE_STATUS_INVAL; + } + return SANE_STATUS_GOOD; } SANE_Status -sane_get_parameters (SANE_Handle __sane_unused__ h, SANE_Parameters __sane_unused__ *parms) +sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { + Lexmark_Device *lexmark_device; + SANE_Parameters *device_params; + SANE_Int res, width_px; + SANE_Int channels, bitsperchannel; + + DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, + (void *) params); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + if (!lexmark_device) + return SANE_STATUS_INVAL; + + res = lexmark_device->val[OPT_RESOLUTION].w; + + device_params = &(lexmark_device->params); + + /* 24 bit colour = 8 bits/channel for each of the RGB channels */ + channels = 3; + bitsperchannel = 8; + if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) + != 0) + channels = 1; + + /* geometry in pixels */ + width_px = + lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; + DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n", + lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w, + lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w); + + DBG (7, "sane_get_parameters: res=(%d)\n", res); + + device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY + if (channels == 1) + device_params->format = SANE_FRAME_GRAY; + + device_params->last_frame = SANE_TRUE; + device_params->lines = -1; + device_params->depth = bitsperchannel; + device_params->pixels_per_line = width_px; + device_params->bytes_per_line = + (SANE_Int) ((7 + device_params->pixels_per_line) / 8); + + if (params != 0) + { + params->format = device_params->format; + params->last_frame = device_params->last_frame; + params->lines = device_params->lines; + params->depth = device_params->depth; + params->pixels_per_line = device_params->pixels_per_line; + params->bytes_per_line = device_params->bytes_per_line; + } + + return SANE_STATUS_GOOD; } SANE_Status -sane_start (SANE_Handle __sane_unused__ h) +sane_start (SANE_Handle handle) { + Lexmark_Device *lexmark_device; + SANE_Status status; + + DBG (2, "sane_start: handle=%p\n", (void *) handle); + + if (!initialized) + return SANE_STATUS_INVAL; + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + // launch scan commands + static SANE_Byte cmd[] = { 0x80, 0x00, 0x00, 0xFF }; + + status = usb_write_then_read_twice(lexmark_device, cmd, 4); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + + status = usb_write_then_read_twice(lexmark_device, cmd, 4); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + + status = usb_write_then_read_twice(lexmark_device, cmd, 4); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + return SANE_STATUS_GOOD; } SANE_Status -sane_read (SANE_Handle __sane_unused__ h, SANE_Byte __sane_unused__ *buf, SANE_Int __sane_unused__ maxlen, SANE_Int __sane_unused__ *lenp) +sane_read (SANE_Handle handle, SANE_Byte * data, + SANE_Int max_length, SANE_Int * length) { + DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", + (void *) handle, (void *) data, max_length, (void *) length); + return SANE_STATUS_GOOD; } SANE_Status -sane_set_io_mode (SANE_Handle __sane_unused__ h, SANE_Bool __sane_unused__ non_blocking) +sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { + DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", + (void *) handle, non_blocking); + return SANE_STATUS_GOOD; } SANE_Status -sane_get_select_fd (SANE_Handle __sane_unused__ h, SANE_Int __sane_unused__ *fdp) +sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { - return SANE_STATUS_GOOD; + DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", (void *) handle, + fd ? "!=" : "="); + + return SANE_STATUS_UNSUPPORTED; } void -sane_cancel (SANE_Handle __sane_unused__ h) +sane_cancel (SANE_Handle handle) { - + DBG (2, "sane_cancel: handle = %p\n", (void *) handle); } void -sane_close (SANE_Handle __sane_unused__ h) +sane_close (SANE_Handle handle) { - + DBG (2, "sane_close: handle=%p\n", (void *) handle); } void sane_exit (void) { + Lexmark_Device *lexmark_device, *next_lexmark_device; + + DBG (2, "sane_exit\n"); + + if (!initialized) + return; + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = next_lexmark_device) + { + next_lexmark_device = lexmark_device->next; + free (lexmark_device); + } + + if (devlist) + free (devlist); + + sanei_usb_exit(); + initialized = SANE_FALSE; } -static SANE_Status -probe_lexmark_devices (void) -{ - return SANE_STATUS_GOOD; -} diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index 5826b7469..7a3a6ae21 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -3,6 +3,19 @@ #include "../include/sane/config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "../include/_stdint.h" #include "../include/sane/sane.h" #include "../include/sane/sanei.h" @@ -12,4 +25,75 @@ #include "../include/sane/sanei_backend.h" +typedef struct Read_Buffer +{ + SANE_Int gray_offset; + SANE_Int max_gray_offset; + SANE_Int region; + SANE_Int red_offset; + SANE_Int green_offset; + SANE_Int blue_offset; + SANE_Int max_red_offset; + SANE_Int max_green_offset; + SANE_Int max_blue_offset; + SANE_Byte *data; + SANE_Byte *readptr; + SANE_Byte *writeptr; + SANE_Byte *max_writeptr; + size_t size; + size_t linesize; + SANE_Bool empty; + SANE_Int image_line_no; + SANE_Int bit_counter; + SANE_Int max_lineart_offset; +} +Read_Buffer; + + +typedef enum +{ + OPT_NUM_OPTS = 0, + OPT_MODE, + OPT_RESOLUTION, + OPT_PREVIEW, + + OPT_GEOMETRY_GROUP, + OPT_TL_X, /* top-left x */ + OPT_TL_Y, /* top-left y */ + OPT_BR_X, /* bottom-right x */ + OPT_BR_Y, /* bottom-right y */ + + /* must come last: */ + NUM_OPTIONS +} +Lexmark_Options; + +typedef struct Lexmark_Device +{ + struct Lexmark_Device *next; + SANE_Bool missing; /**< devices has been unplugged or swtiched off */ + + SANE_Device sane; + SANE_Option_Descriptor opt[NUM_OPTIONS]; + Option_Value val[NUM_OPTIONS]; + SANE_Parameters params; + SANE_Int devnum; + long data_size; + SANE_Bool initialized; + SANE_Bool eof; + SANE_Int x_dpi; + SANE_Int y_dpi; + long data_ctr; + SANE_Bool device_cancelled; + SANE_Int cancel_ctr; + SANE_Byte *transfer_buffer; + size_t bytes_read; + size_t bytes_remaining; + size_t bytes_in_buffer; + SANE_Byte *read_pointer; + Read_Buffer *read_buffer; +} +Lexmark_Device; + + #endif /* LEXMARK_X2600_H */ From 315fe1fdf567f33c4870272754e96c62c506bcbf Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Fri, 25 Nov 2022 17:39:07 +0100 Subject: [PATCH 09/49] fix trailing whitespaces --- backend/lexmark.c | 2 +- backend/lexmark_x2600.c | 77 ++++++++++++++++++++--------------------- backend/lexmark_x2600.h | 2 +- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/backend/lexmark.c b/backend/lexmark.c index 124056eef..b3071198f 100644 --- a/backend/lexmark.c +++ b/backend/lexmark.c @@ -827,7 +827,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, break; case SANE_ACTION_SET_VALUE: - + if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) { return SANE_STATUS_INVAL; diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 7847549e1..61882e6d2 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -38,9 +38,9 @@ SANE_Status usb_write_then_read_twice (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) { size_t buf_size; - SANE_Byte buf[3]; - SANE_Status status; - + SANE_Byte buf[128]; + SANE_Status status; + status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); if (status != SANE_STATUS_GOOD) { @@ -228,14 +228,14 @@ attach_one (SANE_String_Const devname) lexmark_device->sane.vendor = "Lexmark"; lexmark_device->sane.model = "X2600 series"; lexmark_device->sane.type = "flat bed"; - + /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = NULL; /* mark device as present */ lexmark_device->missing = SANE_FALSE; sanei_usb_close (lexmark_device->devnum); - + /* insert it a the start of the chained list */ lexmark_device->next = first_device; first_device = lexmark_device; @@ -250,7 +250,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) FILE *fp; SANE_Char config_line[PATH_MAX]; const char *lp; - + DBG_INIT (); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); @@ -259,7 +259,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) if (version_code) *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); - + sanei_usb_init (); fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); @@ -276,11 +276,11 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) /* skip empty lines */ if (*lp == 0) continue; - + DBG (4, "attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices (config_line, attach_one); } - + DBG (4, "finished reading configure file\n"); fclose (fp); initialized = SANE_TRUE; @@ -292,13 +292,13 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { SANE_Int index; Lexmark_Device *lexmark_device; - + DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", (void *) device_list, local_only); if (devlist) free (devlist); - + devlist = malloc ((num_devices + 1) * sizeof (devlist[0])); if (!devlist) return (SANE_STATUS_NO_MEM); @@ -317,7 +317,7 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) devlist[index] = 0; *device_list = devlist; - + return SANE_STATUS_GOOD; } @@ -343,13 +343,13 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) break; } - + *handle = lexmark_device; status = init_options (lexmark_device); if (status != SANE_STATUS_GOOD) return status; - + return status; } @@ -376,7 +376,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) DBG (2, "sane_get_option_descriptor: name=%s\n", lexmark_device->opt[option].name); } - + return &(lexmark_device->opt[option]); } @@ -398,7 +398,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, break; } - + if (value == NULL) return SANE_STATUS_INVAL; @@ -475,7 +475,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, break; case SANE_ACTION_GET_VALUE: - + switch (option) { case OPT_NUM_OPTS: @@ -494,11 +494,11 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, break; } break; - + default: return SANE_STATUS_INVAL; } - + return SANE_STATUS_GOOD; } @@ -509,7 +509,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) SANE_Parameters *device_params; SANE_Int res, width_px; SANE_Int channels, bitsperchannel; - + DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, (void *) params); @@ -524,9 +524,9 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) return SANE_STATUS_INVAL; res = lexmark_device->val[OPT_RESOLUTION].w; - + device_params = &(lexmark_device->params); - + /* 24 bit colour = 8 bits/channel for each of the RGB channels */ channels = 3; bitsperchannel = 8; @@ -540,18 +540,18 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n", lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w, lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w); - + DBG (7, "sane_get_parameters: res=(%d)\n", res); - + device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY if (channels == 1) device_params->format = SANE_FRAME_GRAY; - + device_params->last_frame = SANE_TRUE; device_params->lines = -1; device_params->depth = bitsperchannel; device_params->pixels_per_line = width_px; - device_params->bytes_per_line = + device_params->bytes_per_line = (SANE_Int) ((7 + device_params->pixels_per_line) / 8); if (params != 0) @@ -564,7 +564,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) params->bytes_per_line = device_params->bytes_per_line; } - + return SANE_STATUS_GOOD; } @@ -588,13 +588,6 @@ sane_start (SANE_Handle handle) // launch scan commands static SANE_Byte cmd[] = { 0x80, 0x00, 0x00, 0xFF }; - - status = usb_write_then_read_twice(lexmark_device, cmd, 4); - if (status != SANE_STATUS_GOOD) - { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); - return status; - } status = usb_write_then_read_twice(lexmark_device, cmd, 4); if (status != SANE_STATUS_GOOD) @@ -609,7 +602,14 @@ sane_start (SANE_Handle handle) DBG (1, "USB IO Error in sane_start, cannot launch scan"); return status; } - + + status = usb_write_then_read_twice(lexmark_device, cmd, 4); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "USB IO Error in sane_start, cannot launch scan"); + return status; + } + return SANE_STATUS_GOOD; } @@ -619,7 +619,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, { DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", (void *) handle, (void *) data, max_length, (void *) length); - + return SANE_STATUS_GOOD; } @@ -637,7 +637,7 @@ sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) { DBG (2, "sane_get_select_fd: handle = %p, fd %s 0\n", (void *) handle, fd ? "!=" : "="); - + return SANE_STATUS_UNSUPPORTED; } @@ -662,7 +662,7 @@ sane_exit (void) if (!initialized) return; - + for (lexmark_device = first_device; lexmark_device; lexmark_device = next_lexmark_device) { @@ -677,4 +677,3 @@ sane_exit (void) initialized = SANE_FALSE; } - diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index 7a3a6ae21..2b1ec72f4 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -56,7 +56,7 @@ typedef enum OPT_MODE, OPT_RESOLUTION, OPT_PREVIEW, - + OPT_GEOMETRY_GROUP, OPT_TL_X, /* top-left x */ OPT_TL_Y, /* top-left y */ From d343dc963ba7df537f1cd69e77e474f7c48055eb Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 06:24:49 +0100 Subject: [PATCH 10/49] protocol implementation in progress --- backend/lexmark_x2600.c | 180 +++++++++++++++++++++++++++++----------- 1 file changed, 131 insertions(+), 49 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 61882e6d2..ca38c511f 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -34,32 +34,76 @@ static SANE_Range y_range = { 2 /* quantization */ }; +static SANE_Int command1_block_size = 28; +static SANE_Byte command1_block[] = { + 0xA5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xAA, 0xBB, + 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x03, 0x00, + 0x00, 0x00, 0x80, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, + 0xAA, 0xBB, 0xCC, 0xDD}; + +static SANE_Int command2_block_size = 28; +static SANE_Byte command2_block[] = { + 0xA5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xAA, 0xBB, + 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x04, 0x00, + 0x00, 0x00, 0x80, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, + 0xAA, 0xBB, 0xCC, 0xDD}; + +static SANE_Int command_with_params_block_size = 52; +static SANE_Byte command_with_params_block[] = { + 0xA5, 0x00, 0x31, 0x10, 0x01, 0x83, 0xAA, 0xBB, + 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x05, 0x00, + 0x18, 0x00, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x02, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, + 0xAA, 0xBB, 0xCC, 0xDD}; + + SANE_Status -usb_write_then_read_twice (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) +usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) { - size_t buf_size; - SANE_Byte buf[128]; + size_t buf_size = 128; + SANE_Byte buf[buf_size]; SANE_Status status; + DBG (2, "USB WRITE device:%d size:%d cmd:%p\n", dev->devnum, cmd_size, cmd[0]); + + sanei_usb_set_endpoint(dev->devnum, USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK, 0x02); status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); if (status != SANE_STATUS_GOOD) { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); + DBG (1, "USB WRITE IO Error in usb_write_then_read, cannot launch scan status: %d\n", status); return status; } + //sanei_usb_set_endpoint(dev->devnum, USB_DIR_IN|USB_ENDPOINT_TYPE_BULK , 0x01); status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); + DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan\n"); return status; } - status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); - if (status != SANE_STATUS_GOOD) - { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); - return status; - } - return status; + return SANE_STATUS_GOOD; +} + +void +build_packet(Lexmark_Device * dev, SANE_Byte packet_id, SANE_Byte * buffer){ + memcpy(buffer, command_with_params_block, command_with_params_block_size); + // protocole related... "ID?" + buffer[14] = packet_id; + // mode + buffer[20] = 0x02; + // pixel width + buffer[24] = 0xF0; + buffer[25] = 0x00; + // pixel height + buffer[28] = 0xF0; + buffer[29] = 0x00; + // dpi x + buffer[40] = 0xC8; + buffer[41] = 0x00; + // dpi y + buffer[42] = 0xC8; + buffer[43] = 0x00; } SANE_Status @@ -170,7 +214,7 @@ init_options (Lexmark_Device * dev) od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &x_range; - dev->val[OPT_BR_X].w = 1700; + dev->val[OPT_BR_X].w = 1699; /* bottom-right y */ od = &(dev->opt[OPT_BR_Y]); @@ -183,7 +227,7 @@ init_options (Lexmark_Device * dev) od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &y_range; - dev->val[OPT_BR_Y].w = 2338; + dev->val[OPT_BR_Y].w = 2337; return SANE_STATUS_GOOD; } @@ -214,15 +258,15 @@ attach_one (SANE_String_Const devname) if (lexmark_device == NULL) return SANE_STATUS_NO_MEM; - status = sanei_usb_open (devname, &dn); - if (status != SANE_STATUS_GOOD) - { - DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, - sane_strstatus (status)); - return status; - } - else - DBG (2, "attachLexmark: device `%s' successfully opened\n", devname); + /* status = sanei_usb_open (devname, &dn); */ + /* if (status != SANE_STATUS_GOOD) */ + /* { */ + /* DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, */ + /* sane_strstatus (status)); */ + /* return status; */ + /* } */ + /* else */ + /* DBG (2, "attachLexmark: device `%s' successfully opened dn: %s\n", devname, dn); */ lexmark_device->sane.name = strdup (devname); lexmark_device->sane.vendor = "Lexmark"; @@ -234,7 +278,7 @@ attach_one (SANE_String_Const devname) /* mark device as present */ lexmark_device->missing = SANE_FALSE; - sanei_usb_close (lexmark_device->devnum); + //sanei_usb_close (lexmark_device->devnum); /* insert it a the start of the chained list */ lexmark_device->next = first_device; @@ -343,13 +387,25 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) break; } - *handle = lexmark_device; status = init_options (lexmark_device); if (status != SANE_STATUS_GOOD) return status; + DBG(2, "sane_open: device `%s' opening devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); + status = sanei_usb_open (lexmark_device->sane.name, &(lexmark_device->devnum)); + if (status != SANE_STATUS_GOOD) + { + DBG (1, "sane_open: couldn't open device `%s': %s\n", lexmark_device->sane.name, + sane_strstatus (status)); + return status; + } + else + { + DBG (2, "sane_open: device `%s' successfully opened devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); + } + return status; } @@ -563,17 +619,16 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) params->pixels_per_line = device_params->pixels_per_line; params->bytes_per_line = device_params->bytes_per_line; } - - return SANE_STATUS_GOOD; } SANE_Status sane_start (SANE_Handle handle) { - Lexmark_Device *lexmark_device; + Lexmark_Device * lexmark_device; SANE_Status status; - + SANE_Byte * cmd = (SANE_Byte *) malloc (command_with_params_block_size * sizeof (SANE_Byte));; + DBG (2, "sane_start: handle=%p\n", (void *) handle); if (!initialized) @@ -586,30 +641,25 @@ sane_start (SANE_Handle handle) break; } - // launch scan commands - static SANE_Byte cmd[] = { 0x80, 0x00, 0x00, 0xFF }; - - status = usb_write_then_read_twice(lexmark_device, cmd, 4); + //launch scan commands + status = usb_write_then_read(lexmark_device, command1_block, command1_block_size); if (status != SANE_STATUS_GOOD) - { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); - return status; - } + return status; - status = usb_write_then_read_twice(lexmark_device, cmd, 4); + status = usb_write_then_read(lexmark_device, command2_block, command2_block_size); if (status != SANE_STATUS_GOOD) - { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); - return status; - } + return status; - status = usb_write_then_read_twice(lexmark_device, cmd, 4); + build_packet(lexmark_device, 0x05, cmd); + DBG (2, "sane_start: cmd=%p\n", cmd); + status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) - { - DBG (1, "USB IO Error in sane_start, cannot launch scan"); - return status; - } - + return status; + build_packet(lexmark_device, 0x01, cmd);; + status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); + if (status != SANE_STATUS_GOOD) + return status; + return SANE_STATUS_GOOD; } @@ -617,9 +667,30 @@ SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { + Lexmark_Device * lexmark_device; + SANE_Status status; + DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", (void *) handle, (void *) data, max_length, (void *) length); + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + size_t size = 256; + SANE_Byte buf[size]; + + //sanei_usb_set_endpoint(lexmark_device->devnum, USB_DIR_IN|USB_ENDPOINT_TYPE_BULK , 0x01); + status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) + { + DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan\n"); + return status; + } + return SANE_STATUS_GOOD; } @@ -650,7 +721,18 @@ sane_cancel (SANE_Handle handle) void sane_close (SANE_Handle handle) { + Lexmark_Device * lexmark_device; + DBG (2, "sane_close: handle=%p\n", (void *) handle); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + sanei_usb_close (lexmark_device->devnum); } void From a44127d1bc04ff762015b72207f0e50895bef9af Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 06:36:57 +0100 Subject: [PATCH 11/49] protocol implementation in progress --- backend/lexmark_x2600.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index ca38c511f..210a515e7 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -58,6 +58,10 @@ static SANE_Byte command_with_params_block[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD}; +static SANE_Int last_data_packet_size = 9; +static SANE_Byte last_data_packet[] = { + 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01}; SANE_Status usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) @@ -690,6 +694,9 @@ sane_read (SANE_Handle handle, SANE_Byte * data, DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan\n"); return status; } + + if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) + return SANE_STATUS_EOF; return SANE_STATUS_GOOD; } From e6cb0cf07e9037642acdb61428027d85fa347108 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 07:14:45 +0100 Subject: [PATCH 12/49] update packet forging --- backend/lexmark_x2600.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 210a515e7..843933d35 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -94,20 +94,28 @@ build_packet(Lexmark_Device * dev, SANE_Byte packet_id, SANE_Byte * buffer){ memcpy(buffer, command_with_params_block, command_with_params_block_size); // protocole related... "ID?" buffer[14] = packet_id; + // mode - buffer[20] = 0x02; - // pixel width - buffer[24] = 0xF0; - buffer[25] = 0x00; - // pixel height - buffer[28] = 0xF0; - buffer[29] = 0x00; - // dpi x - buffer[40] = 0xC8; - buffer[41] = 0x00; - // dpi y - buffer[42] = 0xC8; - buffer[43] = 0x00; + if (memcmp(dev->val[OPT_MODE].s, "Color", 5) == 0 ) + buffer[20] = 0x03; + else + buffer[20] = 0x02; + + // pixel width (swap lower byte -> higher byte) + buffer[24] = dev->val[OPT_BR_X].w & 0xFF; + buffer[25] = (dev->val[OPT_BR_X].w >> 8) & 0xFF; + + // pixel height (swap lower byte -> higher byte) + buffer[28] = dev->val[OPT_BR_X].w & 0xFF; + buffer[29] = (dev->val[OPT_BR_X].w >> 8) & 0xFF; + + // dpi x (swap lower byte -> higher byte) + buffer[40] = dev->val[OPT_RESOLUTION].w & 0xFF; + buffer[41] = (dev->val[OPT_RESOLUTION].w >> 8) & 0xFF; + + // dpi y (swap lower byte -> higher byte) + buffer[42] = dev->val[OPT_RESOLUTION].w & 0xFF; + buffer[43] = (dev->val[OPT_RESOLUTION].w >> 8) & 0xFF; } SANE_Status @@ -658,7 +666,8 @@ sane_start (SANE_Handle handle) DBG (2, "sane_start: cmd=%p\n", cmd); status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) - return status; + return status; + build_packet(lexmark_device, 0x01, cmd);; status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) From 68d6519b6e9ed2802e416fd6c7d1489e657208ed Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 07:43:23 +0100 Subject: [PATCH 13/49] fix packet forging --- backend/lexmark_x2600.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 843933d35..6f2026e88 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -106,8 +106,8 @@ build_packet(Lexmark_Device * dev, SANE_Byte packet_id, SANE_Byte * buffer){ buffer[25] = (dev->val[OPT_BR_X].w >> 8) & 0xFF; // pixel height (swap lower byte -> higher byte) - buffer[28] = dev->val[OPT_BR_X].w & 0xFF; - buffer[29] = (dev->val[OPT_BR_X].w >> 8) & 0xFF; + buffer[28] = dev->val[OPT_BR_Y].w & 0xFF; + buffer[29] = (dev->val[OPT_BR_Y].w >> 8) & 0xFF; // dpi x (swap lower byte -> higher byte) buffer[40] = dev->val[OPT_RESOLUTION].w & 0xFF; @@ -693,10 +693,9 @@ sane_read (SANE_Handle handle, SANE_Byte * data, break; } - size_t size = 256; + size_t size = max_length; SANE_Byte buf[size]; - //sanei_usb_set_endpoint(lexmark_device->devnum, USB_DIR_IN|USB_ENDPOINT_TYPE_BULK , 0x01); status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { @@ -704,6 +703,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, return status; } + // is last data packet ? if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) return SANE_STATUS_EOF; From 21f163e797457e47b11a1eea0524be942eb4526a Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 08:15:11 +0100 Subject: [PATCH 14/49] fix warnings --- backend/lexmark_x2600.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 6f2026e88..7ba92db63 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -63,6 +63,11 @@ static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; +void +clean_and_copy_data(SANE_Byte * buf, SANE_Byte * data, SANE_Int * length) +{ +} + SANE_Status usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) { @@ -70,8 +75,6 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) SANE_Byte buf[buf_size]; SANE_Status status; - DBG (2, "USB WRITE device:%d size:%d cmd:%p\n", dev->devnum, cmd_size, cmd[0]); - sanei_usb_set_endpoint(dev->devnum, USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK, 0x02); status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); if (status != SANE_STATUS_GOOD) @@ -250,8 +253,6 @@ static SANE_Status attach_one (SANE_String_Const devname) { Lexmark_Device *lexmark_device; - SANE_Int dn; - SANE_Status status; DBG (2, "attachLexmark: devname=%s\n", devname); @@ -270,16 +271,6 @@ attach_one (SANE_String_Const devname) if (lexmark_device == NULL) return SANE_STATUS_NO_MEM; - /* status = sanei_usb_open (devname, &dn); */ - /* if (status != SANE_STATUS_GOOD) */ - /* { */ - /* DBG (1, "attachLexmark: couldn't open device `%s': %s\n", devname, */ - /* sane_strstatus (status)); */ - /* return status; */ - /* } */ - /* else */ - /* DBG (2, "attachLexmark: device `%s' successfully opened dn: %s\n", devname, dn); */ - lexmark_device->sane.name = strdup (devname); lexmark_device->sane.vendor = "Lexmark"; lexmark_device->sane.model = "X2600 series"; @@ -290,14 +281,12 @@ attach_one (SANE_String_Const devname) /* mark device as present */ lexmark_device->missing = SANE_FALSE; - //sanei_usb_close (lexmark_device->devnum); - /* insert it a the start of the chained list */ lexmark_device->next = first_device; first_device = lexmark_device; num_devices++; - return status; + return SANE_STATUS_GOOD; } SANE_Status @@ -707,6 +696,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) return SANE_STATUS_EOF; + clean_and_copy_data(buf, data, length); + return SANE_STATUS_GOOD; } @@ -715,7 +706,10 @@ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", (void *) handle, non_blocking); - + + if (non_blocking) + return SANE_STATUS_UNSUPPORTED; + return SANE_STATUS_GOOD; } From 8efa35874016870bee35e5f0cdb3ea5a03b716cd Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 08:16:54 +0100 Subject: [PATCH 15/49] fix warnings --- backend/lexmark_x2600.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 7ba92db63..c6b56b3cb 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -64,8 +64,10 @@ static SANE_Byte last_data_packet[] = { 0x01}; void -clean_and_copy_data(SANE_Byte * buf, SANE_Byte * data, SANE_Int * length) +clean_and_copy_data(SANE_Byte * source, size_t source_size, SANE_Byte * destination, SANE_Int * destination_length) { + + memcpy (buffer, rb->readptr, available_bytes); } SANE_Status @@ -696,7 +698,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) return SANE_STATUS_EOF; - clean_and_copy_data(buf, data, length); + clean_and_copy_data(buf, size, data, length); return SANE_STATUS_GOOD; } From eec401f5c3a6502db6e212086eb5137b0386b64a Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 08:45:57 +0100 Subject: [PATCH 16/49] data copy in progress --- backend/lexmark_x2600.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index c6b56b3cb..1df7c6b18 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -64,10 +64,22 @@ static SANE_Byte last_data_packet[] = { 0x01}; void -clean_and_copy_data(SANE_Byte * source, size_t source_size, SANE_Byte * destination, SANE_Int * destination_length) +clean_and_copy_data(SANE_Byte * source, size_t source_size, + SANE_Byte * destination, SANE_Int * destination_length) { + SANE_Int i = 0; + // 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segment length = 192) + // 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segment length = 1536) + // 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segment length = 15000) - memcpy (buffer, rb->readptr, available_bytes); + // SANE_Int segment_length = + while (i < source_size) + { + + i++; + } + DBG (1, "clean_and_copy_data done\n"); + //memcpy (buffer, rb->readptr, available_bytes); } SANE_Status From 0f9135def25c42d7f3008ab2d6c3cd54e5043b28 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 15:05:49 +0100 Subject: [PATCH 17/49] basic backend working --- backend/lexmark_x2600.c | 91 ++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 1df7c6b18..591392f5f 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -21,17 +21,16 @@ static SANE_String_Const mode_list[] = { }; static SANE_Range x_range = { - 1, /* minimum */ + 0, /* minimum */ 5078, /* maximum */ - 2 /* quantization : 16 is required so we - never have an odd width */ + 1 /* quantization */ }; static SANE_Range y_range = { - 1, /* minimum */ + 0, /* minimum */ 7015, /* maximum */ /* 7032, for X74 */ - 2 /* quantization */ + 1 /* quantization */ }; static SANE_Int command1_block_size = 28; @@ -64,21 +63,29 @@ static SANE_Byte last_data_packet[] = { 0x01}; void -clean_and_copy_data(SANE_Byte * source, size_t source_size, +clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length) { - SANE_Int i = 0; - // 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segment length = 192) - // 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segment length = 1536) - // 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segment length = 15000) + SANE_Int i = 9; + SANE_Int bytes_written = 0; + // BW 1b 53 02 00 41 00 00 00 00 | 32 | 41 -> 65 (segment length = 64) + // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segment length = 192) + // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segment length = 1536) + // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segment length = 15000) - // SANE_Int segment_length = + SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; + DBG (1, "clean_and_copy_data segment_length %d\n", segment_length); while (i < source_size) { + memcpy (destination + bytes_written, source + i, segment_length); + bytes_written += segment_length; - i++; + i += segment_length + 9; + DBG (2, " i:%d bytes_written:%d\n", i, bytes_written); } - DBG (1, "clean_and_copy_data done\n"); + + *destination_length = bytes_written; + DBG (1, "clean_and_copy_data done %d\n", *destination_length); //memcpy (buffer, rb->readptr, available_bytes); } @@ -432,6 +439,10 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", (void *) handle, option); + /* Check for valid option number */ + if ((option < 0) || (option >= NUM_OPTIONS)) + return NULL; + for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) { @@ -441,7 +452,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) if (!lexmark_device) return NULL; - + if (lexmark_device->opt[option].name) { DBG (2, "sane_get_option_descriptor: name=%s\n", @@ -578,8 +589,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Lexmark_Device *lexmark_device; SANE_Parameters *device_params; - SANE_Int res, width_px; - SANE_Int channels, bitsperchannel; + SANE_Int width_px; DBG (2, "sane_get_parameters: handle=%p, params=%p\n", (void *) handle, (void *) params); @@ -594,36 +604,30 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) if (!lexmark_device) return SANE_STATUS_INVAL; - res = lexmark_device->val[OPT_RESOLUTION].w; + // res = lexmark_device->val[OPT_RESOLUTION].w; device_params = &(lexmark_device->params); - - /* 24 bit colour = 8 bits/channel for each of the RGB channels */ - channels = 3; - bitsperchannel = 8; - if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) - != 0) - channels = 1; - - /* geometry in pixels */ width_px = lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; - DBG (7, "sane_get_parameters: tl=(%d,%d) br=(%d,%d)\n", - lexmark_device->val[OPT_TL_X].w, lexmark_device->val[OPT_TL_Y].w, - lexmark_device->val[OPT_BR_X].w, lexmark_device->val[OPT_BR_Y].w); - DBG (7, "sane_get_parameters: res=(%d)\n", res); - - device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY - if (channels == 1) - device_params->format = SANE_FRAME_GRAY; - - device_params->last_frame = SANE_TRUE; - device_params->lines = -1; - device_params->depth = bitsperchannel; + /* 24 bit colour = 8 bits/channel for each of the RGB channels */ device_params->pixels_per_line = width_px; + device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY + device_params->depth = 8; device_params->bytes_per_line = - (SANE_Int) ((7 + device_params->pixels_per_line) / 8); + (SANE_Int) ((3 * (device_params->pixels_per_line + 1) * device_params->depth )/ 8); + + if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) + != 0) + { + device_params->format = SANE_FRAME_GRAY; + device_params->bytes_per_line = + (SANE_Int) ((device_params->pixels_per_line + 1)* device_params->depth / 8); + } + + /* geometry in pixels */ + device_params->last_frame = SANE_TRUE; + device_params->lines = lexmark_device->val[OPT_BR_Y].w; if (params != 0) { @@ -686,8 +690,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, Lexmark_Device * lexmark_device; SANE_Status status; - DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%p\n", - (void *) handle, (void *) data, max_length, (void *) length); + DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%d\n", + (void *) handle, (void *) data, max_length, *length); for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) @@ -708,7 +712,10 @@ sane_read (SANE_Handle handle, SANE_Byte * data, // is last data packet ? if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) - return SANE_STATUS_EOF; + { + length = 0; + return SANE_STATUS_EOF; + } clean_and_copy_data(buf, size, data, length); From 185807a33553f7d025b8cc73be52868d11002143 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 19:49:21 +0100 Subject: [PATCH 18/49] fix packet empty skip --- backend/lexmark_x2600.c | 72 ++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 591392f5f..018a714bd 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -62,31 +62,60 @@ static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; +/* static SANE_Int empty_data_packet_size = 8; */ + static SANE_Byte empty_data_packet[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + void clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, - SANE_Byte * destination, SANE_Int * destination_length) + SANE_Byte * destination, SANE_Int * destination_length, SANE_Int mode) { SANE_Int i = 9; SANE_Int bytes_written = 0; - // BW 1b 53 02 00 41 00 00 00 00 | 32 | 41 -> 65 (segment length = 64) + // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segment length = 32) + // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segment length = 64) // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segment length = 192) // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segment length = 1536) // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segment length = 15000) + + /* DBG (2, "Empty packet? %p %p\n", source[9], source[10]); */ + /* // buffer might contain only ff ff ff ... after data */ + /* if (memcmp(source + 9, empty_data_packet, empty_data_packet_size) == 0 ) */ + /* { */ + /* DBG (2, "Empty packet\n"); */ + /* *destination_length = 0; */ + /* return; */ + /* } */ SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; - DBG (1, "clean_and_copy_data segment_length %d\n", segment_length); + SANE_Byte tmp = 0; + DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", segment_length, mode); while (i < source_size) { + if (memcmp(source + 9, empty_data_packet, 4) == 0 ) + break; memcpy (destination + bytes_written, source + i, segment_length); - bytes_written += segment_length; + // swap RGB <- BGR + if (mode == SANE_FRAME_RGB) + { + for(SANE_Int j=bytes_written; j < bytes_written + segment_length; j += 3) + { + tmp = destination[j]; + destination[j] = destination[j+2]; + destination[j+2] = tmp; + } + } + bytes_written += segment_length; i += segment_length + 9; - DBG (2, " i:%d bytes_written:%d\n", i, bytes_written); + DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); } + DBG (20, " destination[] %d %d %d %d", + destination[bytes_written-4], destination[bytes_written-3], destination[bytes_written-2], + destination[bytes_written-1]); *destination_length = bytes_written; - DBG (1, "clean_and_copy_data done %d\n", *destination_length); - //memcpy (buffer, rb->readptr, available_bytes); + DBG (10, "clean_and_copy_data done %d\n", *destination_length); } SANE_Status @@ -96,6 +125,7 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) SANE_Byte buf[buf_size]; SANE_Status status; + DBG (10, "usb_write_then_read: %d\n", dev->devnum); sanei_usb_set_endpoint(dev->devnum, USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK, 0x02); status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); if (status != SANE_STATUS_GOOD) @@ -107,7 +137,7 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan\n"); + DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan devnum=%d\n", dev->devnum); return status; } return SANE_STATUS_GOOD; @@ -604,9 +634,9 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) if (!lexmark_device) return SANE_STATUS_INVAL; - // res = lexmark_device->val[OPT_RESOLUTION].w; - + // res = lexmark_device->val[OPT_RESOLUTION].w; device_params = &(lexmark_device->params); + width_px = lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; @@ -615,20 +645,25 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) device_params->format = SANE_FRAME_RGB; // SANE_FRAME_GRAY device_params->depth = 8; device_params->bytes_per_line = - (SANE_Int) ((3 * (device_params->pixels_per_line + 1) * device_params->depth )/ 8); - + (SANE_Int) (3 * device_params->pixels_per_line); + if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) != 0) { device_params->format = SANE_FRAME_GRAY; - device_params->bytes_per_line = - (SANE_Int) ((device_params->pixels_per_line + 1)* device_params->depth / 8); + device_params->bytes_per_line = + (SANE_Int) (device_params->pixels_per_line); } /* geometry in pixels */ device_params->last_frame = SANE_TRUE; device_params->lines = lexmark_device->val[OPT_BR_Y].w; + DBG (2, "sane_get_parameters: device_params->pixels_per_line=%d\n", + device_params->pixels_per_line); + DBG (2, "sane_get_parameters: device_params->bytes_per_line=%d\n", + device_params->bytes_per_line); + if (params != 0) { params->format = device_params->format; @@ -690,8 +725,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, Lexmark_Device * lexmark_device; SANE_Status status; - DBG (2, "sane_read: handle=%p, data=%p, max_length = %d, length=%d\n", - (void *) handle, (void *) data, max_length, *length); + DBG (20, "sane_read: handle=%p, data=%p, max_length = %d\n", + (void *) handle, (void *) data, max_length); for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) @@ -706,7 +741,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan\n"); + DBG (1, "USB READ IO Error in usb_write_then_read, cannot read data devnum=%d\n", + lexmark_device->devnum); return status; } @@ -717,7 +753,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, return SANE_STATUS_EOF; } - clean_and_copy_data(buf, size, data, length); + clean_and_copy_data(buf, size, data, length, lexmark_device->params.format); return SANE_STATUS_GOOD; } From d739ffb8f019cab08680f3824ce9b486ecf38c3a Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 21:57:10 +0100 Subject: [PATCH 19/49] remove trailing whitepaces --- backend/lexmark_x2600.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 018a714bd..a62447f51 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -63,8 +63,8 @@ static SANE_Byte last_data_packet[] = { 0x01}; /* static SANE_Int empty_data_packet_size = 8; */ - static SANE_Byte empty_data_packet[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static SANE_Byte empty_data_packet[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; void clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, @@ -86,7 +86,7 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, /* *destination_length = 0; */ /* return; */ /* } */ - + SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; SANE_Byte tmp = 0; DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", segment_length, mode); @@ -105,7 +105,7 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, destination[j+2] = tmp; } } - + bytes_written += segment_length; i += segment_length + 9; DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); @@ -148,13 +148,13 @@ build_packet(Lexmark_Device * dev, SANE_Byte packet_id, SANE_Byte * buffer){ memcpy(buffer, command_with_params_block, command_with_params_block_size); // protocole related... "ID?" buffer[14] = packet_id; - + // mode if (memcmp(dev->val[OPT_MODE].s, "Color", 5) == 0 ) buffer[20] = 0x03; else buffer[20] = 0x02; - + // pixel width (swap lower byte -> higher byte) buffer[24] = dev->val[OPT_BR_X].w & 0xFF; buffer[25] = (dev->val[OPT_BR_X].w >> 8) & 0xFF; @@ -166,7 +166,7 @@ build_packet(Lexmark_Device * dev, SANE_Byte packet_id, SANE_Byte * buffer){ // dpi x (swap lower byte -> higher byte) buffer[40] = dev->val[OPT_RESOLUTION].w & 0xFF; buffer[41] = (dev->val[OPT_RESOLUTION].w >> 8) & 0xFF; - + // dpi y (swap lower byte -> higher byte) buffer[42] = dev->val[OPT_RESOLUTION].w & 0xFF; buffer[43] = (dev->val[OPT_RESOLUTION].w >> 8) & 0xFF; @@ -472,7 +472,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) /* Check for valid option number */ if ((option < 0) || (option >= NUM_OPTIONS)) return NULL; - + for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) { @@ -482,7 +482,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) if (!lexmark_device) return NULL; - + if (lexmark_device->opt[option].name) { DBG (2, "sane_get_option_descriptor: name=%s\n", @@ -634,9 +634,9 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) if (!lexmark_device) return SANE_STATUS_INVAL; - // res = lexmark_device->val[OPT_RESOLUTION].w; + // res = lexmark_device->val[OPT_RESOLUTION].w; device_params = &(lexmark_device->params); - + width_px = lexmark_device->val[OPT_BR_X].w - lexmark_device->val[OPT_TL_X].w; @@ -682,7 +682,7 @@ sane_start (SANE_Handle handle) Lexmark_Device * lexmark_device; SANE_Status status; SANE_Byte * cmd = (SANE_Byte *) malloc (command_with_params_block_size * sizeof (SANE_Byte));; - + DBG (2, "sane_start: handle=%p\n", (void *) handle); if (!initialized) @@ -709,12 +709,12 @@ sane_start (SANE_Handle handle) status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) return status; - + build_packet(lexmark_device, 0x01, cmd);; status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) return status; - + return SANE_STATUS_GOOD; } @@ -724,7 +724,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, { Lexmark_Device * lexmark_device; SANE_Status status; - + DBG (20, "sane_read: handle=%p, data=%p, max_length = %d\n", (void *) handle, (void *) data, max_length); @@ -752,9 +752,9 @@ sane_read (SANE_Handle handle, SANE_Byte * data, length = 0; return SANE_STATUS_EOF; } - + clean_and_copy_data(buf, size, data, length, lexmark_device->params.format); - + return SANE_STATUS_GOOD; } @@ -763,10 +763,10 @@ sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking) { DBG (2, "sane_set_io_mode: handle = %p, non_blocking = %d\n", (void *) handle, non_blocking); - + if (non_blocking) return SANE_STATUS_UNSUPPORTED; - + return SANE_STATUS_GOOD; } @@ -791,7 +791,7 @@ sane_close (SANE_Handle handle) Lexmark_Device * lexmark_device; DBG (2, "sane_close: handle=%p\n", (void *) handle); - + for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) { From 6e488f3891f21bf4a0076342a10a97f4b9c0afe2 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 22:20:26 +0100 Subject: [PATCH 20/49] fix missing define --- backend/lexmark_x2600.c | 74 ++++++++++++++++++++++------------------- backend/lexmark_x2600.h | 2 +- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index a62447f51..1f7e111ad 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -29,7 +29,6 @@ static SANE_Range x_range = { static SANE_Range y_range = { 0, /* minimum */ 7015, /* maximum */ - /* 7032, for X74 */ 1 /* quantization */ }; @@ -62,43 +61,37 @@ static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; -/* static SANE_Int empty_data_packet_size = 8; */ - static SANE_Byte empty_data_packet[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static SANE_Byte empty_data_packet[8] = {0xFF}; void clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, - SANE_Byte * destination, SANE_Int * destination_length, SANE_Int mode) + SANE_Byte * destination, SANE_Int * destination_length, + SANE_Int mode) { SANE_Int i = 9; SANE_Int bytes_written = 0; - // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segment length = 32) - // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segment length = 64) - // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segment length = 192) - // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segment length = 1536) - // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segment length = 15000) + // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segmentlng= 32) + // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segmentlng= 64) + // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segmentlng= 192) + // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segmentlng= 1536) + // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segmentlng=15000) - /* DBG (2, "Empty packet? %p %p\n", source[9], source[10]); */ - /* // buffer might contain only ff ff ff ... after data */ - /* if (memcmp(source + 9, empty_data_packet, empty_data_packet_size) == 0 ) */ - /* { */ - /* DBG (2, "Empty packet\n"); */ - /* *destination_length = 0; */ - /* return; */ - /* } */ SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; SANE_Byte tmp = 0; - DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", segment_length, mode); + DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", + segment_length, mode); while (i < source_size) { + // some segments contains only 0xFF ignore them if (memcmp(source + 9, empty_data_packet, 4) == 0 ) break; memcpy (destination + bytes_written, source + i, segment_length); // swap RGB <- BGR if (mode == SANE_FRAME_RGB) { - for(SANE_Int j=bytes_written; j < bytes_written + segment_length; j += 3) + for(SANE_Int j=bytes_written; j < bytes_written + segment_length; + j += 3) { tmp = destination[j]; destination[j] = destination[j+2]; @@ -112,7 +105,9 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, } DBG (20, " destination[] %d %d %d %d", - destination[bytes_written-4], destination[bytes_written-3], destination[bytes_written-2], + destination[bytes_written-4], + destination[bytes_written-3], + destination[bytes_written-2], destination[bytes_written-1]); *destination_length = bytes_written; DBG (10, "clean_and_copy_data done %d\n", *destination_length); @@ -130,14 +125,16 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); if (status != SANE_STATUS_GOOD) { - DBG (1, "USB WRITE IO Error in usb_write_then_read, cannot launch scan status: %d\n", status); + DBG (1, "USB WRITE IO Error in usb_write_then_read, launch fail: %d\n", + status); return status; } - //sanei_usb_set_endpoint(dev->devnum, USB_DIR_IN|USB_ENDPOINT_TYPE_BULK , 0x01); + status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ IO Error in usb_write_then_read, cannot launch scan devnum=%d\n", dev->devnum); + DBG (1, "USB READ IO Error in usb_write_then_read, fail devnum=%d\n", + dev->devnum); return status; } return SANE_STATUS_GOOD; @@ -193,7 +190,7 @@ init_options (Lexmark_Device * dev) od->constraint.range = 0; dev->val[OPT_NUM_OPTS].w = NUM_OPTIONS; - /* mode - sets the scan mode: Color, Gray, or Line Art */ + /* mode - sets the scan mode: Color / Gray */ od = &(dev->opt[OPT_MODE]); od->name = SANE_NAME_SCAN_MODE; od->title = SANE_TITLE_SCAN_MODE; @@ -445,17 +442,20 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) if (status != SANE_STATUS_GOOD) return status; - DBG(2, "sane_open: device `%s' opening devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); + DBG(2, "sane_open: device `%s' opening devnum: '%d'\n", + lexmark_device->sane.name, lexmark_device->devnum); status = sanei_usb_open (lexmark_device->sane.name, &(lexmark_device->devnum)); if (status != SANE_STATUS_GOOD) { - DBG (1, "sane_open: couldn't open device `%s': %s\n", lexmark_device->sane.name, + DBG (1, "sane_open: couldn't open device `%s': %s\n", + lexmark_device->sane.name, sane_strstatus (status)); return status; } else { - DBG (2, "sane_open: device `%s' successfully opened devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); + DBG (2, "sane_open: device `%s' successfully opened devnum: '%d'\n", + lexmark_device->sane.name, lexmark_device->devnum); } return status; @@ -681,7 +681,8 @@ sane_start (SANE_Handle handle) { Lexmark_Device * lexmark_device; SANE_Status status; - SANE_Byte * cmd = (SANE_Byte *) malloc (command_with_params_block_size * sizeof (SANE_Byte));; + SANE_Byte * cmd = (SANE_Byte *) malloc + (command_with_params_block_size * sizeof (SANE_Byte));; DBG (2, "sane_start: handle=%p\n", (void *) handle); @@ -696,22 +697,25 @@ sane_start (SANE_Handle handle) } //launch scan commands - status = usb_write_then_read(lexmark_device, command1_block, command1_block_size); + status = usb_write_then_read(lexmark_device, command1_block, + command1_block_size); if (status != SANE_STATUS_GOOD) return status; - status = usb_write_then_read(lexmark_device, command2_block, command2_block_size); + status = usb_write_then_read(lexmark_device, command2_block, + command2_block_size); if (status != SANE_STATUS_GOOD) return status; build_packet(lexmark_device, 0x05, cmd); - DBG (2, "sane_start: cmd=%p\n", cmd); - status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); + status = usb_write_then_read(lexmark_device, cmd, + command_with_params_block_size); if (status != SANE_STATUS_GOOD) return status; build_packet(lexmark_device, 0x01, cmd);; - status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); + status = usb_write_then_read(lexmark_device, cmd, + command_with_params_block_size); if (status != SANE_STATUS_GOOD) return status; @@ -741,7 +745,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ IO Error in usb_write_then_read, cannot read data devnum=%d\n", + DBG (1, "USB READ Error in usb_write_then_read, cannot read devnum=%d\n", lexmark_device->devnum); return status; } diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index 2b1ec72f4..ad0bdb45e 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -1,6 +1,6 @@ #ifndef LEXMARK_X2600_H #define LEXMARK_X2600_H - +#define BACKEND_NAME lexmark_x2600 #include "../include/sane/config.h" #include From 65c341b9d5b0b2fbdef173735049dbc23ab267a4 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 22:22:25 +0100 Subject: [PATCH 21/49] remove useless edit --- backend/lexmark.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/lexmark.c b/backend/lexmark.c index b3071198f..9a35632ec 100644 --- a/backend/lexmark.c +++ b/backend/lexmark.c @@ -829,9 +829,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) - { return SANE_STATUS_INVAL; - } + /* Make sure boolean values are only TRUE or FALSE */ if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) { From f8bd456aa54435419acd0547b398e22940a2e1ce Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sat, 26 Nov 2022 22:23:28 +0100 Subject: [PATCH 22/49] remove useless edit --- backend/lexmark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/lexmark.c b/backend/lexmark.c index 9a35632ec..3c171c779 100644 --- a/backend/lexmark.c +++ b/backend/lexmark.c @@ -829,7 +829,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, case SANE_ACTION_SET_VALUE: if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) - return SANE_STATUS_INVAL; + return SANE_STATUS_INVAL; /* Make sure boolean values are only TRUE or FALSE */ if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) From 2503ec84979e832ca12c433eef7955985697005d Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sun, 27 Nov 2022 09:55:40 +0100 Subject: [PATCH 23/49] tweak options --- backend/lexmark_x2600.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 1f7e111ad..598710009 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -116,7 +116,7 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, SANE_Status usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) { - size_t buf_size = 128; + size_t buf_size = 256; SANE_Byte buf[buf_size]; SANE_Status status; @@ -225,7 +225,7 @@ init_options (Lexmark_Device * dev) od->title = SANE_TITLE_PREVIEW; od->desc = SANE_DESC_PREVIEW; od->size = sizeof (SANE_Word); - od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->cap = SANE_CAP_INACTIVE; od->type = SANE_TYPE_BOOL; od->constraint_type = SANE_CONSTRAINT_NONE; dev->val[OPT_PREVIEW].w = SANE_FALSE; @@ -246,7 +246,7 @@ init_options (Lexmark_Device * dev) od->title = SANE_TITLE_SCAN_TL_X; od->desc = SANE_DESC_SCAN_TL_X; od->type = SANE_TYPE_INT; - od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->cap = SANE_CAP_INACTIVE; od->size = sizeof (SANE_Word); od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; @@ -259,7 +259,7 @@ init_options (Lexmark_Device * dev) od->title = SANE_TITLE_SCAN_TL_Y; od->desc = SANE_DESC_SCAN_TL_Y; od->type = SANE_TYPE_INT; - od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->cap = SANE_CAP_INACTIVE; od->size = sizeof (SANE_Word); od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; @@ -358,6 +358,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); if (!fp) { + DBG (2, "No config no prob...(%s)\n", LEXMARK_X2600_CONFIG_FILE); return SANE_STATUS_GOOD; } while (sanei_config_read (config_line, sizeof (config_line), fp)) @@ -389,6 +390,8 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", (void *) device_list, local_only); + sanei_usb_scan_devices (); + if (devlist) free (devlist); @@ -400,8 +403,11 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) lexmark_device = first_device; while (lexmark_device != NULL) { + DBG (2, "sane_get_devices: lexmark_device->missing:%d\n", + lexmark_device->missing); if (lexmark_device->missing == SANE_FALSE) { + devlist[index] = &(lexmark_device->sane); index++; } @@ -428,7 +434,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) { - DBG (2, "sane_open: devname from list: %s\n", + DBG (10, "sane_open: devname from list: %s\n", lexmark_device->sane.name); if (strcmp (devicename, "") == 0 || strcmp (devicename, "lexmark") == 0 @@ -663,6 +669,12 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) device_params->pixels_per_line); DBG (2, "sane_get_parameters: device_params->bytes_per_line=%d\n", device_params->bytes_per_line); + DBG (2, "sane_get_parameters: device_params->format=%d\n", + device_params->format); + DBG (2, " SANE_FRAME_GRAY: %d\n", + SANE_FRAME_GRAY); + DBG (2, " SANE_FRAME_RGB: %d\n", + SANE_FRAME_RGB); if (params != 0) { From 1549f87198fa2570a5c723bbfd3d8a468dcb73a5 Mon Sep 17 00:00:00 2001 From: Benoit Juin Date: Sun, 27 Nov 2022 16:40:35 +0100 Subject: [PATCH 24/49] handle cancel --- backend/lexmark_x2600.c | 73 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 598710009..8e8b61b60 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -56,17 +56,33 @@ static SANE_Byte command_with_params_block[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD}; +static SANE_Int command_cancel_size = 28; +static SANE_Byte command_cancel1_block[] = { + 0xa5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xaa, 0xbb, + 0xcc, 0xdd, 0x02, 0x00, 0x1b, 0x53, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, + 0xaa, 0xbb, 0xcc, 0xdd}; +static SANE_Byte command_cancel2_block[] = { + 0xa5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xaa, 0xbb, + 0xcc, 0xdd, 0x02, 0x00, 0x1b, 0x53, 0x06, 0x00, + 0x00, 0x00, 0x80, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, + 0xaa, 0xbb, 0xcc, 0xdd}; + static SANE_Int last_data_packet_size = 9; static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; +static SANE_Int cancel_packet_size = 9; +static SANE_Byte cancel_packet[] = { + 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03}; - static SANE_Byte empty_data_packet[8] = {0xFF}; +static SANE_Byte empty_data_packet[8] = {0xFF}; void clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length, - SANE_Int mode) + SANE_Int mode, SANE_Int max_length) { SANE_Int i = 9; SANE_Int bytes_written = 0; @@ -78,6 +94,10 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; + // edge case segment doesn(t feet in the packet size + /* if(segment_length > source_size - 9) */ + /* segment_length = source_size - 9; */ + SANE_Byte tmp = 0; DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", segment_length, mode); @@ -328,7 +348,7 @@ attach_one (SANE_String_Const devname) lexmark_device->read_buffer = NULL; /* mark device as present */ lexmark_device->missing = SANE_FALSE; - + lexmark_device->device_cancelled = SANE_FALSE; /* insert it a the start of the chained list */ lexmark_device->next = first_device; first_device = lexmark_device; @@ -663,7 +683,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) /* geometry in pixels */ device_params->last_frame = SANE_TRUE; - device_params->lines = lexmark_device->val[OPT_BR_Y].w; + device_params->lines = -1;//lexmark_device->val[OPT_BR_Y].w; DBG (2, "sane_get_parameters: device_params->pixels_per_line=%d\n", device_params->pixels_per_line); @@ -740,6 +760,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, { Lexmark_Device * lexmark_device; SANE_Status status; + size_t size = max_length; + SANE_Byte buf[size]; DBG (20, "sane_read: handle=%p, data=%p, max_length = %d\n", (void *) handle, (void *) data, max_length); @@ -751,8 +773,26 @@ sane_read (SANE_Handle handle, SANE_Byte * data, break; } - size_t size = max_length; - SANE_Byte buf[size]; + if (lexmark_device->device_cancelled == SANE_TRUE) { + usb_write_then_read(lexmark_device, command_cancel1_block, + command_cancel_size); + usb_write_then_read(lexmark_device, command_cancel2_block, + command_cancel_size); + usb_write_then_read(lexmark_device, command_cancel1_block, + command_cancel_size); + usb_write_then_read(lexmark_device, command_cancel2_block, + command_cancel_size); + // to empty buffers + status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + DBG (10, "USB READ \n"); + status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + DBG (10, "USB READ \n"); + status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + DBG (10, "USB READ \n"); + //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + //DBG (10, "USB READ \n"); + return SANE_STATUS_CANCELLED;//SANE_STATUS_GOOD; //; + } status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) @@ -769,7 +809,15 @@ sane_read (SANE_Handle handle, SANE_Byte * data, return SANE_STATUS_EOF; } - clean_and_copy_data(buf, size, data, length, lexmark_device->params.format); + // cancel packet received? + if (memcmp(cancel_packet, buf, cancel_packet_size) == 0) + { + length = 0; + return SANE_STATUS_CANCELLED; + } + + clean_and_copy_data(buf, size, data, length, lexmark_device->params.format, + max_length); return SANE_STATUS_GOOD; } @@ -798,7 +846,18 @@ sane_get_select_fd (SANE_Handle handle, SANE_Int * fd) void sane_cancel (SANE_Handle handle) { + Lexmark_Device * lexmark_device; + DBG (2, "sane_cancel: handle = %p\n", (void *) handle); + + for (lexmark_device = first_device; lexmark_device; + lexmark_device = lexmark_device->next) + { + if (lexmark_device == handle) + break; + } + + lexmark_device->device_cancelled = SANE_TRUE; } void From 02f1a624f3db011cd3d39541667a5bc7fb423106 Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Thu, 23 Nov 2023 08:03:57 +0000 Subject: [PATCH 25/49] Apply 1 suggestion(s) to 1 file(s) --- backend/lexmark_x2600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 8e8b61b60..92c64598f 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -32,12 +32,12 @@ static SANE_Range y_range = { 1 /* quantization */ }; -static SANE_Int command1_block_size = 28; static SANE_Byte command1_block[] = { 0xA5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xAA, 0xBB, 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD}; +static SANE_Int command1_block_size = sizeof(command1_block); static SANE_Int command2_block_size = 28; static SANE_Byte command2_block[] = { From 0098b1c58b82a7d6720d7aaa4dc4c8770a57f648 Mon Sep 17 00:00:00 2001 From: Ralph Little Date: Thu, 23 Nov 2023 08:05:14 +0000 Subject: [PATCH 26/49] Apply 2 suggestion(s) to 1 file(s) --- backend/lexmark_x2600.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 92c64598f..87a86ff97 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -77,10 +77,10 @@ static SANE_Byte cancel_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03}; -static SANE_Byte empty_data_packet[8] = {0xFF}; +static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF}; void -clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, +clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length, SANE_Int mode, SANE_Int max_length) { From 35aed3072ccfc4462057748b66b88d6a4bc44bc3 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Thu, 23 Nov 2023 09:06:12 +0100 Subject: [PATCH 27/49] add debug info --- backend/lexmark_x2600.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 8e8b61b60..42473ddee 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -91,7 +91,10 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segmentlng= 192) // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segmentlng= 1536) // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segmentlng=15000) + // COLOR 1b 53 02 00 f7 0f 00 | | 0ff7 -> 4087 + // COLOR 1b 53 02 00 fa 0f 00 [ [ 0ffa -> 4090 <- in that case the line doesnt fit, clean_and_copy_data will be called again with the rest of the data + // if source doesnt start with 1b 53 02, then it is a continuation packet SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; // edge case segment doesn(t feet in the packet size @@ -99,20 +102,32 @@ clean_and_copy_data(SANE_Byte * source, SANE_Int source_size, /* segment_length = source_size - 9; */ SANE_Byte tmp = 0; - DBG (10, "clean_and_copy_data segment_length:%d mode:%d\n", - segment_length, mode); + + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx \n", source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); + + DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d \n", + segment_length, mode, source_size, *destination_length); + while (i < source_size) { + DBG (20, " i=%d\n", i); // some segments contains only 0xFF ignore them if (memcmp(source + 9, empty_data_packet, 4) == 0 ) break; + + // works: clean_and_copy_data segment_length:4086 mode:1 source_size=16380 destination_length=32688 source[3] source[4] source[5] = 00 f7 0f + // fails: clean_and_copy_data segment_length:62972 mode:1 source_size=16 destination_length=32712 source[3] source[4] source[5] = f5 f9 f4 + memcpy (destination + bytes_written, source + i, segment_length); + DBG (20, " i=%d memcpy done\n", i); // swap RGB <- BGR if (mode == SANE_FRAME_RGB) { for(SANE_Int j=bytes_written; j < bytes_written + segment_length; j += 3) { + // DBG (20, " swapping RGB <- BGR j=%d\n", j); + tmp = destination[j]; destination[j] = destination[j+2]; destination[j+2] = tmp; @@ -763,7 +778,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, size_t size = max_length; SANE_Byte buf[size]; - DBG (20, "sane_read: handle=%p, data=%p, max_length = %d\n", + DBG (1, "sane_read: handle=%p, data=%p, max_length=%d\n", (void *) handle, (void *) data, max_length); for (lexmark_device = first_device; lexmark_device; From 0a0afc2a710ce705a678107da59f9534fcb8407a Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Thu, 23 Nov 2023 09:13:29 +0100 Subject: [PATCH 28/49] fix typo --- backend/lexmark_x2600.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index aa467618b..277d325e8 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -77,7 +77,7 @@ static SANE_Byte cancel_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03}; -static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF, 0xFF}; +static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; void clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, @@ -103,10 +103,10 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte tmp = 0; - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx \n", source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx \n", source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); - DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d \n", - segment_length, mode, source_size, *destination_length); + DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d\n", + segment_length, mode, source_size, *destination_length, max_length); while (i < source_size) { From 6e9f4b3785f231e26a1a1d608d98c632a0031eaf Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Thu, 23 Nov 2023 09:40:54 +0100 Subject: [PATCH 29/49] fix debug line --- backend/lexmark_x2600.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 277d325e8..b0e58ba59 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -39,14 +39,13 @@ static SANE_Byte command1_block[] = { 0xAA, 0xBB, 0xCC, 0xDD}; static SANE_Int command1_block_size = sizeof(command1_block); -static SANE_Int command2_block_size = 28; static SANE_Byte command2_block[] = { 0xA5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xAA, 0xBB, 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD}; +static SANE_Int command2_block_size = sizeof(command2_block); -static SANE_Int command_with_params_block_size = 52; static SANE_Byte command_with_params_block[] = { 0xA5, 0x00, 0x31, 0x10, 0x01, 0x83, 0xAA, 0xBB, 0xCC, 0xDD, 0x02, 0x00, 0x1B, 0x53, 0x05, 0x00, @@ -55,8 +54,8 @@ static SANE_Byte command_with_params_block[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, 0xAA, 0xBB, 0xCC, 0xDD}; +static SANE_Int command_with_params_block_size = sizeof(command_with_params_block); -static SANE_Int command_cancel_size = 28; static SANE_Byte command_cancel1_block[] = { 0xa5, 0x00, 0x19, 0x10, 0x01, 0x83, 0xaa, 0xbb, 0xcc, 0xdd, 0x02, 0x00, 0x1b, 0x53, 0x0f, 0x00, @@ -67,15 +66,17 @@ static SANE_Byte command_cancel2_block[] = { 0xcc, 0xdd, 0x02, 0x00, 0x1b, 0x53, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xaa, 0xbb, 0xcc, 0xdd}; +static SANE_Int command_cancel_size = sizeof(command_cancel1_block); -static SANE_Int last_data_packet_size = 9; static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; -static SANE_Int cancel_packet_size = 9; +static SANE_Int last_data_packet_size = sizeof(last_data_packet); + static SANE_Byte cancel_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03}; +static SANE_Int cancel_packet_size = sizeof(cancel_packet); static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -94,8 +95,6 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // COLOR 1b 53 02 00 f7 0f 00 | | 0ff7 -> 4087 // COLOR 1b 53 02 00 fa 0f 00 [ [ 0ffa -> 4090 <- in that case the line doesnt fit, clean_and_copy_data will be called again with the rest of the data - // if source doesnt start with 1b 53 02, then it is a continuation packet - SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; // edge case segment doesn(t feet in the packet size /* if(segment_length > source_size - 9) */ @@ -107,6 +106,11 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d\n", segment_length, mode, source_size, *destination_length, max_length); + + + //if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) + // if source doesnt start with 1b 53 02, then it is a continuation packet + while (i < source_size) { From 51aaef6d81a813cf5549a6b8154198f76d3fad25 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Fri, 24 Nov 2023 06:09:27 +0100 Subject: [PATCH 30/49] WIP: fill a buffer instead of messy sync read/write --- backend/lexmark_x2600.c | 376 ++++++++++++++++++++++++++-------------- 1 file changed, 248 insertions(+), 128 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index b0e58ba59..1b1a4e87e 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -68,6 +68,15 @@ static SANE_Byte command_cancel2_block[] = { 0xaa, 0xbb, 0xcc, 0xdd}; static SANE_Int command_cancel_size = sizeof(command_cancel1_block); +static SANE_Byte unknnown_d_data_packet[] = { + 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00}; +static SANE_Int unknnown_d_data_packet_size = sizeof(unknnown_d_data_packet); + +static SANE_Byte empty_line_data_packet[] = { + 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00}; +static SANE_Int empty_line_data_packet_size = sizeof(empty_line_data_packet); + static SANE_Byte last_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01}; @@ -78,52 +87,147 @@ static SANE_Byte cancel_packet[] = { 0x03}; static SANE_Int cancel_packet_size = sizeof(cancel_packet); -static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static SANE_Byte linebegin_data_packet[] = { + 0x1b, 0x53, 0x02, 0x00}; +static SANE_Int linebegin_data_packet_size = sizeof(linebegin_data_packet); + +static SANE_Byte unknnown_a_data_packet[] = { + 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; +static SANE_Int unknnown_a_data_packet_size = sizeof(unknnown_a_data_packet); + +static SANE_Byte unknnown_c_data_packet[] = { + 0x1b, 0x53, 0x05, 0x00, 0x00, 0x00}; +static SANE_Int unknnown_c_data_packet_size = sizeof(unknnown_c_data_packet); + +static SANE_Byte unknnown_b_data_packet[] = { + 0xa5, 0x00, 0x06, 0x10, 0x01, 0xaa, 0xbb, 0xcc, + 0xdd}; +static SANE_Int unknnown_b_data_packet_size = sizeof(unknnown_b_data_packet); + + + + +//static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; void clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length, - SANE_Int mode, SANE_Int max_length) + SANE_Int mode, SANE_Int max_length, SANE_Handle dev) { - SANE_Int i = 9; + + // if source doesnt start with 1b 53 02, then it is a continuation packet + if (memcmp(empty_line_data_packet, source, empty_line_data_packet_size) == 0){ + return; + } + if (memcmp(unknnown_a_data_packet, source, unknnown_a_data_packet_size) == 0){ + return; + } + if (memcmp(unknnown_b_data_packet, source, unknnown_b_data_packet_size) == 0){ + return; + } + if (memcmp(unknnown_c_data_packet, source, unknnown_c_data_packet_size) == 0){ + return; + } + if (memcmp(unknnown_d_data_packet, source, unknnown_d_data_packet_size) == 0){ + return; + } + + Lexmark_Device * ldev = (Lexmark_Device * ) dev; + + SANE_Int i = 0; + SANE_Int k = 0; + SANE_Int overflow = 0; SANE_Int bytes_written = 0; + SANE_Int segment_length = source_size;//ldev->bytes_remaining; + SANE_Int offset = 0; + SANE_Int end_offset = 0; + SANE_Byte tmp = 0; // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segmentlng= 32) // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segmentlng= 64) // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segmentlng= 192) // COLOR 1b 53 02 00 01 06 00 00 00 | 512 | 601 -> 1537 (segmentlng= 1536) // COLOR 1b 53 02 00 99 3a 00 00 00 | 5000 | 3a99 -> 15001 (segmentlng=15000) - // COLOR 1b 53 02 00 f7 0f 00 | | 0ff7 -> 4087 - // COLOR 1b 53 02 00 fa 0f 00 [ [ 0ffa -> 4090 <- in that case the line doesnt fit, clean_and_copy_data will be called again with the rest of the data + // COLOR 1b 53 02 00 f7 0f 00 | 1362 | 0ff7 -> 4087 <- limit where sane_read can a read a line at e time, more that 1362 and then the rest + // of the line will be available in the next sane_read call + // COLOR 1b 53 02 00 fa 0f 00 | | 0ffa -> 4090 <- in that case the line doesnt fit, clean_and_copy_data will be called again with the rest of the data + - SANE_Int segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; // edge case segment doesn(t feet in the packet size /* if(segment_length > source_size - 9) */ /* segment_length = source_size - 9; */ - SANE_Byte tmp = 0; + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[8], source[9], source[10], source[11], source[12], source[13], source[14], source[15]); + if(source_size > 16){ + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[source_size-16], + source[source_size-15], + source[source_size-14], + source[source_size-13], + source[source_size-12], + source[source_size-11], + source[source_size-10], + source[source_size-9]); + DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[source_size-8], + source[source_size-7], + source[source_size-6], + source[source_size-5], + source[source_size-4], + source[source_size-3], + source[source_size-2], + source[source_size-1]); + } - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx \n", source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); - - DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d\n", - segment_length, mode, source_size, *destination_length, max_length); + DBG (10, "\n"); - //if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) - // if source doesnt start with 1b 53 02, then it is a continuation packet + // fill the read buffer from source + ldev->read_buffer->size += source_size; + DBG (10, "size=%ld source_size=%d\n", ldev->read_buffer->size, source_size); + SANE_Byte* alloc_result = realloc( + ldev->read_buffer->data, + ldev->read_buffer->size*sizeof(SANE_Byte)); + DBG (10, "ALLOC done\n"); + if(alloc_result==NULL){ + // TODO no more memory + } + + ldev->read_buffer->data = alloc_result; + // point to the end of our new alloceted buffer minus the source_size + ldev->read_buffer->writeptr = ldev->read_buffer->data + \ + ldev->read_buffer->size - source_size; + memcpy(ldev->read_buffer->writeptr, source, source_size); + + // if source doesnt start with 1b 53 02, then it is a continuation packet + if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ + segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; + offset = 9; + i = offset; + //ldev->bytes_remaining = segment_length; + end_offset = source_size % (segment_length+9); + } else { + DBG (20, "this is not a new line packet, continu current data line\n"); + //return; + } + DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d i=%d offset=%d bytes_remaining=%ld end_offset=%d\n", + segment_length, mode, source_size, *destination_length, max_length, i, offset, ldev->bytes_remaining, end_offset); - while (i < source_size) { - DBG (20, " i=%d\n", i); // some segments contains only 0xFF ignore them - if (memcmp(source + 9, empty_data_packet, 4) == 0 ) - break; + //if (memcmp(source + offset, empty_data_packet, 4) == 0 ) + // break; - // works: clean_and_copy_data segment_length:4086 mode:1 source_size=16380 destination_length=32688 source[3] source[4] source[5] = 00 f7 0f - // fails: clean_and_copy_data segment_length:62972 mode:1 source_size=16 destination_length=32712 source[3] source[4] source[5] = f5 f9 f4 - - memcpy (destination + bytes_written, source + i, segment_length); - DBG (20, " i=%d memcpy done\n", i); + if(i + segment_length <= max_length){ + memcpy (destination + bytes_written, source + i, segment_length); + }else{ + memcpy (destination + bytes_written, source + i, max_length - i); + } + DBG (20, " i=%d + segment_length=%d = %d\n", i, segment_length, i + segment_length); + overflow = i + segment_length - max_length; // swap RGB <- BGR if (mode == SANE_FRAME_RGB) { @@ -131,25 +235,38 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, j += 3) { // DBG (20, " swapping RGB <- BGR j=%d\n", j); - tmp = destination[j]; destination[j] = destination[j+2]; destination[j+2] = tmp; } } - - bytes_written += segment_length; - i += segment_length + 9; - DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); + if(i + segment_length < max_length){ + bytes_written += segment_length; + }else{ + bytes_written += (max_length - i); + } + i += segment_length + offset; + k++; + DBG (20, " k=%d i=%d bytes_written=%d\n", k, i, bytes_written); + //DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); } - DBG (20, " destination[] %d %d %d %d", - destination[bytes_written-4], - destination[bytes_written-3], - destination[bytes_written-2], - destination[bytes_written-1]); - *destination_length = bytes_written; - DBG (10, "clean_and_copy_data done %d\n", *destination_length); + + /* DBG (20, " destination[] %d %d %d %d", */ + /* destination[bytes_written-4], */ + /* destination[bytes_written-3], */ + /* destination[bytes_written-2], */ + /* destination[bytes_written-1]); */ + DBG (20, " overflow=%d\n", overflow); + + if(overflow > 0){ + *destination_length = bytes_written; // - 40 + }else{ + *destination_length = bytes_written; + } + + //ldev->bytes_remaining -= bytes_written; + DBG (10, "bytes_written=%d\n", bytes_written); } SANE_Status @@ -350,7 +467,7 @@ attach_one (SANE_String_Const devname) if (strcmp (lexmark_device->sane.name, devname) == 0) { lexmark_device->missing = SANE_FALSE; - return SANE_STATUS_GOOD; + return SANE_STATUS_GOOD; } } @@ -364,7 +481,10 @@ attach_one (SANE_String_Const devname) lexmark_device->sane.type = "flat bed"; /* Make the pointer to the read buffer null here */ - lexmark_device->read_buffer = NULL; + lexmark_device->read_buffer = malloc (sizeof (Read_Buffer)); + //lexmark_device->read_buffer->writeptr = lexmark_device->read_buffer; + //lexmark_device->read_buffer->readptr = lexmark_device->read_buffer; + lexmark_device->read_buffer->size = 0; /* mark device as present */ lexmark_device->missing = SANE_FALSE; lexmark_device->device_cancelled = SANE_FALSE; @@ -403,12 +523,12 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) while (sanei_config_read (config_line, sizeof (config_line), fp)) { if (config_line[0] == '#') - continue; /* ignore line comments */ + continue; /* ignore line comments */ lp = sanei_config_skip_whitespace (config_line); /* skip empty lines */ if (*lp == 0) - continue; + continue; DBG (4, "attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices (config_line, attach_one); @@ -445,11 +565,11 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) DBG (2, "sane_get_devices: lexmark_device->missing:%d\n", lexmark_device->missing); if (lexmark_device->missing == SANE_FALSE) - { + { - devlist[index] = &(lexmark_device->sane); - index++; - } + devlist[index] = &(lexmark_device->sane); + index++; + } lexmark_device = lexmark_device->next; } devlist[index] = 0; @@ -474,11 +594,11 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) lexmark_device = lexmark_device->next) { DBG (10, "sane_open: devname from list: %s\n", - lexmark_device->sane.name); + lexmark_device->sane.name); if (strcmp (devicename, "") == 0 - || strcmp (devicename, "lexmark") == 0 - || strcmp (devicename, lexmark_device->sane.name) == 0) - break; + || strcmp (devicename, "lexmark") == 0 + || strcmp (devicename, lexmark_device->sane.name) == 0) + break; } *handle = lexmark_device; @@ -494,7 +614,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) { DBG (1, "sane_open: couldn't open device `%s': %s\n", lexmark_device->sane.name, - sane_strstatus (status)); + sane_strstatus (status)); return status; } else @@ -522,7 +642,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } if (!lexmark_device) @@ -531,7 +651,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) if (lexmark_device->opt[option].name) { DBG (2, "sane_get_option_descriptor: name=%s\n", - lexmark_device->opt[option].name); + lexmark_device->opt[option].name); } return &(lexmark_device->opt[option]); @@ -552,7 +672,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } @@ -568,88 +688,88 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, } /* Make sure boolean values are only TRUE or FALSE */ if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) - { - if (! - ((*(SANE_Bool *) value == SANE_FALSE) - || (*(SANE_Bool *) value == SANE_TRUE))) - return SANE_STATUS_INVAL; - } + { + if (! + ((*(SANE_Bool *) value == SANE_FALSE) + || (*(SANE_Bool *) value == SANE_TRUE))) + return SANE_STATUS_INVAL; + } /* Check range constraints */ if (lexmark_device->opt[option].constraint_type == - SANE_CONSTRAINT_RANGE) - { - status = - sanei_constrain_value (&(lexmark_device->opt[option]), value, - info); - if (status != SANE_STATUS_GOOD) - { - DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); - return SANE_STATUS_INVAL; - } - } + SANE_CONSTRAINT_RANGE) + { + status = + sanei_constrain_value (&(lexmark_device->opt[option]), value, + info); + if (status != SANE_STATUS_GOOD) + { + DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); + return SANE_STATUS_INVAL; + } + } switch (option) - { - case OPT_NUM_OPTS: - case OPT_RESOLUTION: - case OPT_TL_X: - case OPT_TL_Y: - case OPT_BR_X: - case OPT_BR_Y: - DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, - lexmark_device->opt[option].name); - lexmark_device->val[option].w = *(SANE_Word *) value; - if (lexmark_device->val[OPT_TL_X].w > - lexmark_device->val[OPT_BR_X].w) - { - w = lexmark_device->val[OPT_TL_X].w; - lexmark_device->val[OPT_TL_X].w = - lexmark_device->val[OPT_BR_X].w; - lexmark_device->val[OPT_BR_X].w = w; - if (info) - *info |= SANE_INFO_RELOAD_PARAMS; - } - if (lexmark_device->val[OPT_TL_Y].w > - lexmark_device->val[OPT_BR_Y].w) - { - w = lexmark_device->val[OPT_TL_Y].w; - lexmark_device->val[OPT_TL_Y].w = - lexmark_device->val[OPT_BR_Y].w; - lexmark_device->val[OPT_BR_Y].w = w; - if (info) - *info |= SANE_INFO_RELOAD_PARAMS; - } - break; - case OPT_MODE: - strcpy (lexmark_device->val[option].s, value); - if (info) - *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; - } + { + case OPT_NUM_OPTS: + case OPT_RESOLUTION: + case OPT_TL_X: + case OPT_TL_Y: + case OPT_BR_X: + case OPT_BR_Y: + DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, + lexmark_device->opt[option].name); + lexmark_device->val[option].w = *(SANE_Word *) value; + if (lexmark_device->val[OPT_TL_X].w > + lexmark_device->val[OPT_BR_X].w) + { + w = lexmark_device->val[OPT_TL_X].w; + lexmark_device->val[OPT_TL_X].w = + lexmark_device->val[OPT_BR_X].w; + lexmark_device->val[OPT_BR_X].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } + if (lexmark_device->val[OPT_TL_Y].w > + lexmark_device->val[OPT_BR_Y].w) + { + w = lexmark_device->val[OPT_TL_Y].w; + lexmark_device->val[OPT_TL_Y].w = + lexmark_device->val[OPT_BR_Y].w; + lexmark_device->val[OPT_BR_Y].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } + break; + case OPT_MODE: + strcpy (lexmark_device->val[option].s, value); + if (info) + *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; + return SANE_STATUS_GOOD; + } if (info != NULL) - *info |= SANE_INFO_RELOAD_PARAMS; + *info |= SANE_INFO_RELOAD_PARAMS; break; case SANE_ACTION_GET_VALUE: switch (option) - { - 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: - *(SANE_Word *) value = lexmark_device->val[option].w; - DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, - lexmark_device->opt[option].name); - break; - case OPT_MODE: - strcpy (value, lexmark_device->val[option].s); - break; - } + { + 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: + *(SANE_Word *) value = lexmark_device->val[option].w; + DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, + lexmark_device->opt[option].name); + break; + case OPT_MODE: + strcpy (value, lexmark_device->val[option].s); + break; + } break; default: @@ -673,7 +793,7 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } if (!lexmark_device) @@ -744,7 +864,7 @@ sane_start (SANE_Handle handle) lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } //launch scan commands @@ -775,7 +895,7 @@ sane_start (SANE_Handle handle) SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, - SANE_Int max_length, SANE_Int * length) + SANE_Int max_length, SANE_Int * length) { Lexmark_Device * lexmark_device; SANE_Status status; @@ -789,7 +909,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } if (lexmark_device->device_cancelled == SANE_TRUE) { @@ -836,7 +956,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, } clean_and_copy_data(buf, size, data, length, lexmark_device->params.format, - max_length); + max_length, handle); return SANE_STATUS_GOOD; } @@ -873,7 +993,7 @@ sane_cancel (SANE_Handle handle) lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } lexmark_device->device_cancelled = SANE_TRUE; @@ -890,7 +1010,7 @@ sane_close (SANE_Handle handle) lexmark_device = lexmark_device->next) { if (lexmark_device == handle) - break; + break; } sanei_usb_close (lexmark_device->devnum); From 94b67794a5b0e1b8a19cdfd1cdd622852838fca4 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sat, 25 Nov 2023 06:15:33 +0100 Subject: [PATCH 31/49] handle high dpi and use a buffer to read data --- backend/lexmark_x2600.c | 337 ++++++++++++++++++++++++++++------------ backend/lexmark_x2600.h | 5 +- 2 files changed, 241 insertions(+), 101 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 1b1a4e87e..952fb58d2 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -104,7 +104,7 @@ static SANE_Byte unknnown_b_data_packet[] = { 0xdd}; static SANE_Int unknnown_b_data_packet_size = sizeof(unknnown_b_data_packet); - +static SANE_Int line_header_length = 9; //static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -135,13 +135,9 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, Lexmark_Device * ldev = (Lexmark_Device * ) dev; SANE_Int i = 0; - SANE_Int k = 0; - SANE_Int overflow = 0; - SANE_Int bytes_written = 0; - SANE_Int segment_length = source_size;//ldev->bytes_remaining; - SANE_Int offset = 0; - SANE_Int end_offset = 0; - SANE_Byte tmp = 0; + // SANE_Int k = 0; + // SANE_Int bytes_written = 0; + // SANE_Byte tmp = 0; // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segmentlng= 32) // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segmentlng= 64) // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segmentlng= 192) @@ -160,113 +156,253 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", source[8], source[9], source[10], source[11], source[12], source[13], source[14], source[15]); - if(source_size > 16){ + int debug_offset = 4092; + if(source_size > debug_offset){ DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[source_size-16], - source[source_size-15], - source[source_size-14], - source[source_size-13], - source[source_size-12], - source[source_size-11], - source[source_size-10], - source[source_size-9]); + source[source_size-16-debug_offset], + source[source_size-15-debug_offset], + source[source_size-14-debug_offset], + source[source_size-13-debug_offset], + source[source_size-12-debug_offset], + source[source_size-11-debug_offset], + source[source_size-10-debug_offset], + source[source_size-9]-debug_offset); DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[source_size-8], - source[source_size-7], - source[source_size-6], - source[source_size-5], - source[source_size-4], - source[source_size-3], - source[source_size-2], - source[source_size-1]); + source[source_size-8-debug_offset], + source[source_size-7-debug_offset], + source[source_size-6-debug_offset], + source[source_size-5-debug_offset], + source[source_size-4-debug_offset], + source[source_size-3-debug_offset], + source[source_size-2-debug_offset], + source[source_size-1-debug_offset]); } DBG (10, "\n"); + // the scanner sends series of 8 lines function param source + // every lines has prefix see linebegin_data_packet + // the source parameter as a limited length :function param source_size + // so the serie og 8 lines can be splited + // in such case, in the next call of this function, source contain the end of the + // broken segment. + // Here is the way data is read: + // 1 - check that source begin with a linebegin_data_packet signature + // if this is the case the source[4] & source[5] contains how much data + // can be read before onother header is reach (linebegin_data_packet) - // fill the read buffer from source - ldev->read_buffer->size += source_size; - DBG (10, "size=%ld source_size=%d\n", ldev->read_buffer->size, source_size); - SANE_Byte* alloc_result = realloc( - ldev->read_buffer->data, - ldev->read_buffer->size*sizeof(SANE_Byte)); - DBG (10, "ALLOC done\n"); - if(alloc_result==NULL){ - // TODO no more memory - } - - ldev->read_buffer->data = alloc_result; - // point to the end of our new alloceted buffer minus the source_size - ldev->read_buffer->writeptr = ldev->read_buffer->data + \ - ldev->read_buffer->size - source_size; - memcpy(ldev->read_buffer->writeptr, source, source_size); - - // if source doesnt start with 1b 53 02, then it is a continuation packet + // does source start with linebegin_data_packet? if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ - segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; - offset = 9; - i = offset; - //ldev->bytes_remaining = segment_length; - end_offset = source_size % (segment_length+9); + // extract the number of bytes we can read befor new header is reached + // store it in the device in case of continuation packet + ldev->read_buffer->linesize = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; + DBG (20, "this is the begining of a line linesize=%ld\n", + ldev->read_buffer->linesize); } else { - DBG (20, "this is not a new line packet, continu current data line\n"); + DBG (20, "this is not a new line packet, continue to fill the read buffer\n"); //return; } - DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d i=%d offset=%d bytes_remaining=%ld end_offset=%d\n", - segment_length, mode, source_size, *destination_length, max_length, i, offset, ldev->bytes_remaining, end_offset); - while (i < source_size) - { - // some segments contains only 0xFF ignore them - //if (memcmp(source + offset, empty_data_packet, 4) == 0 ) - // break; - if(i + segment_length <= max_length){ - memcpy (destination + bytes_written, source + i, segment_length); - }else{ - memcpy (destination + bytes_written, source + i, max_length - i); - } - DBG (20, " i=%d + segment_length=%d = %d\n", i, segment_length, i + segment_length); - overflow = i + segment_length - max_length; - // swap RGB <- BGR - if (mode == SANE_FRAME_RGB) - { - for(SANE_Int j=bytes_written; j < bytes_written + segment_length; - j += 3) - { - // DBG (20, " swapping RGB <- BGR j=%d\n", j); - tmp = destination[j]; - destination[j] = destination[j+2]; - destination[j+2] = tmp; - } + // fill out buffer stored in ldev->read_buffer->data + // loop on data + while (i < source_size){ + // last line was full + if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ + // current line number + ldev->read_buffer->image_line_no += 1; + + // if next block fit in the source + if(i + line_header_length + ldev->read_buffer->linesize <= source_size){ + DBG (20, "last line was full\n"); + // extract the first line + // allocate + SANE_Int size_to_realloc = ldev->read_buffer->image_line_no * + ldev->read_buffer->linesize * sizeof(SANE_Byte); + DBG (20, "size_to_realloc=%d\n", size_to_realloc); + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; + SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); + if(alloc_result == NULL){ + // TODO allocation was not possible + DBG (20, "REALLOC failed\n"); } - if(i + segment_length < max_length){ - bytes_written += segment_length; - }else{ - bytes_written += (max_length - i); + ldev->read_buffer->data = alloc_result; + // set write pointer + ldev->read_buffer->writeptr = + ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; + ldev->read_buffer->readptr = + ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; + // copy data + memcpy(ldev->read_buffer->writeptr, source + i + line_header_length, ldev->read_buffer->linesize); + ldev->read_buffer->write_byte_counter += ldev->read_buffer->linesize; + } - i += segment_length + offset; - k++; - DBG (20, " k=%d i=%d bytes_written=%d\n", k, i, bytes_written); - //DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); + + // last line was not full lets extract what is left + else{ + DBG (20, "next line doesnt fit %d < %ld sourcesize=%d i=%d\n", + source_size, i + line_header_length + ldev->read_buffer->linesize, + source_size, i); + SANE_Int bytes_left = source_size - i - line_header_length; + ldev->read_buffer->last_line_bytes_read = bytes_left; + DBG (20, " ldev->read_buffer->write_byte_counter=%d bytes_left=%d\n", + ldev->read_buffer->write_byte_counter, bytes_left); + // so copy what is left + SANE_Int size_to_realloc = ((ldev->read_buffer->image_line_no-1) * + ldev->read_buffer->linesize + bytes_left) * sizeof(SANE_Byte); + DBG (20, "size_to_realloc=%d\n", size_to_realloc); + SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); + if(alloc_result == NULL){ + // TODO allocation was not possible + DBG (20, "REALLOC failed\n"); + } + ldev->read_buffer->data = alloc_result; + // set write pointer + ldev->read_buffer->writeptr = + ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; + ldev->read_buffer->readptr = + ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; + // copy data + //DBG (20, "REALLOC bytes_left=%d\n", bytes_left); + memcpy(ldev->read_buffer->writeptr, source + i + line_header_length, bytes_left); + ldev->read_buffer->write_byte_counter += bytes_left; + + } + // shift 'i' to next line + i += ldev->read_buffer->linesize + line_header_length; + }else{ + // this packet is begeging with the end of a line from the last usb packet + SANE_Int bytes_left = ldev->read_buffer->linesize - ldev->read_buffer->last_line_bytes_read; + DBG (20, "last line was splitted bytes_left=%d write_byte_counter=%d\n", + bytes_left, ldev->read_buffer->write_byte_counter); + // we filled our last line so tell it + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; + + SANE_Int size_to_realloc = ldev->read_buffer->image_line_no * + ldev->read_buffer->linesize * sizeof(SANE_Byte); + DBG (20, "size_to_realloc=%d\n", size_to_realloc); + SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); + if(alloc_result == NULL){ + // TODO allocation was not possible + DBG (20, "REALLOC failed\n"); + } + ldev->read_buffer->data = alloc_result; + // reposition write/read pointer + ldev->read_buffer->writeptr = + ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; + ldev->read_buffer->readptr = + ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; + // copy data + memcpy(ldev->read_buffer->writeptr, source + i, bytes_left); + ldev->read_buffer->write_byte_counter += bytes_left; + // shift 'i' to next line + i += bytes_left; } - - - /* DBG (20, " destination[] %d %d %d %d", */ - /* destination[bytes_written-4], */ - /* destination[bytes_written-3], */ - /* destination[bytes_written-2], */ - /* destination[bytes_written-1]); */ - DBG (20, " overflow=%d\n", overflow); - - if(overflow > 0){ - *destination_length = bytes_written; // - 40 - }else{ - *destination_length = bytes_written; + DBG (20, "i=%d image_line_no=%d\n", i, ldev->read_buffer->image_line_no); } - //ldev->bytes_remaining -= bytes_written; - DBG (10, "bytes_written=%d\n", bytes_written); + + // read our buffer to fill the destination buffer + // mulitple call so read may has been already started + // length already read is stored in ldev->read_buffer->read_byte_counter + DBG (20, "##### source read done now sending to destination\n"); + SANE_Int bytes_to_read = + ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; + //DBG (20, "memcopy bytes_to_read=%d\n", bytes_to_read); + memcpy (destination, ldev->read_buffer->readptr, bytes_to_read); + ldev->read_buffer->read_byte_counter += bytes_to_read; + //ldev->read_buffer->readptr += bytes_to_read; + + *destination_length = bytes_to_read; + //DBG (20, "done destination_length=%d\n\n\n", bytes_to_read); + + + /* // fill the read buffer from source */ + /* ldev->read_buffer->size += (source_size - offset); */ + /* DBG (10, "size=%ld source_size=%d offset=%d\n", */ + /* ldev->read_buffer->size, source_size, offset); */ + /* SANE_Byte* alloc_result = realloc( */ + /* ldev->read_buffer->data, */ + /* ldev->read_buffer->size*sizeof(SANE_Byte)); */ + /* DBG (10, "ALLOC done\n"); */ + /* if(alloc_result==NULL){ */ + /* // TODO no more memory */ + /* } */ + /* ldev->read_buffer->data = alloc_result; */ + /* // point to the end of our new alloceted buffer minus the source_size - offset */ + /* ldev->read_buffer->writeptr = ldev->read_buffer->data + \ */ + /* ldev->read_buffer->size - (source_size - offset); */ + /* memcpy(ldev->read_buffer->writeptr, source + offset, source_size - offset); */ + + + + /* // if source doesnt start with 1b 53 02, then it is a continuation packet */ + /* if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ */ + /* segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; */ + /* offset = 9; */ + /* i = offset; */ + /* //ldev->bytes_remaining = segment_length; */ + /* end_offset = source_size % (segment_length+9); */ + /* } else { */ + /* DBG (20, "this is not a new line packet, continu current data line\n"); */ + /* //return; */ + /* } */ + /* DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d i=%d offset=%d bytes_remaining=%ld end_offset=%d\n", */ + /* segment_length, mode, source_size, *destination_length, max_length, i, offset, ldev->bytes_remaining, end_offset); */ + + /* while (i < source_size) */ + /* { */ + /* // some segments contains only 0xFF ignore them */ + /* //if (memcmp(source + offset, empty_data_packet, 4) == 0 ) */ + /* // break; */ + + /* if(i + segment_length <= max_length){ */ + /* memcpy (destination + bytes_written, source + i, segment_length); */ + /* }else{ */ + /* memcpy (destination + bytes_written, source + i, max_length - i); */ + /* } */ + /* DBG (20, " i=%d + segment_length=%d = %d\n", i, segment_length, i + segment_length); */ + /* overflow = i + segment_length - max_length; */ + /* // swap RGB <- BGR */ + /* if (mode == SANE_FRAME_RGB) */ + /* { */ + /* for(SANE_Int j=bytes_written; j < bytes_written + segment_length; */ + /* j += 3) */ + /* { */ + /* // DBG (20, " swapping RGB <- BGR j=%d\n", j); */ + /* tmp = destination[j]; */ + /* destination[j] = destination[j+2]; */ + /* destination[j+2] = tmp; */ + /* } */ + /* } */ + /* if(i + segment_length < max_length){ */ + /* bytes_written += segment_length; */ + /* }else{ */ + /* bytes_written += (max_length - i); */ + /* } */ + /* i += segment_length + offset; */ + /* k++; */ + /* DBG (20, " k=%d i=%d bytes_written=%d\n", k, i, bytes_written); */ + /* //DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); */ + /* } */ + + + /* /\* DBG (20, " destination[] %d %d %d %d", *\/ */ + /* /\* destination[bytes_written-4], *\/ */ + /* /\* destination[bytes_written-3], *\/ */ + /* /\* destination[bytes_written-2], *\/ */ + /* /\* destination[bytes_written-1]); *\/ */ + /* DBG (20, " overflow=%d\n", overflow); */ + + /* if(overflow > 0){ */ + /* *destination_length = bytes_written; // - 40 */ + /* }else{ */ + /* *destination_length = bytes_written; */ + /* } */ + + /* //ldev->bytes_remaining -= bytes_written; */ + /* DBG (10, "bytes_written=%d\n", bytes_written); */ } SANE_Status @@ -482,9 +618,12 @@ attach_one (SANE_String_Const devname) /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = malloc (sizeof (Read_Buffer)); - //lexmark_device->read_buffer->writeptr = lexmark_device->read_buffer; - //lexmark_device->read_buffer->readptr = lexmark_device->read_buffer; + lexmark_device->read_buffer->data = NULL; lexmark_device->read_buffer->size = 0; + lexmark_device->read_buffer->last_line_bytes_read = 0; + lexmark_device->read_buffer->image_line_no = 0; + lexmark_device->read_buffer->write_byte_counter = 0; + lexmark_device->read_buffer->read_byte_counter = 0; /* mark device as present */ lexmark_device->missing = SANE_FALSE; lexmark_device->device_cancelled = SANE_FALSE; diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index ad0bdb45e..223a44e66 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -42,10 +42,11 @@ typedef struct Read_Buffer SANE_Byte *max_writeptr; size_t size; size_t linesize; + size_t last_line_bytes_read; SANE_Bool empty; SANE_Int image_line_no; - SANE_Int bit_counter; - SANE_Int max_lineart_offset; + SANE_Int write_byte_counter; + SANE_Int read_byte_counter; } Read_Buffer; From 768fa3bf5982c099adec67ab8bb7b304ce00f4fb Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sat, 25 Nov 2023 07:18:22 +0100 Subject: [PATCH 32/49] refactor more readable --- backend/lexmark_x2600.c | 241 +++++++++++----------------------------- 1 file changed, 64 insertions(+), 177 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 952fb58d2..4ebcdd5f3 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -133,8 +133,8 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, } Lexmark_Device * ldev = (Lexmark_Device * ) dev; - SANE_Int i = 0; + SANE_Int bytes_read = 0; // SANE_Int k = 0; // SANE_Int bytes_written = 0; // SANE_Byte tmp = 0; @@ -204,105 +204,80 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, //return; } - - // fill out buffer stored in ldev->read_buffer->data - // loop on data - while (i < source_size){ + SANE_Int source_read_cursor = 0; + SANE_Int block_pixel_data_length = 0; + SANE_Byte* alloc_result; + SANE_Int size_to_realloc = 0; + while(i < source_size){ // last line was full if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ - // current line number - ldev->read_buffer->image_line_no += 1; - // if next block fit in the source if(i + line_header_length + ldev->read_buffer->linesize <= source_size){ - DBG (20, "last line was full\n"); - // extract the first line - // allocate - SANE_Int size_to_realloc = ldev->read_buffer->image_line_no * + ldev->read_buffer->image_line_no += 1; + source_read_cursor = i + line_header_length; + block_pixel_data_length = ldev->read_buffer->linesize; + ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; + size_to_realloc = ldev->read_buffer->image_line_no * ldev->read_buffer->linesize * sizeof(SANE_Byte); - DBG (20, "size_to_realloc=%d\n", size_to_realloc); - ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; - SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); - if(alloc_result == NULL){ - // TODO allocation was not possible - DBG (20, "REALLOC failed\n"); - } - ldev->read_buffer->data = alloc_result; - // set write pointer - ldev->read_buffer->writeptr = - ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; - ldev->read_buffer->readptr = - ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; - // copy data - memcpy(ldev->read_buffer->writeptr, source + i + line_header_length, ldev->read_buffer->linesize); - ldev->read_buffer->write_byte_counter += ldev->read_buffer->linesize; - + bytes_read = block_pixel_data_length + line_header_length; } - - // last line was not full lets extract what is left + // next block cannot be read fully because source_size is too small + // (USB packet fragmentation) else{ - DBG (20, "next line doesnt fit %d < %ld sourcesize=%d i=%d\n", - source_size, i + line_header_length + ldev->read_buffer->linesize, - source_size, i); - SANE_Int bytes_left = source_size - i - line_header_length; - ldev->read_buffer->last_line_bytes_read = bytes_left; - DBG (20, " ldev->read_buffer->write_byte_counter=%d bytes_left=%d\n", - ldev->read_buffer->write_byte_counter, bytes_left); - // so copy what is left - SANE_Int size_to_realloc = ((ldev->read_buffer->image_line_no-1) * - ldev->read_buffer->linesize + bytes_left) * sizeof(SANE_Byte); - DBG (20, "size_to_realloc=%d\n", size_to_realloc); - SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); - if(alloc_result == NULL){ - // TODO allocation was not possible - DBG (20, "REALLOC failed\n"); - } - ldev->read_buffer->data = alloc_result; - // set write pointer - ldev->read_buffer->writeptr = - ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; - ldev->read_buffer->readptr = - ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; - // copy data - //DBG (20, "REALLOC bytes_left=%d\n", bytes_left); - memcpy(ldev->read_buffer->writeptr, source + i + line_header_length, bytes_left); - ldev->read_buffer->write_byte_counter += bytes_left; - + ldev->read_buffer->image_line_no += 1; + source_read_cursor = i + line_header_length; + block_pixel_data_length = source_size - i - line_header_length; + ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; + size_to_realloc = ((ldev->read_buffer->image_line_no-1) * + ldev->read_buffer->linesize + block_pixel_data_length) * sizeof(SANE_Byte); + bytes_read = block_pixel_data_length + line_header_length; } - // shift 'i' to next line - i += ldev->read_buffer->linesize + line_header_length; - }else{ - // this packet is begeging with the end of a line from the last usb packet - SANE_Int bytes_left = ldev->read_buffer->linesize - ldev->read_buffer->last_line_bytes_read; - DBG (20, "last line was splitted bytes_left=%d write_byte_counter=%d\n", - bytes_left, ldev->read_buffer->write_byte_counter); - // we filled our last line so tell it - ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; - - SANE_Int size_to_realloc = ldev->read_buffer->image_line_no * - ldev->read_buffer->linesize * sizeof(SANE_Byte); - DBG (20, "size_to_realloc=%d\n", size_to_realloc); - SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); - if(alloc_result == NULL){ - // TODO allocation was not possible - DBG (20, "REALLOC failed\n"); - } - ldev->read_buffer->data = alloc_result; - // reposition write/read pointer - ldev->read_buffer->writeptr = - ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; - ldev->read_buffer->readptr = - ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; - // copy data - memcpy(ldev->read_buffer->writeptr, source + i, bytes_left); - ldev->read_buffer->write_byte_counter += bytes_left; - // shift 'i' to next line - i += bytes_left; } - DBG (20, "i=%d image_line_no=%d\n", i, ldev->read_buffer->image_line_no); + // last line was not full lets extract what is left + // this is du to USB packet fragmentation + else{ + // the last line was not full so no increment + ldev->read_buffer->image_line_no += 0; + source_read_cursor = i; + block_pixel_data_length = ldev->read_buffer->linesize - + ldev->read_buffer->last_line_bytes_read; + // we completed the last line with missing bytes so new the line is full + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; + size_to_realloc = ldev->read_buffer->image_line_no * + ldev->read_buffer->linesize * sizeof(SANE_Byte); + bytes_read = block_pixel_data_length; + } + + DBG (20, "size_to_realloc=%d i=%d image_line_no=%d\n", + size_to_realloc, i, ldev->read_buffer->image_line_no); + // do realoc memory space for our buffer + SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); + if(alloc_result == NULL){ + // TODO allocation was not possible + DBG (20, "REALLOC failed\n"); + } + // point data to our new memary space + ldev->read_buffer->data = alloc_result; + // reposition writeptr and readptr to the correct memory adress + // to do that use write_byte_counter and read_byte_counter + ldev->read_buffer->writeptr = + ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; + ldev->read_buffer->readptr = + ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; + // copy new data + memcpy( + ldev->read_buffer->writeptr, + source + source_read_cursor, + block_pixel_data_length + ); + + // store how long is the buffer + ldev->read_buffer->write_byte_counter += block_pixel_data_length; + + i += bytes_read; } - + // read our buffer to fill the destination buffer // mulitple call so read may has been already started // length already read is stored in ldev->read_buffer->read_byte_counter @@ -315,94 +290,6 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, //ldev->read_buffer->readptr += bytes_to_read; *destination_length = bytes_to_read; - //DBG (20, "done destination_length=%d\n\n\n", bytes_to_read); - - - /* // fill the read buffer from source */ - /* ldev->read_buffer->size += (source_size - offset); */ - /* DBG (10, "size=%ld source_size=%d offset=%d\n", */ - /* ldev->read_buffer->size, source_size, offset); */ - /* SANE_Byte* alloc_result = realloc( */ - /* ldev->read_buffer->data, */ - /* ldev->read_buffer->size*sizeof(SANE_Byte)); */ - /* DBG (10, "ALLOC done\n"); */ - /* if(alloc_result==NULL){ */ - /* // TODO no more memory */ - /* } */ - /* ldev->read_buffer->data = alloc_result; */ - /* // point to the end of our new alloceted buffer minus the source_size - offset */ - /* ldev->read_buffer->writeptr = ldev->read_buffer->data + \ */ - /* ldev->read_buffer->size - (source_size - offset); */ - /* memcpy(ldev->read_buffer->writeptr, source + offset, source_size - offset); */ - - - - /* // if source doesnt start with 1b 53 02, then it is a continuation packet */ - /* if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ */ - /* segment_length = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; */ - /* offset = 9; */ - /* i = offset; */ - /* //ldev->bytes_remaining = segment_length; */ - /* end_offset = source_size % (segment_length+9); */ - /* } else { */ - /* DBG (20, "this is not a new line packet, continu current data line\n"); */ - /* //return; */ - /* } */ - /* DBG (10, "clean_and_copy_data segment_length:%d mode:%d source_size=%d destination_length=%d max_length=%d i=%d offset=%d bytes_remaining=%ld end_offset=%d\n", */ - /* segment_length, mode, source_size, *destination_length, max_length, i, offset, ldev->bytes_remaining, end_offset); */ - - /* while (i < source_size) */ - /* { */ - /* // some segments contains only 0xFF ignore them */ - /* //if (memcmp(source + offset, empty_data_packet, 4) == 0 ) */ - /* // break; */ - - /* if(i + segment_length <= max_length){ */ - /* memcpy (destination + bytes_written, source + i, segment_length); */ - /* }else{ */ - /* memcpy (destination + bytes_written, source + i, max_length - i); */ - /* } */ - /* DBG (20, " i=%d + segment_length=%d = %d\n", i, segment_length, i + segment_length); */ - /* overflow = i + segment_length - max_length; */ - /* // swap RGB <- BGR */ - /* if (mode == SANE_FRAME_RGB) */ - /* { */ - /* for(SANE_Int j=bytes_written; j < bytes_written + segment_length; */ - /* j += 3) */ - /* { */ - /* // DBG (20, " swapping RGB <- BGR j=%d\n", j); */ - /* tmp = destination[j]; */ - /* destination[j] = destination[j+2]; */ - /* destination[j+2] = tmp; */ - /* } */ - /* } */ - /* if(i + segment_length < max_length){ */ - /* bytes_written += segment_length; */ - /* }else{ */ - /* bytes_written += (max_length - i); */ - /* } */ - /* i += segment_length + offset; */ - /* k++; */ - /* DBG (20, " k=%d i=%d bytes_written=%d\n", k, i, bytes_written); */ - /* //DBG (20, " i:%d bytes_written:%d\n", i, bytes_written); */ - /* } */ - - - /* /\* DBG (20, " destination[] %d %d %d %d", *\/ */ - /* /\* destination[bytes_written-4], *\/ */ - /* /\* destination[bytes_written-3], *\/ */ - /* /\* destination[bytes_written-2], *\/ */ - /* /\* destination[bytes_written-1]); *\/ */ - /* DBG (20, " overflow=%d\n", overflow); */ - - /* if(overflow > 0){ */ - /* *destination_length = bytes_written; // - 40 */ - /* }else{ */ - /* *destination_length = bytes_written; */ - /* } */ - - /* //ldev->bytes_remaining -= bytes_written; */ - /* DBG (10, "bytes_written=%d\n", bytes_written); */ } SANE_Status From 6ee35589907d0068ede53fc2b60ac451788a9173 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sat, 25 Nov 2023 09:23:42 +0100 Subject: [PATCH 33/49] add color channel swap --- backend/lexmark_x2600.c | 63 +++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 4ebcdd5f3..d2f19b6d3 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -132,12 +132,8 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, return; } - Lexmark_Device * ldev = (Lexmark_Device * ) dev; - SANE_Int i = 0; - SANE_Int bytes_read = 0; // SANE_Int k = 0; // SANE_Int bytes_written = 0; - // SANE_Byte tmp = 0; // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segmentlng= 32) // BW 1b 53 02 00 41 00 00 00 00 | 64 | 41 -> 65 (segmentlng= 64) // COLOR 1b 53 02 00 c1 00 00 00 00 | 64 | c1 -> 193 (segmentlng= 192) @@ -191,6 +187,15 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // if this is the case the source[4] & source[5] contains how much data // can be read before onother header is reach (linebegin_data_packet) + Lexmark_Device * ldev = (Lexmark_Device * ) dev; + SANE_Int i = 0; + SANE_Int bytes_read = 0; + SANE_Byte tmp = 0; + SANE_Int source_read_cursor = 0; + SANE_Int block_pixel_data_length = 0; + SANE_Byte* alloc_result; + SANE_Int size_to_realloc = 0; + // does source start with linebegin_data_packet? if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ // extract the number of bytes we can read befor new header is reached @@ -204,10 +209,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, //return; } - SANE_Int source_read_cursor = 0; - SANE_Int block_pixel_data_length = 0; - SANE_Byte* alloc_result; - SANE_Int size_to_realloc = 0; + // loop over source buffer while(i < source_size){ // last line was full if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ @@ -282,14 +284,45 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // mulitple call so read may has been already started // length already read is stored in ldev->read_buffer->read_byte_counter DBG (20, "##### source read done now sending to destination\n"); - SANE_Int bytes_to_read = - ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; - //DBG (20, "memcopy bytes_to_read=%d\n", bytes_to_read); - memcpy (destination, ldev->read_buffer->readptr, bytes_to_read); - ldev->read_buffer->read_byte_counter += bytes_to_read; - //ldev->read_buffer->readptr += bytes_to_read; - *destination_length = bytes_to_read; + // we will copy image line by image line + // this avoid error on color channels swapping + SANE_Int available_bytes_to_read = + ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; + SANE_Int offset = 0; + //*destination_length = 0; + i = 0; + while(available_bytes_to_read >= ldev->read_buffer->linesize){ + DBG (20, " i=%d destination_length=%d\n", i, *destination_length); + offset = i*ldev->read_buffer->linesize; + + SANE_Byte * color_swarp_ptr = ldev->read_buffer->readptr + offset; + // we have to invert color channels + if (mode == SANE_FRAME_RGB){ + for(SANE_Int j=0; j < ldev->read_buffer->linesize;j += 3) + { + // DBG (20, " swapping RGB <- BGR j=%d\n", j); + tmp = *(color_swarp_ptr + j); + *(color_swarp_ptr + j) = *(color_swarp_ptr + j + 2); + *(color_swarp_ptr + j + 2) = tmp; + } + } + + + memcpy ( + destination + offset, + ldev->read_buffer->readptr + offset, + ldev->read_buffer->linesize + ); + ldev->read_buffer->read_byte_counter += ldev->read_buffer->linesize; + //ldev->read_buffer->readptr += bytes_to_read; + + available_bytes_to_read = + ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; + i++; + } + + *destination_length = ldev->read_buffer->linesize * i; } SANE_Status From fc8e03ef6938e2f4d4c0e672baac8c90d1b70676 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 26 Nov 2023 06:08:37 +0100 Subject: [PATCH 34/49] cleanup logs --- backend/lexmark_x2600.c | 88 +++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index d2f19b6d3..d00528d09 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -68,10 +68,6 @@ static SANE_Byte command_cancel2_block[] = { 0xaa, 0xbb, 0xcc, 0xdd}; static SANE_Int command_cancel_size = sizeof(command_cancel1_block); -static SANE_Byte unknnown_d_data_packet[] = { - 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00}; -static SANE_Int unknnown_d_data_packet_size = sizeof(unknnown_d_data_packet); - static SANE_Byte empty_line_data_packet[] = { 0x1b, 0x53, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; @@ -92,17 +88,26 @@ static SANE_Byte linebegin_data_packet[] = { static SANE_Int linebegin_data_packet_size = sizeof(linebegin_data_packet); static SANE_Byte unknnown_a_data_packet[] = { - 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; + 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00}; static SANE_Int unknnown_a_data_packet_size = sizeof(unknnown_a_data_packet); +static SANE_Byte unknnown_b_data_packet[] = { + 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; +static SANE_Int unknnown_b_data_packet_size = sizeof(unknnown_b_data_packet); + static SANE_Byte unknnown_c_data_packet[] = { - 0x1b, 0x53, 0x05, 0x00, 0x00, 0x00}; + 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00}; static SANE_Int unknnown_c_data_packet_size = sizeof(unknnown_c_data_packet); -static SANE_Byte unknnown_b_data_packet[] = { +static SANE_Byte unknnown_d_data_packet[] = { + 0x1b, 0x53, 0x05, 0x00, 0x00, 0x00}; +static SANE_Int unknnown_d_data_packet_size = sizeof(unknnown_d_data_packet); + +static SANE_Byte unknnown_e_data_packet[] = { 0xa5, 0x00, 0x06, 0x10, 0x01, 0xaa, 0xbb, 0xcc, 0xdd}; -static SANE_Int unknnown_b_data_packet_size = sizeof(unknnown_b_data_packet); +static SANE_Int unknnown_e_data_packet_size = sizeof(unknnown_e_data_packet); + static SANE_Int line_header_length = 9; @@ -131,6 +136,9 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, if (memcmp(unknnown_d_data_packet, source, unknnown_d_data_packet_size) == 0){ return; } + if (memcmp(unknnown_e_data_packet, source, unknnown_e_data_packet_size) == 0){ + return; + } // SANE_Int k = 0; // SANE_Int bytes_written = 0; @@ -195,7 +203,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Int block_pixel_data_length = 0; SANE_Byte* alloc_result; SANE_Int size_to_realloc = 0; - + // does source start with linebegin_data_packet? if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ // extract the number of bytes we can read befor new header is reached @@ -248,7 +256,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, size_to_realloc = ldev->read_buffer->image_line_no * ldev->read_buffer->linesize * sizeof(SANE_Byte); bytes_read = block_pixel_data_length; - } + } DBG (20, "size_to_realloc=%d i=%d image_line_no=%d\n", size_to_realloc, i, ldev->read_buffer->image_line_no); @@ -272,14 +280,14 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, source + source_read_cursor, block_pixel_data_length ); - + // store how long is the buffer ldev->read_buffer->write_byte_counter += block_pixel_data_length; i += bytes_read; } - + // read our buffer to fill the destination buffer // mulitple call so read may has been already started // length already read is stored in ldev->read_buffer->read_byte_counter @@ -308,7 +316,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, } } - + memcpy ( destination + offset, ldev->read_buffer->readptr + offset, @@ -316,13 +324,13 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, ); ldev->read_buffer->read_byte_counter += ldev->read_buffer->linesize; //ldev->read_buffer->readptr += bytes_to_read; - + available_bytes_to_read = ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; i++; } - *destination_length = ldev->read_buffer->linesize * i; + *destination_length = ldev->read_buffer->linesize * i; } SANE_Status @@ -410,7 +418,7 @@ init_options (Lexmark_Device * dev) od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = MAX_OPTION_STRING_SIZE; - od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; + od->cap = SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = mode_list; dev->val[OPT_MODE].s = malloc (od->size); @@ -451,6 +459,7 @@ init_options (Lexmark_Device * dev) od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->size = 0; od->constraint_type = SANE_CONSTRAINT_NONE; + // /* top-left x */ od = &(dev->opt[OPT_TL_X]); @@ -489,7 +498,7 @@ init_options (Lexmark_Device * dev) od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &x_range; - dev->val[OPT_BR_X].w = 1699; + dev->val[OPT_BR_X].w = 1654; /* bottom-right y */ od = &(dev->opt[OPT_BR_Y]); @@ -502,7 +511,7 @@ init_options (Lexmark_Device * dev) od->unit = SANE_UNIT_PIXEL; od->constraint_type = SANE_CONSTRAINT_RANGE; od->constraint.range = &y_range; - dev->val[OPT_BR_Y].w = 2337; + dev->val[OPT_BR_Y].w = 2339; return SANE_STATUS_GOOD; } @@ -514,7 +523,7 @@ attach_one (SANE_String_Const devname) { Lexmark_Device *lexmark_device; - DBG (2, "attachLexmark: devname=%s\n", devname); + DBG (2, "attach_one: attachLexmark: devname=%s\n", devname); for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) @@ -565,7 +574,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) DBG_INIT (); DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); - DBG (1, "sane_init: SANE lexmark_x2600 backend version %d.%d.%d from %s\n", + DBG (1, " SANE lexmark_x2600 backend version %d.%d.%d from %s\n", SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); if (version_code) @@ -576,7 +585,7 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); if (!fp) { - DBG (2, "No config no prob...(%s)\n", LEXMARK_X2600_CONFIG_FILE); + DBG (2, " No config no prob...(%s)\n", LEXMARK_X2600_CONFIG_FILE); return SANE_STATUS_GOOD; } while (sanei_config_read (config_line, sizeof (config_line), fp)) @@ -589,11 +598,10 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) if (*lp == 0) continue; - DBG (4, "attach_matching_devices(%s)\n", config_line); + DBG (4, " attach_matching_devices(%s)\n", config_line); sanei_usb_attach_matching_devices (config_line, attach_one); } - DBG (4, "finished reading configure file\n"); fclose (fp); initialized = SANE_TRUE; return SANE_STATUS_GOOD; @@ -621,7 +629,7 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) lexmark_device = first_device; while (lexmark_device != NULL) { - DBG (2, "sane_get_devices: lexmark_device->missing:%d\n", + DBG (2, " lexmark_device->missing:%d\n", lexmark_device->missing); if (lexmark_device->missing == SANE_FALSE) { @@ -652,7 +660,7 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) { - DBG (10, "sane_open: devname from list: %s\n", + DBG (10, " devname from list: %s\n", lexmark_device->sane.name); if (strcmp (devicename, "") == 0 || strcmp (devicename, "lexmark") == 0 @@ -666,19 +674,19 @@ sane_open (SANE_String_Const devicename, SANE_Handle * handle) if (status != SANE_STATUS_GOOD) return status; - DBG(2, "sane_open: device `%s' opening devnum: '%d'\n", + DBG(2, " device `%s' opening devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); status = sanei_usb_open (lexmark_device->sane.name, &(lexmark_device->devnum)); if (status != SANE_STATUS_GOOD) { - DBG (1, "sane_open: couldn't open device `%s': %s\n", + DBG (1, " couldn't open device `%s': %s\n", lexmark_device->sane.name, sane_strstatus (status)); return status; } else { - DBG (2, "sane_open: device `%s' successfully opened devnum: '%d'\n", + DBG (2, " device `%s' successfully opened devnum: '%d'\n", lexmark_device->sane.name, lexmark_device->devnum); } @@ -709,7 +717,7 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) if (lexmark_device->opt[option].name) { - DBG (2, "sane_get_option_descriptor: name=%s\n", + DBG (2, " name=%s\n", lexmark_device->opt[option].name); } @@ -763,7 +771,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, info); if (status != SANE_STATUS_GOOD) { - DBG (2, "SANE_CONTROL_OPTION: Bad value for range\n"); + DBG (2, " SANE_CONTROL_OPTION: Bad value for range\n"); return SANE_STATUS_INVAL; } } @@ -775,7 +783,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, case OPT_TL_Y: case OPT_BR_X: case OPT_BR_Y: - DBG (2, "Option value set to %d (%s)\n", *(SANE_Word *) value, + DBG (2, " Option value set to %d (%s)\n", *(SANE_Word *) value, lexmark_device->opt[option].name); lexmark_device->val[option].w = *(SANE_Word *) value; if (lexmark_device->val[OPT_TL_X].w > @@ -822,7 +830,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) value = lexmark_device->val[option].w; - DBG (2, "Option value = %d (%s)\n", *(SANE_Word *) value, + DBG (2, " Option value = %d (%s)\n", *(SANE_Word *) value, lexmark_device->opt[option].name); break; case OPT_MODE: @@ -883,15 +891,17 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) device_params->last_frame = SANE_TRUE; device_params->lines = -1;//lexmark_device->val[OPT_BR_Y].w; - DBG (2, "sane_get_parameters: device_params->pixels_per_line=%d\n", + DBG (2, " device_params->pixels_per_line=%d\n", device_params->pixels_per_line); - DBG (2, "sane_get_parameters: device_params->bytes_per_line=%d\n", + DBG (2, " device_params->bytes_per_line=%d\n", device_params->bytes_per_line); - DBG (2, "sane_get_parameters: device_params->format=%d\n", + DBG (2, " device_params->depth=%d\n", + device_params->depth); + DBG (2, " device_params->format=%d\n", device_params->format); - DBG (2, " SANE_FRAME_GRAY: %d\n", + DBG (2, " SANE_FRAME_GRAY: %d\n", SANE_FRAME_GRAY); - DBG (2, " SANE_FRAME_RGB: %d\n", + DBG (2, " SANE_FRAME_RGB: %d\n", SANE_FRAME_RGB); if (params != 0) @@ -995,8 +1005,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ Error in usb_write_then_read, cannot read devnum=%d\n", - lexmark_device->devnum); + DBG (1, "USB READ Error in usb_write_then_read, cannot read devnum=%d status=%d\n", + lexmark_device->devnum, status); return status; } From 1513839238857711f09effacfc090acfda300b2a Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 26 Nov 2023 06:43:53 +0100 Subject: [PATCH 35/49] whitespace cleanup --- backend/lexmark_x2600.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index d00528d09..31729ea27 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -108,6 +108,10 @@ static SANE_Byte unknnown_e_data_packet[] = { 0xdd}; static SANE_Int unknnown_e_data_packet_size = sizeof(unknnown_e_data_packet); +static SANE_Byte not_ready_data_packet[] = { + 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x84, 0x00}; +static SANE_Int not_ready_data_packet = sizeof(unknnown_c_data_packet); + static SANE_Int line_header_length = 9; @@ -217,6 +221,12 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, //return; } + if(ldev->read_buffer->linesize == 0){ + DBG (20, "linesize=0 something went wrong, lets ignore that USB packet\n"); + return SANE_STATUS_GOOD; + } + + // loop over source buffer while(i < source_size){ // last line was full @@ -301,7 +311,8 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, //*destination_length = 0; i = 0; while(available_bytes_to_read >= ldev->read_buffer->linesize){ - DBG (20, " i=%d destination_length=%d\n", i, *destination_length); + DBG (20, " i=%d destination_length=%d linesize=%ld\n", + i, *destination_length, ldev->read_buffer->linesize); offset = i*ldev->read_buffer->linesize; SANE_Byte * color_swarp_ptr = ldev->read_buffer->readptr + offset; @@ -1005,7 +1016,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ Error in usb_write_then_read, cannot read devnum=%d status=%d\n", + DBG (1, "USB READ Error in sanei_usb_read_bulk, cannot read devnum=%d status=%d\n", lexmark_device->devnum, status); return status; } From d022fa9c1b6b5e3467a0bcd092e45cd4a15b60cf Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Mon, 27 Nov 2023 05:51:46 +0100 Subject: [PATCH 36/49] use buffers --- backend/lexmark_x2600.c | 391 +++++++++++++++++++++++----------------- backend/lexmark_x2600.h | 10 + 2 files changed, 236 insertions(+), 165 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 31729ea27..cc9807905 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -3,16 +3,18 @@ #define BUILD 1 #define LEXMARK_X2600_CONFIG_FILE "lexmark_x2600.conf" #define MAX_OPTION_STRING_SIZE 255 - +static SANE_Int transfer_buffer_size = 32768; static Lexmark_Device *first_device = 0; static SANE_Int num_devices = 0; static const SANE_Device **devlist = 0; static SANE_Bool initialized = SANE_FALSE; +// first value is the size of the wordlist! static SANE_Int dpi_list[] = { - 5, 75, 100, 200, 300, 600 + 4, 100, 200, 300, 600 }; +static SANE_Int dpi_list_size = sizeof(dpi_list) / sizeof(dpi_list[0]); static SANE_String_Const mode_list[] = { SANE_VALUE_SCAN_MODE_COLOR, @@ -108,9 +110,9 @@ static SANE_Byte unknnown_e_data_packet[] = { 0xdd}; static SANE_Int unknnown_e_data_packet_size = sizeof(unknnown_e_data_packet); -static SANE_Byte not_ready_data_packet[] = { - 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x84, 0x00}; -static SANE_Int not_ready_data_packet = sizeof(unknnown_c_data_packet); +/* static SANE_Byte not_ready_data_packet[] = { */ +/* 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x84, 0x00}; */ +/* static SANE_Int not_ready_data_packet_size = sizeof(not_ready_data_packet); */ static SANE_Int line_header_length = 9; @@ -123,27 +125,8 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length, SANE_Int mode, SANE_Int max_length, SANE_Handle dev) { - + DBG (10, "clean_and_copy_data\n"); // if source doesnt start with 1b 53 02, then it is a continuation packet - if (memcmp(empty_line_data_packet, source, empty_line_data_packet_size) == 0){ - return; - } - if (memcmp(unknnown_a_data_packet, source, unknnown_a_data_packet_size) == 0){ - return; - } - if (memcmp(unknnown_b_data_packet, source, unknnown_b_data_packet_size) == 0){ - return; - } - if (memcmp(unknnown_c_data_packet, source, unknnown_c_data_packet_size) == 0){ - return; - } - if (memcmp(unknnown_d_data_packet, source, unknnown_d_data_packet_size) == 0){ - return; - } - if (memcmp(unknnown_e_data_packet, source, unknnown_e_data_packet_size) == 0){ - return; - } - // SANE_Int k = 0; // SANE_Int bytes_written = 0; // BW 1b 53 02 00 21 00 00 00 00 | 32 | 21 -> 33 (segmentlng= 32) @@ -160,34 +143,6 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, /* if(segment_length > source_size - 9) */ /* segment_length = source_size - 9; */ - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[8], source[9], source[10], source[11], source[12], source[13], source[14], source[15]); - int debug_offset = 4092; - if(source_size > debug_offset){ - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[source_size-16-debug_offset], - source[source_size-15-debug_offset], - source[source_size-14-debug_offset], - source[source_size-13-debug_offset], - source[source_size-12-debug_offset], - source[source_size-11-debug_offset], - source[source_size-10-debug_offset], - source[source_size-9]-debug_offset); - DBG (10, "source = %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", - source[source_size-8-debug_offset], - source[source_size-7-debug_offset], - source[source_size-6-debug_offset], - source[source_size-5-debug_offset], - source[source_size-4-debug_offset], - source[source_size-3-debug_offset], - source[source_size-2-debug_offset], - source[source_size-1-debug_offset]); - } - - DBG (10, "\n"); - // the scanner sends series of 8 lines function param source // every lines has prefix see linebegin_data_packet // the source parameter as a limited length :function param source_size @@ -206,6 +161,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Int source_read_cursor = 0; SANE_Int block_pixel_data_length = 0; SANE_Byte* alloc_result; + SANE_Byte* pixel[3]; SANE_Int size_to_realloc = 0; // does source start with linebegin_data_packet? @@ -214,16 +170,16 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // store it in the device in case of continuation packet ldev->read_buffer->linesize = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; - DBG (20, "this is the begining of a line linesize=%ld\n", + DBG (10, " this is the begining of a line linesize=%ld\n", ldev->read_buffer->linesize); } else { - DBG (20, "this is not a new line packet, continue to fill the read buffer\n"); + DBG (10, " this is not a new line packet, continue to fill the read buffer\n"); //return; } if(ldev->read_buffer->linesize == 0){ - DBG (20, "linesize=0 something went wrong, lets ignore that USB packet\n"); - return SANE_STATUS_GOOD; + DBG (10, " linesize=0 something went wrong, lets ignore that USB packet\n"); + return; } @@ -268,13 +224,13 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, bytes_read = block_pixel_data_length; } - DBG (20, "size_to_realloc=%d i=%d image_line_no=%d\n", + DBG (20, " size_to_realloc=%d i=%d image_line_no=%d\n", size_to_realloc, i, ldev->read_buffer->image_line_no); // do realoc memory space for our buffer SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); if(alloc_result == NULL){ // TODO allocation was not possible - DBG (20, "REALLOC failed\n"); + DBG (20, " REALLOC failed\n"); } // point data to our new memary space ldev->read_buffer->data = alloc_result; @@ -301,47 +257,60 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // read our buffer to fill the destination buffer // mulitple call so read may has been already started // length already read is stored in ldev->read_buffer->read_byte_counter - DBG (20, "##### source read done now sending to destination\n"); - // we will copy image line by image line - // this avoid error on color channels swapping SANE_Int available_bytes_to_read = ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; SANE_Int offset = 0; - //*destination_length = 0; - i = 0; - while(available_bytes_to_read >= ldev->read_buffer->linesize){ - DBG (20, " i=%d destination_length=%d linesize=%ld\n", - i, *destination_length, ldev->read_buffer->linesize); - offset = i*ldev->read_buffer->linesize; - SANE_Byte * color_swarp_ptr = ldev->read_buffer->readptr + offset; + DBG (20, " source read done now sending to destination \n"); + + // we will copy image data 3 bytes by 3 bytes if color mod to allow color swap + // this avoid error on color channels swapping + if (mode == SANE_FRAME_RGB){ + + // get max chunk + SANE_Int data_chunk_size = max_length; + if(data_chunk_size > available_bytes_to_read){ + data_chunk_size = available_bytes_to_read; + } + data_chunk_size = data_chunk_size / 3; + data_chunk_size = data_chunk_size * 3; + // we have to invert color channels - if (mode == SANE_FRAME_RGB){ - for(SANE_Int j=0; j < ldev->read_buffer->linesize;j += 3) - { - // DBG (20, " swapping RGB <- BGR j=%d\n", j); - tmp = *(color_swarp_ptr + j); - *(color_swarp_ptr + j) = *(color_swarp_ptr + j + 2); - *(color_swarp_ptr + j + 2) = tmp; - } + SANE_Byte * color_swarp_ptr = ldev->read_buffer->readptr; + for(SANE_Int j=0; j < data_chunk_size;j += 3){ + // DBG (20, " swapping RGB <- BGR j=%d\n", j); + tmp = *(color_swarp_ptr + j); + *(color_swarp_ptr + j) = *(color_swarp_ptr + j + 2); + *(color_swarp_ptr + j + 2) = tmp; } + memcpy (destination, + ldev->read_buffer->readptr, + data_chunk_size); + ldev->read_buffer->read_byte_counter += data_chunk_size; + *destination_length = data_chunk_size; + + } + // gray mode copy until max_length + else{ + + SANE_Int data_chunk_size = max_length; + if(data_chunk_size > available_bytes_to_read){ + data_chunk_size = available_bytes_to_read; + } memcpy ( - destination + offset, - ldev->read_buffer->readptr + offset, - ldev->read_buffer->linesize + destination, + ldev->read_buffer->readptr, + data_chunk_size ); - ldev->read_buffer->read_byte_counter += ldev->read_buffer->linesize; - //ldev->read_buffer->readptr += bytes_to_read; + ldev->read_buffer->read_byte_counter += data_chunk_size;; + *destination_length = data_chunk_size; - available_bytes_to_read = - ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; - i++; } - *destination_length = ldev->read_buffer->linesize * i; + DBG (20, " done destination_length=%d\n", *destination_length); } SANE_Status @@ -353,7 +322,20 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) DBG (10, "usb_write_then_read: %d\n", dev->devnum); sanei_usb_set_endpoint(dev->devnum, USB_DIR_OUT|USB_ENDPOINT_TYPE_BULK, 0x02); + DBG (10, " endpoint set: %d\n", dev->devnum); + + /* status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); */ + /* DBG (10, " readdone: %d\n", dev->devnum); */ + /* if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) */ + /* { */ + /* DBG (1, "USB READ IO Error in usb_write_then_read, fail devnum=%d\n", */ + /* dev->devnum); */ + /* return status; */ + /* } */ + + DBG (10, " attempting to write...: %d\n", dev->devnum); status = sanei_usb_write_bulk (dev->devnum, cmd, &cmd_size); + DBG (10, " writedone: %d\n", dev->devnum); if (status != SANE_STATUS_GOOD) { DBG (1, "USB WRITE IO Error in usb_write_then_read, launch fail: %d\n", @@ -361,13 +343,18 @@ usb_write_then_read (Lexmark_Device * dev, SANE_Byte * cmd, size_t cmd_size) return status; } + debug_packet(cmd, cmd_size, WRITE); + + DBG (10, " attempting to read...: %d\n", dev->devnum); status = sanei_usb_read_bulk (dev->devnum, buf, &buf_size); + DBG (10, " readdone: %d\n", dev->devnum); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { DBG (1, "USB READ IO Error in usb_write_then_read, fail devnum=%d\n", dev->devnum); return status; } + debug_packet(buf, buf_size, READ); return SANE_STATUS_GOOD; } @@ -429,7 +416,7 @@ init_options (Lexmark_Device * dev) od->type = SANE_TYPE_STRING; od->unit = SANE_UNIT_NONE; od->size = MAX_OPTION_STRING_SIZE; - od->cap = SANE_CAP_SOFT_SELECT; + od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_STRING_LIST; od->constraint.string_list = mode_list; dev->val[OPT_MODE].s = malloc (od->size); @@ -444,7 +431,7 @@ init_options (Lexmark_Device * dev) od->desc = SANE_DESC_SCAN_RESOLUTION; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_DPI; - od->size = sizeof (SANE_Word); + od->size = sizeof (SANE_Int); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; od->constraint.word_list = dpi_list; @@ -556,6 +543,10 @@ attach_one (SANE_String_Const devname) lexmark_device->sane.model = "X2600 series"; lexmark_device->sane.type = "flat bed"; + /* init transfer_buffer */ + lexmark_device->transfer_buffer = malloc (transfer_buffer_size); + + /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = malloc (sizeof (Read_Buffer)); lexmark_device->read_buffer->data = NULL; @@ -709,8 +700,8 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) { Lexmark_Device *lexmark_device; - DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", - (void *) handle, option); + //DBG (2, "sane_get_option_descriptor: handle=%p, option = %d\n", + // (void *) handle, option); /* Check for valid option number */ if ((option < 0) || (option >= NUM_OPTIONS)) @@ -728,8 +719,8 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) if (lexmark_device->opt[option].name) { - DBG (2, " name=%s\n", - lexmark_device->opt[option].name); + //DBG (2, " name=%s\n", + // lexmark_device->opt[option].name); } return &(lexmark_device->opt[option]); @@ -747,49 +738,51 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, (void *) handle, option, action, (void *) value, (void *) info); for (lexmark_device = first_device; lexmark_device; - lexmark_device = lexmark_device->next) - { - if (lexmark_device == handle) - break; - } + lexmark_device = lexmark_device->next){ + if (lexmark_device == handle) + break; + } if (value == NULL) return SANE_STATUS_INVAL; - switch (action) - { - case SANE_ACTION_SET_VALUE: - if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)) - { - return SANE_STATUS_INVAL; - } - /* Make sure boolean values are only TRUE or FALSE */ - if (lexmark_device->opt[option].type == SANE_TYPE_BOOL) - { + switch (action){ + case SANE_ACTION_SET_VALUE: + if (!SANE_OPTION_IS_SETTABLE (lexmark_device->opt[option].cap)){ + return SANE_STATUS_INVAL; + } + /* Make sure boolean values are only TRUE or FALSE */ + if (lexmark_device->opt[option].type == SANE_TYPE_BOOL){ if (! ((*(SANE_Bool *) value == SANE_FALSE) || (*(SANE_Bool *) value == SANE_TRUE))) return SANE_STATUS_INVAL; } - /* Check range constraints */ - if (lexmark_device->opt[option].constraint_type == - SANE_CONSTRAINT_RANGE) - { + /* Check range constraints */ + if (lexmark_device->opt[option].constraint_type == + SANE_CONSTRAINT_RANGE){ status = sanei_constrain_value (&(lexmark_device->opt[option]), value, - info); - if (status != SANE_STATUS_GOOD) - { - DBG (2, " SANE_CONTROL_OPTION: Bad value for range\n"); - return SANE_STATUS_INVAL; - } + info); + if (status != SANE_STATUS_GOOD){ + DBG (2, " SANE_CONTROL_OPTION: Bad value for range\n"); + return SANE_STATUS_INVAL; + } } - switch (option) - { + switch (option){ case OPT_NUM_OPTS: case OPT_RESOLUTION: + SANE_Int res_selected = *(SANE_Int *) value; + // first value is the size of the wordlist! + for(int i=1; ival[option].w = *(SANE_Word *) value; + } + } + break; case OPT_TL_X: case OPT_TL_Y: case OPT_BR_X: @@ -798,25 +791,23 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, lexmark_device->opt[option].name); lexmark_device->val[option].w = *(SANE_Word *) value; if (lexmark_device->val[OPT_TL_X].w > - lexmark_device->val[OPT_BR_X].w) - { - w = lexmark_device->val[OPT_TL_X].w; - lexmark_device->val[OPT_TL_X].w = - lexmark_device->val[OPT_BR_X].w; - lexmark_device->val[OPT_BR_X].w = w; - if (info) - *info |= SANE_INFO_RELOAD_PARAMS; - } + lexmark_device->val[OPT_BR_X].w){ + w = lexmark_device->val[OPT_TL_X].w; + lexmark_device->val[OPT_TL_X].w = + lexmark_device->val[OPT_BR_X].w; + lexmark_device->val[OPT_BR_X].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } if (lexmark_device->val[OPT_TL_Y].w > - lexmark_device->val[OPT_BR_Y].w) - { - w = lexmark_device->val[OPT_TL_Y].w; - lexmark_device->val[OPT_TL_Y].w = - lexmark_device->val[OPT_BR_Y].w; - lexmark_device->val[OPT_BR_Y].w = w; - if (info) - *info |= SANE_INFO_RELOAD_PARAMS; - } + lexmark_device->val[OPT_BR_Y].w){ + w = lexmark_device->val[OPT_TL_Y].w; + lexmark_device->val[OPT_TL_Y].w = + lexmark_device->val[OPT_BR_Y].w; + lexmark_device->val[OPT_BR_Y].w = w; + if (info) + *info |= SANE_INFO_RELOAD_PARAMS; + } break; case OPT_MODE: strcpy (lexmark_device->val[option].s, value); @@ -825,14 +816,13 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, return SANE_STATUS_GOOD; } - if (info != NULL) - *info |= SANE_INFO_RELOAD_PARAMS; - break; - case SANE_ACTION_GET_VALUE: + if (info != NULL) + *info |= SANE_INFO_RELOAD_PARAMS; - switch (option) - { + break; + case SANE_ACTION_GET_VALUE: + switch (option){ case OPT_NUM_OPTS: case OPT_RESOLUTION: case OPT_PREVIEW: @@ -841,18 +831,18 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, case OPT_BR_X: case OPT_BR_Y: *(SANE_Word *) value = lexmark_device->val[option].w; - DBG (2, " Option value = %d (%s)\n", *(SANE_Word *) value, - lexmark_device->opt[option].name); + //DBG (2, " Option value = %d (%s)\n", *(SANE_Word *) value, + // lexmark_device->opt[option].name); break; case OPT_MODE: strcpy (value, lexmark_device->val[option].s); break; } - break; + break; - default: - return SANE_STATUS_INVAL; - } + default: + return SANE_STATUS_INVAL; + } return SANE_STATUS_GOOD; } @@ -935,7 +925,7 @@ sane_start (SANE_Handle handle) SANE_Byte * cmd = (SANE_Byte *) malloc (command_with_params_block_size * sizeof (SANE_Byte));; - DBG (2, "sane_start: handle=%p\n", (void *) handle); + DBG (2, "sane_start: handle=%p initialized=%d\n", (void *) handle, initialized); if (!initialized) return SANE_STATUS_INVAL; @@ -973,17 +963,52 @@ sane_start (SANE_Handle handle) return SANE_STATUS_GOOD; } + +void debug_packet(const SANE_Byte * source, SANE_Int source_size, Debug_Packet dp){ + if(dp == READ){ + DBG (10, "source READ <<< size=%d\n", source_size); + }else{ + DBG (10, "source WRITE >>> size=%d\n", source_size); + } + + DBG (10, " %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[0], source[1], source[2], source[3], source[4], source[5], source[6], source[7]); + DBG (10, " %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[8], source[9], source[10], source[11], source[12], source[13], source[14], source[15]); + int debug_offset = 4092; + if(source_size > debug_offset){ + DBG (10, " %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[source_size-16-debug_offset], + source[source_size-15-debug_offset], + source[source_size-14-debug_offset], + source[source_size-13-debug_offset], + source[source_size-12-debug_offset], + source[source_size-11-debug_offset], + source[source_size-10-debug_offset], + source[source_size-9]-debug_offset); + DBG (10, " %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", + source[source_size-8-debug_offset], + source[source_size-7-debug_offset], + source[source_size-6-debug_offset], + source[source_size-5-debug_offset], + source[source_size-4-debug_offset], + source[source_size-3-debug_offset], + source[source_size-2-debug_offset], + source[source_size-1-debug_offset]); + } + return; +} + SANE_Status sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length, SANE_Int * length) { Lexmark_Device * lexmark_device; SANE_Status status; - size_t size = max_length; - SANE_Byte buf[size]; - - DBG (1, "sane_read: handle=%p, data=%p, max_length=%d\n", - (void *) handle, (void *) data, max_length); + size_t size = transfer_buffer_size; + //SANE_Byte buf[size]; + DBG (1, "\n"); + DBG (1, "sane_read max_length=%d:\n", max_length); for (lexmark_device = first_device; lexmark_device; lexmark_device = lexmark_device->next) @@ -993,6 +1018,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, } if (lexmark_device->device_cancelled == SANE_TRUE) { + DBG (10, "device_cancelled=True \n"); usb_write_then_read(lexmark_device, command_cancel1_block, command_cancel_size); usb_write_then_read(lexmark_device, command_cancel2_block, @@ -1002,41 +1028,75 @@ sane_read (SANE_Handle handle, SANE_Byte * data, usb_write_then_read(lexmark_device, command_cancel2_block, command_cancel_size); // to empty buffers - status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); DBG (10, "USB READ \n"); - status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); DBG (10, "USB READ \n"); - status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); DBG (10, "USB READ \n"); //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); //DBG (10, "USB READ \n"); return SANE_STATUS_CANCELLED;//SANE_STATUS_GOOD; //; } - status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); + DBG (1, " usb_read\n"); + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) { - DBG (1, "USB READ Error in sanei_usb_read_bulk, cannot read devnum=%d status=%d\n", - lexmark_device->devnum, status); + DBG (1, " USB READ Error in sanei_usb_read_bulk, cannot read devnum=%d status=%d size=%ld\n", + lexmark_device->devnum, status, size); return status; } + DBG (1, " usb_read done size=%ld\n", size); + debug_packet(lexmark_device->transfer_buffer, size, READ); // is last data packet ? - if (memcmp(last_data_packet, buf, last_data_packet_size) == 0) + if (memcmp(last_data_packet, lexmark_device->transfer_buffer, last_data_packet_size) == 0) { length = 0; return SANE_STATUS_EOF; } // cancel packet received? - if (memcmp(cancel_packet, buf, cancel_packet_size) == 0) + if (memcmp(cancel_packet, lexmark_device->transfer_buffer, cancel_packet_size) == 0) { length = 0; return SANE_STATUS_CANCELLED; } - clean_and_copy_data(buf, size, data, length, lexmark_device->params.format, - max_length, handle); + + if (memcmp(empty_line_data_packet, lexmark_device->transfer_buffer, empty_line_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + if (memcmp(unknnown_a_data_packet, lexmark_device->transfer_buffer, unknnown_a_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + if (memcmp(unknnown_b_data_packet, lexmark_device->transfer_buffer, unknnown_b_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + if (memcmp(unknnown_c_data_packet, lexmark_device->transfer_buffer, unknnown_c_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + if (memcmp(unknnown_d_data_packet, lexmark_device->transfer_buffer, unknnown_d_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + if (memcmp(unknnown_e_data_packet, lexmark_device->transfer_buffer, unknnown_e_data_packet_size) == 0){ + return SANE_STATUS_GOOD; + } + + clean_and_copy_data( + lexmark_device->transfer_buffer, + size, + data, + length, + lexmark_device->params.format, + max_length, + handle); return SANE_STATUS_GOOD; } @@ -1075,6 +1135,7 @@ sane_cancel (SANE_Handle handle) if (lexmark_device == handle) break; } + sanei_usb_reset (lexmark_device->devnum); lexmark_device->device_cancelled = SANE_TRUE; } diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index 223a44e66..ea5f2570d 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -69,6 +69,14 @@ typedef enum } Lexmark_Options; +typedef enum +{ + READ = 0, + WRITE = 1, +} +Debug_Packet; + + typedef struct Lexmark_Device { struct Lexmark_Device *next; @@ -97,4 +105,6 @@ typedef struct Lexmark_Device Lexmark_Device; +void debug_packet(const SANE_Byte * source, SANE_Int source_size, Debug_Packet dp); + #endif /* LEXMARK_X2600_H */ From c9e8d812df91a06834c402edf84f682d3e5da118 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Wed, 29 Nov 2023 06:10:05 +0100 Subject: [PATCH 37/49] reposition readPtr correctly --- backend/lexmark_x2600.c | 238 ++++++++++++++++++++++------------------ 1 file changed, 129 insertions(+), 109 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index cc9807905..4b49cc1f2 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -120,7 +120,7 @@ static SANE_Int line_header_length = 9; //static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; -void +SANE_Status clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte * destination, SANE_Int * destination_length, SANE_Int mode, SANE_Int max_length, SANE_Handle dev) @@ -164,95 +164,101 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte* pixel[3]; SANE_Int size_to_realloc = 0; - // does source start with linebegin_data_packet? - if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ - // extract the number of bytes we can read befor new header is reached - // store it in the device in case of continuation packet - ldev->read_buffer->linesize = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; - ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; - DBG (10, " this is the begining of a line linesize=%ld\n", - ldev->read_buffer->linesize); - } else { - DBG (10, " this is not a new line packet, continue to fill the read buffer\n"); - //return; - } - if(ldev->read_buffer->linesize == 0){ - DBG (10, " linesize=0 something went wrong, lets ignore that USB packet\n"); - return; - } + if(!ldev->eof){ + + // does source start with linebegin_data_packet? + if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ + // extract the number of bytes we can read befor new header is reached + // store it in the device in case of continuation packet + ldev->read_buffer->linesize = (source[4] + ((source[5] << 8) & 0xFF00)) - 1; + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; + DBG (10, " this is the begining of a line linesize=%ld\n", + ldev->read_buffer->linesize); + } else { + DBG (10, " this is not a new line packet, continue to fill the read buffer\n"); + //return; + } + + if(ldev->read_buffer->linesize == 0){ + DBG (10, " linesize=0 something went wrong, lets ignore that USB packet\n"); + return SANE_STATUS_CANCELLED; + } - // loop over source buffer - while(i < source_size){ - // last line was full - if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ - // if next block fit in the source - if(i + line_header_length + ldev->read_buffer->linesize <= source_size){ - ldev->read_buffer->image_line_no += 1; - source_read_cursor = i + line_header_length; - block_pixel_data_length = ldev->read_buffer->linesize; - ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; + // loop over source buffer + while(i < source_size){ + // last line was full + if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ + // if next block fit in the source + if(i + line_header_length + ldev->read_buffer->linesize <= source_size){ + ldev->read_buffer->image_line_no += 1; + source_read_cursor = i + line_header_length; + block_pixel_data_length = ldev->read_buffer->linesize; + ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; + size_to_realloc = ldev->read_buffer->image_line_no * + ldev->read_buffer->linesize * sizeof(SANE_Byte); + bytes_read = block_pixel_data_length + line_header_length; + } + // next block cannot be read fully because source_size is too small + // (USB packet fragmentation) + else{ + ldev->read_buffer->image_line_no += 1; + source_read_cursor = i + line_header_length; + block_pixel_data_length = source_size - i - line_header_length; + ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; + size_to_realloc = ((ldev->read_buffer->image_line_no-1) * + ldev->read_buffer->linesize + block_pixel_data_length) * sizeof(SANE_Byte); + bytes_read = block_pixel_data_length + line_header_length; + } + } + // last line was not full lets extract what is left + // this is du to USB packet fragmentation + else{ + // the last line was not full so no increment + ldev->read_buffer->image_line_no += 0; + source_read_cursor = i; + block_pixel_data_length = ldev->read_buffer->linesize - + ldev->read_buffer->last_line_bytes_read; + // we completed the last line with missing bytes so new the line is full + ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; size_to_realloc = ldev->read_buffer->image_line_no * ldev->read_buffer->linesize * sizeof(SANE_Byte); - bytes_read = block_pixel_data_length + line_header_length; + bytes_read = block_pixel_data_length; } - // next block cannot be read fully because source_size is too small - // (USB packet fragmentation) - else{ - ldev->read_buffer->image_line_no += 1; - source_read_cursor = i + line_header_length; - block_pixel_data_length = source_size - i - line_header_length; - ldev->read_buffer->last_line_bytes_read = block_pixel_data_length; - size_to_realloc = ((ldev->read_buffer->image_line_no-1) * - ldev->read_buffer->linesize + block_pixel_data_length) * sizeof(SANE_Byte); - bytes_read = block_pixel_data_length + line_header_length; + + DBG (20, " size_to_realloc=%d i=%d image_line_no=%d\n", + size_to_realloc, i, ldev->read_buffer->image_line_no); + // do realoc memory space for our buffer + SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); + if(alloc_result == NULL){ + // TODO allocation was not possible + DBG (20, " REALLOC failed\n"); } - } - // last line was not full lets extract what is left - // this is du to USB packet fragmentation - else{ - // the last line was not full so no increment - ldev->read_buffer->image_line_no += 0; - source_read_cursor = i; - block_pixel_data_length = ldev->read_buffer->linesize - - ldev->read_buffer->last_line_bytes_read; - // we completed the last line with missing bytes so new the line is full - ldev->read_buffer->last_line_bytes_read = ldev->read_buffer->linesize; - size_to_realloc = ldev->read_buffer->image_line_no * - ldev->read_buffer->linesize * sizeof(SANE_Byte); - bytes_read = block_pixel_data_length; - } + // point data to our new memary space + ldev->read_buffer->data = alloc_result; + // reposition writeptr and readptr to the correct memory adress + // to do that use write_byte_counter and read_byte_counter + ldev->read_buffer->writeptr = + ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; + // copy new data + memcpy( + ldev->read_buffer->writeptr, + source + source_read_cursor, + block_pixel_data_length + ); - DBG (20, " size_to_realloc=%d i=%d image_line_no=%d\n", - size_to_realloc, i, ldev->read_buffer->image_line_no); - // do realoc memory space for our buffer - SANE_Byte* alloc_result = realloc(ldev->read_buffer->data, size_to_realloc); - if(alloc_result == NULL){ - // TODO allocation was not possible - DBG (20, " REALLOC failed\n"); + // store how long is the buffer + ldev->read_buffer->write_byte_counter += block_pixel_data_length; + + i += bytes_read; } - // point data to our new memary space - ldev->read_buffer->data = alloc_result; - // reposition writeptr and readptr to the correct memory adress - // to do that use write_byte_counter and read_byte_counter - ldev->read_buffer->writeptr = - ldev->read_buffer->data + ldev->read_buffer->write_byte_counter; - ldev->read_buffer->readptr = - ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; - // copy new data - memcpy( - ldev->read_buffer->writeptr, - source + source_read_cursor, - block_pixel_data_length - ); - - // store how long is the buffer - ldev->read_buffer->write_byte_counter += block_pixel_data_length; - - i += bytes_read; } + // reposition our readptr + ldev->read_buffer->readptr = + ldev->read_buffer->data + ldev->read_buffer->read_byte_counter; + // read our buffer to fill the destination buffer // mulitple call so read may has been already started @@ -307,10 +313,18 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, ); ldev->read_buffer->read_byte_counter += data_chunk_size;; *destination_length = data_chunk_size; - + } - DBG (20, " done destination_length=%d\n", *destination_length); + DBG (20, " done destination_length=%d available_bytes_to_read=%d\n", + *destination_length, available_bytes_to_read); + + if(available_bytes_to_read > 0){ + return SANE_STATUS_GOOD; + }else{ + return SANE_STATUS_EOF; + } + } SANE_Status @@ -542,7 +556,7 @@ attach_one (SANE_String_Const devname) lexmark_device->sane.vendor = "Lexmark"; lexmark_device->sane.model = "X2600 series"; lexmark_device->sane.type = "flat bed"; - + /* init transfer_buffer */ lexmark_device->transfer_buffer = malloc (transfer_buffer_size); @@ -555,6 +569,7 @@ attach_one (SANE_String_Const devname) lexmark_device->read_buffer->image_line_no = 0; lexmark_device->read_buffer->write_byte_counter = 0; lexmark_device->read_buffer->read_byte_counter = 0; + lexmark_device->eof = SANE_FALSE; /* mark device as present */ lexmark_device->missing = SANE_FALSE; lexmark_device->device_cancelled = SANE_FALSE; @@ -1043,33 +1058,38 @@ sane_read (SANE_Handle handle, SANE_Byte * data, } //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); - DBG (1, " usb_read\n"); - status = sanei_usb_read_bulk ( - lexmark_device->devnum, lexmark_device->transfer_buffer, &size); - if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) - { - DBG (1, " USB READ Error in sanei_usb_read_bulk, cannot read devnum=%d status=%d size=%ld\n", - lexmark_device->devnum, status, size); - return status; - } - DBG (1, " usb_read done size=%ld\n", size); - debug_packet(lexmark_device->transfer_buffer, size, READ); - + if(!lexmark_device->eof){ + DBG (1, " usb_read\n"); + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); + if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF) + { + DBG (1, " USB READ Error in sanei_usb_read_bulk, cannot read devnum=%d status=%d size=%ld\n", + lexmark_device->devnum, status, size); + return status; + } + DBG (1, " usb_read done size=%ld\n", size); + debug_packet(lexmark_device->transfer_buffer, size, READ); + }else{ + DBG (1, " no usb_read eof reached\n"); + } + // is last data packet ? - if (memcmp(last_data_packet, lexmark_device->transfer_buffer, last_data_packet_size) == 0) - { - length = 0; - return SANE_STATUS_EOF; - } + if (!lexmark_device->eof && memcmp(last_data_packet, lexmark_device->transfer_buffer, last_data_packet_size) == 0){ + // we may still have data left to send in our buffer device->read_buffer->data + //length = 0; + //return SANE_STATUS_EOF; + lexmark_device->eof = SANE_TRUE; + DBG (1, " EOF PACKET no more data from scanner\n"); + + return SANE_STATUS_GOOD; + } // cancel packet received? - if (memcmp(cancel_packet, lexmark_device->transfer_buffer, cancel_packet_size) == 0) - { - length = 0; - return SANE_STATUS_CANCELLED; - } - - + if (memcmp(cancel_packet, lexmark_device->transfer_buffer, cancel_packet_size) == 0){ + length = 0; + return SANE_STATUS_CANCELLED; + } if (memcmp(empty_line_data_packet, lexmark_device->transfer_buffer, empty_line_data_packet_size) == 0){ return SANE_STATUS_GOOD; } @@ -1088,8 +1108,8 @@ sane_read (SANE_Handle handle, SANE_Byte * data, if (memcmp(unknnown_e_data_packet, lexmark_device->transfer_buffer, unknnown_e_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - - clean_and_copy_data( + + status = clean_and_copy_data( lexmark_device->transfer_buffer, size, data, @@ -1098,7 +1118,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, max_length, handle); - return SANE_STATUS_GOOD; + return status; } SANE_Status From 1fb0a78dd8861e481d16f2fd6e7b6780abb73b53 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Wed, 29 Nov 2023 06:23:32 +0100 Subject: [PATCH 38/49] simple scan sends cancel on page finish ... --- backend/lexmark_x2600.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 4b49cc1f2..c4ca89545 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -322,6 +322,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, if(available_bytes_to_read > 0){ return SANE_STATUS_GOOD; }else{ + ldev->eof = 0; return SANE_STATUS_EOF; } @@ -1155,9 +1156,9 @@ sane_cancel (SANE_Handle handle) if (lexmark_device == handle) break; } - sanei_usb_reset (lexmark_device->devnum); + //sanei_usb_reset (lexmark_device->devnum); - lexmark_device->device_cancelled = SANE_TRUE; + //lexmark_device->device_cancelled = SANE_TRUE; } void From 0661fe9d8994be8e8d2e4e14ba382cac2c5859cc Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Wed, 29 Nov 2023 06:31:31 +0100 Subject: [PATCH 39/49] fix warnings --- backend/lexmark_x2600.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index c4ca89545..89f42887f 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -115,7 +115,7 @@ static SANE_Int unknnown_e_data_packet_size = sizeof(unknnown_e_data_packet); /* static SANE_Int not_ready_data_packet_size = sizeof(not_ready_data_packet); */ -static SANE_Int line_header_length = 9; +static SANE_Int line_header_length = 9; //static SANE_Byte empty_data_packet[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -160,13 +160,11 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Byte tmp = 0; SANE_Int source_read_cursor = 0; SANE_Int block_pixel_data_length = 0; - SANE_Byte* alloc_result; - SANE_Byte* pixel[3]; SANE_Int size_to_realloc = 0; if(!ldev->eof){ - + // does source start with linebegin_data_packet? if (memcmp(linebegin_data_packet, source, linebegin_data_packet_size) == 0){ // extract the number of bytes we can read befor new header is reached @@ -191,7 +189,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, // last line was full if(ldev->read_buffer->last_line_bytes_read == ldev->read_buffer->linesize){ // if next block fit in the source - if(i + line_header_length + ldev->read_buffer->linesize <= source_size){ + if(i + line_header_length + (SANE_Int) ldev->read_buffer->linesize <= source_size){ ldev->read_buffer->image_line_no += 1; source_read_cursor = i + line_header_length; block_pixel_data_length = ldev->read_buffer->linesize; @@ -234,6 +232,7 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, if(alloc_result == NULL){ // TODO allocation was not possible DBG (20, " REALLOC failed\n"); + return SANE_STATUS_NO_MEM; } // point data to our new memary space ldev->read_buffer->data = alloc_result; @@ -266,7 +265,6 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, SANE_Int available_bytes_to_read = ldev->read_buffer->write_byte_counter - ldev->read_buffer->read_byte_counter; - SANE_Int offset = 0; DBG (20, " source read done now sending to destination \n"); @@ -313,19 +311,19 @@ clean_and_copy_data(const SANE_Byte * source, SANE_Int source_size, ); ldev->read_buffer->read_byte_counter += data_chunk_size;; *destination_length = data_chunk_size; - + } DBG (20, " done destination_length=%d available_bytes_to_read=%d\n", *destination_length, available_bytes_to_read); - + if(available_bytes_to_read > 0){ return SANE_STATUS_GOOD; }else{ ldev->eof = 0; - return SANE_STATUS_EOF; + return SANE_STATUS_EOF; } - + } SANE_Status @@ -557,7 +555,7 @@ attach_one (SANE_String_Const devname) lexmark_device->sane.vendor = "Lexmark"; lexmark_device->sane.model = "X2600 series"; lexmark_device->sane.type = "flat bed"; - + /* init transfer_buffer */ lexmark_device->transfer_buffer = malloc (transfer_buffer_size); @@ -749,6 +747,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, Lexmark_Device *lexmark_device; SANE_Status status; SANE_Word w; + SANE_Int res_selected; DBG (2, "sane_control_option: handle=%p, opt=%d, act=%d, val=%p, info=%p\n", (void *) handle, option, action, (void *) value, (void *) info); @@ -790,7 +789,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, switch (option){ case OPT_NUM_OPTS: case OPT_RESOLUTION: - SANE_Int res_selected = *(SANE_Int *) value; + res_selected = *(SANE_Int *) value; // first value is the size of the wordlist! for(int i=1; ieof && memcmp(last_data_packet, lexmark_device->transfer_buffer, last_data_packet_size) == 0){ - // we may still have data left to send in our buffer device->read_buffer->data + // we may still have data left to send in our buffer device->read_buffer->data //length = 0; //return SANE_STATUS_EOF; lexmark_device->eof = SANE_TRUE; @@ -1109,7 +1108,7 @@ sane_read (SANE_Handle handle, SANE_Byte * data, if (memcmp(unknnown_e_data_packet, lexmark_device->transfer_buffer, unknnown_e_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - + status = clean_and_copy_data( lexmark_device->transfer_buffer, size, @@ -1157,7 +1156,6 @@ sane_cancel (SANE_Handle handle) break; } //sanei_usb_reset (lexmark_device->devnum); - //lexmark_device->device_cancelled = SANE_TRUE; } From ec9efba602802b64cf9b58df8b34408d77ec27ba Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Wed, 29 Nov 2023 06:39:17 +0100 Subject: [PATCH 40/49] compile/typo fix --- backend/lexmark_x2600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 89f42887f..54fd12e89 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1000,7 +1000,7 @@ void debug_packet(const SANE_Byte * source, SANE_Int source_size, Debug_Packet d source[source_size-12-debug_offset], source[source_size-11-debug_offset], source[source_size-10-debug_offset], - source[source_size-9]-debug_offset); + source[source_size-9-debug_offset]); DBG (10, " %02hhx %02hhx %02hhx %02hhx | %02hhx %02hhx %02hhx %02hhx \n", source[source_size-8-debug_offset], source[source_size-7-debug_offset], From 0255c74669b787cdddf232e5d6bd2e653149ade9 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Thu, 30 Nov 2023 04:53:35 +0100 Subject: [PATCH 41/49] free buffers --- backend/lexmark_x2600.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 54fd12e89..4d6b6d7f7 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1190,6 +1190,8 @@ sane_exit (void) lexmark_device = next_lexmark_device) { next_lexmark_device = lexmark_device->next; + free (lexmark_device->transfer_buffer); + free (lexmark_device->read_buffer); free (lexmark_device); } From 80478c865be8608067adb7d1e6ea79ddb44d06b9 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Thu, 30 Nov 2023 06:47:40 +0100 Subject: [PATCH 42/49] add licence & author note --- backend/lexmark_x2600.c | 43 +++++++++++++++++++++++++++++++++++++++++ backend/lexmark_x2600.h | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 4d6b6d7f7..40c9a57f2 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -1,3 +1,46 @@ +/* lexmark_x2600.c: SANE backend for Lexmark x2600 scanners. + + (C) 2023 "Benoit Juin" + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. + + **************************************************************************/ + + #include "lexmark_x2600.h" #define BUILD 1 diff --git a/backend/lexmark_x2600.h b/backend/lexmark_x2600.h index ea5f2570d..e53b48d49 100644 --- a/backend/lexmark_x2600.h +++ b/backend/lexmark_x2600.h @@ -1,3 +1,44 @@ +/* lexmark_x2600.c: SANE backend for Lexmark x2600 scanners. + + (C) 2023 "Benoit Juin" + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. + + **************************************************************************/ #ifndef LEXMARK_X2600_H #define LEXMARK_X2600_H #define BACKEND_NAME lexmark_x2600 From 7631c15c5ecf4cce83c3b7c313aaadb40f1f1024 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 05:51:50 +0100 Subject: [PATCH 43/49] Mem alloc checks, typo and handle cancel scan correctly --- backend/lexmark_x2600.c | 88 +++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 40c9a57f2..67cd91cc3 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -132,26 +132,26 @@ static SANE_Byte linebegin_data_packet[] = { 0x1b, 0x53, 0x02, 0x00}; static SANE_Int linebegin_data_packet_size = sizeof(linebegin_data_packet); -static SANE_Byte unknnown_a_data_packet[] = { +static SANE_Byte unknown_a_data_packet[] = { 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x80, 0x00}; -static SANE_Int unknnown_a_data_packet_size = sizeof(unknnown_a_data_packet); +static SANE_Int unknown_a_data_packet_size = sizeof(unknown_a_data_packet); -static SANE_Byte unknnown_b_data_packet[] = { +static SANE_Byte unknown_b_data_packet[] = { 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; -static SANE_Int unknnown_b_data_packet_size = sizeof(unknnown_b_data_packet); +static SANE_Int unknown_b_data_packet_size = sizeof(unknown_b_data_packet); -static SANE_Byte unknnown_c_data_packet[] = { +static SANE_Byte unknown_c_data_packet[] = { 0x1b, 0x53, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00}; -static SANE_Int unknnown_c_data_packet_size = sizeof(unknnown_c_data_packet); +static SANE_Int unknown_c_data_packet_size = sizeof(unknown_c_data_packet); -static SANE_Byte unknnown_d_data_packet[] = { +static SANE_Byte unknown_d_data_packet[] = { 0x1b, 0x53, 0x05, 0x00, 0x00, 0x00}; -static SANE_Int unknnown_d_data_packet_size = sizeof(unknnown_d_data_packet); +static SANE_Int unknown_d_data_packet_size = sizeof(unknown_d_data_packet); -static SANE_Byte unknnown_e_data_packet[] = { +static SANE_Byte unknown_e_data_packet[] = { 0xa5, 0x00, 0x06, 0x10, 0x01, 0xaa, 0xbb, 0xcc, 0xdd}; -static SANE_Int unknnown_e_data_packet_size = sizeof(unknnown_e_data_packet); +static SANE_Int unknown_e_data_packet_size = sizeof(unknown_e_data_packet); /* static SANE_Byte not_ready_data_packet[] = { */ /* 0x1b, 0x53, 0x01, 0x00, 0x01, 0x00, 0x84, 0x00}; */ @@ -595,23 +595,23 @@ attach_one (SANE_String_Const devname) return SANE_STATUS_NO_MEM; lexmark_device->sane.name = strdup (devname); + if (lexmark_device->sane.name == NULL) + return SANE_STATUS_NO_MEM; lexmark_device->sane.vendor = "Lexmark"; lexmark_device->sane.model = "X2600 series"; lexmark_device->sane.type = "flat bed"; /* init transfer_buffer */ lexmark_device->transfer_buffer = malloc (transfer_buffer_size); + if (lexmark_device->transfer_buffer == NULL) + return SANE_STATUS_NO_MEM; /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = malloc (sizeof (Read_Buffer)); - lexmark_device->read_buffer->data = NULL; - lexmark_device->read_buffer->size = 0; - lexmark_device->read_buffer->last_line_bytes_read = 0; - lexmark_device->read_buffer->image_line_no = 0; - lexmark_device->read_buffer->write_byte_counter = 0; - lexmark_device->read_buffer->read_byte_counter = 0; - lexmark_device->eof = SANE_FALSE; + if (lexmark_device->read_buffer == NULL) + return SANE_STATUS_NO_MEM; + /* mark device as present */ lexmark_device->missing = SANE_FALSE; lexmark_device->device_cancelled = SANE_FALSE; @@ -981,7 +981,9 @@ sane_start (SANE_Handle handle) Lexmark_Device * lexmark_device; SANE_Status status; SANE_Byte * cmd = (SANE_Byte *) malloc - (command_with_params_block_size * sizeof (SANE_Byte));; + (command_with_params_block_size * sizeof (SANE_Byte)); + if (cmd == NULL) + return SANE_STATUS_NO_MEM; DBG (2, "sane_start: handle=%p initialized=%d\n", (void *) handle, initialized); @@ -995,6 +997,20 @@ sane_start (SANE_Handle handle) break; } + if(lexmark_device == NULL){ + DBG (2, " Cannot find device\n"); + return SANE_STATUS_IO_ERROR; + } + + lexmark_device->read_buffer->data = NULL; + lexmark_device->read_buffer->size = 0; + lexmark_device->read_buffer->last_line_bytes_read = 0; + lexmark_device->read_buffer->image_line_no = 0; + lexmark_device->read_buffer->write_byte_counter = 0; + lexmark_device->read_buffer->read_byte_counter = 0; + lexmark_device->eof = SANE_FALSE; + lexmark_device->device_cancelled = SANE_FALSE; + //launch scan commands status = usb_write_then_read(lexmark_device, command1_block, command1_block_size); @@ -1018,6 +1034,8 @@ sane_start (SANE_Handle handle) if (status != SANE_STATUS_GOOD) return status; + free(cmd); + return SANE_STATUS_GOOD; } @@ -1088,16 +1106,16 @@ sane_read (SANE_Handle handle, SANE_Byte * data, // to empty buffers status = sanei_usb_read_bulk ( lexmark_device->devnum, lexmark_device->transfer_buffer, &size); - DBG (10, "USB READ \n"); - status = sanei_usb_read_bulk ( - lexmark_device->devnum, lexmark_device->transfer_buffer, &size); - DBG (10, "USB READ \n"); - status = sanei_usb_read_bulk ( - lexmark_device->devnum, lexmark_device->transfer_buffer, &size); - DBG (10, "USB READ \n"); - //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); - //DBG (10, "USB READ \n"); - return SANE_STATUS_CANCELLED;//SANE_STATUS_GOOD; //; + if(status == SANE_STATUS_GOOD){ + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); + } + if(status == SANE_STATUS_GOOD){ + status = sanei_usb_read_bulk ( + lexmark_device->devnum, lexmark_device->transfer_buffer, &size); + } + + return status; } //status = sanei_usb_read_bulk (lexmark_device->devnum, buf, &size); @@ -1136,19 +1154,19 @@ sane_read (SANE_Handle handle, SANE_Byte * data, if (memcmp(empty_line_data_packet, lexmark_device->transfer_buffer, empty_line_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - if (memcmp(unknnown_a_data_packet, lexmark_device->transfer_buffer, unknnown_a_data_packet_size) == 0){ + if (memcmp(unknown_a_data_packet, lexmark_device->transfer_buffer, unknown_a_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - if (memcmp(unknnown_b_data_packet, lexmark_device->transfer_buffer, unknnown_b_data_packet_size) == 0){ + if (memcmp(unknown_b_data_packet, lexmark_device->transfer_buffer, unknown_b_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - if (memcmp(unknnown_c_data_packet, lexmark_device->transfer_buffer, unknnown_c_data_packet_size) == 0){ + if (memcmp(unknown_c_data_packet, lexmark_device->transfer_buffer, unknown_c_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - if (memcmp(unknnown_d_data_packet, lexmark_device->transfer_buffer, unknnown_d_data_packet_size) == 0){ + if (memcmp(unknown_d_data_packet, lexmark_device->transfer_buffer, unknown_d_data_packet_size) == 0){ return SANE_STATUS_GOOD; } - if (memcmp(unknnown_e_data_packet, lexmark_device->transfer_buffer, unknnown_e_data_packet_size) == 0){ + if (memcmp(unknown_e_data_packet, lexmark_device->transfer_buffer, unknown_e_data_packet_size) == 0){ return SANE_STATUS_GOOD; } @@ -1198,8 +1216,8 @@ sane_cancel (SANE_Handle handle) if (lexmark_device == handle) break; } - //sanei_usb_reset (lexmark_device->devnum); - //lexmark_device->device_cancelled = SANE_TRUE; + sanei_usb_reset (lexmark_device->devnum); + lexmark_device->device_cancelled = SANE_TRUE; } void From f7dd8e224dd0d8dff4eaf8a0c7f4bddfc52e2d81 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 06:00:23 +0100 Subject: [PATCH 44/49] memoy leak fix --- backend/lexmark_x2600.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 67cd91cc3..5b24c399e 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -999,6 +999,7 @@ sane_start (SANE_Handle handle) if(lexmark_device == NULL){ DBG (2, " Cannot find device\n"); + free(cmd); return SANE_STATUS_IO_ERROR; } @@ -1015,27 +1016,30 @@ sane_start (SANE_Handle handle) status = usb_write_then_read(lexmark_device, command1_block, command1_block_size); if (status != SANE_STATUS_GOOD) + free(cmd); return status; status = usb_write_then_read(lexmark_device, command2_block, command2_block_size); if (status != SANE_STATUS_GOOD) + free(cmd); return status; build_packet(lexmark_device, 0x05, cmd); status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) + free(cmd); return status; build_packet(lexmark_device, 0x01, cmd);; status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); if (status != SANE_STATUS_GOOD) + free(cmd); return status; free(cmd); - return SANE_STATUS_GOOD; } From 068714ef6ec59e7857b099e36839358caa2f4890 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 06:14:03 +0100 Subject: [PATCH 45/49] fix ifs --- backend/lexmark_x2600.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 5b24c399e..669ed5c65 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -672,8 +672,8 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) SANE_Int index; Lexmark_Device *lexmark_device; - DBG (2, "sane_get_devices: device_list=%p, local_only=%d\n", - (void *) device_list, local_only); + DBG (2, "sane_get_devices: device_list=%p, local_only=%d num_devices=%d\n", + (void *) device_list, local_only, num_devices); sanei_usb_scan_devices (); @@ -1015,30 +1015,31 @@ sane_start (SANE_Handle handle) //launch scan commands status = usb_write_then_read(lexmark_device, command1_block, command1_block_size); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD){ free(cmd); return status; - + } status = usb_write_then_read(lexmark_device, command2_block, command2_block_size); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD){ free(cmd); return status; - + } build_packet(lexmark_device, 0x05, cmd); status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD){ free(cmd); return status; - + } build_packet(lexmark_device, 0x01, cmd);; status = usb_write_then_read(lexmark_device, cmd, command_with_params_block_size); - if (status != SANE_STATUS_GOOD) + if (status != SANE_STATUS_GOOD){ free(cmd); return status; - + } + free(cmd); return SANE_STATUS_GOOD; } From 84c94b83689424be2962040cd079f78f30188a83 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 07:03:39 +0100 Subject: [PATCH 46/49] handle usb plug/unplug correctly --- backend/lexmark_x2600.c | 65 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 669ed5c65..2119bfe1d 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -577,18 +577,18 @@ attach_one (SANE_String_Const devname) { Lexmark_Device *lexmark_device; - DBG (2, "attach_one: attachLexmark: devname=%s\n", devname); + DBG (2, "attach_one: attachLexmark: devname=%s first_device=%p\n", + devname, (void *)first_device); for (lexmark_device = first_device; lexmark_device; - lexmark_device = lexmark_device->next) - { - /* already attached devices */ - if (strcmp (lexmark_device->sane.name, devname) == 0) - { - lexmark_device->missing = SANE_FALSE; - return SANE_STATUS_GOOD; - } + lexmark_device = lexmark_device->next){ + /* already attached devices */ + + if (strcmp (lexmark_device->sane.name, devname) == 0){ + lexmark_device->missing = SANE_FALSE; + return SANE_STATUS_GOOD; } + } lexmark_device = (Lexmark_Device *) malloc (sizeof (Lexmark_Device)); if (lexmark_device == NULL) @@ -606,7 +606,6 @@ attach_one (SANE_String_Const devname) if (lexmark_device->transfer_buffer == NULL) return SANE_STATUS_NO_MEM; - /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = malloc (sizeof (Read_Buffer)); if (lexmark_device->read_buffer == NULL) @@ -619,27 +618,18 @@ attach_one (SANE_String_Const devname) lexmark_device->next = first_device; first_device = lexmark_device; num_devices++; + DBG (2, " first_device=%p\n", (void *)first_device); return SANE_STATUS_GOOD; } SANE_Status -sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) -{ - FILE *fp; +scan_devices(){ SANE_Char config_line[PATH_MAX]; + FILE *fp; const char *lp; - - DBG_INIT (); - DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", - version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); - DBG (1, " SANE lexmark_x2600 backend version %d.%d.%d from %s\n", - SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); - - if (version_code) - *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); - - sanei_usb_init (); + num_devices = 0; + first_device = NULL; fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); if (!fp) @@ -658,14 +648,32 @@ sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) continue; DBG (4, " attach_matching_devices(%s)\n", config_line); + sanei_usb_init(); sanei_usb_attach_matching_devices (config_line, attach_one); } fclose (fp); - initialized = SANE_TRUE; return SANE_STATUS_GOOD; } +SANE_Status +sane_init (SANE_Int *version_code, SANE_Auth_Callback authorize) +{ + DBG_INIT (); + DBG (2, "sane_init: version_code %s 0, authorize %s 0\n", + version_code == 0 ? "=" : "!=", authorize == 0 ? "=" : "!="); + DBG (1, " SANE lexmark_x2600 backend version %d.%d.%d from %s\n", + SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD, PACKAGE_STRING); + + if (version_code) + *version_code = SANE_VERSION_CODE (SANE_CURRENT_MAJOR, SANE_CURRENT_MINOR, BUILD); + + + SANE_Status status = scan_devices(); + initialized = SANE_TRUE; + return status; +} + SANE_Status sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) { @@ -675,7 +683,8 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) DBG (2, "sane_get_devices: device_list=%p, local_only=%d num_devices=%d\n", (void *) device_list, local_only, num_devices); - sanei_usb_scan_devices (); + //sanei_usb_scan_devices (); + SANE_Status status = scan_devices(); if (devlist) free (devlist); @@ -702,7 +711,7 @@ sane_get_devices (const SANE_Device ***device_list, SANE_Bool local_only) *device_list = devlist; - return SANE_STATUS_GOOD; + return status; } SANE_Status @@ -1039,7 +1048,7 @@ sane_start (SANE_Handle handle) free(cmd); return status; } - + free(cmd); return SANE_STATUS_GOOD; } From daebecd21676372bf10a7e5d20108d372870e5aa Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 07:11:41 +0100 Subject: [PATCH 47/49] fix memory leak --- backend/lexmark_x2600.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 2119bfe1d..2899c8ad8 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -625,10 +625,17 @@ attach_one (SANE_String_Const devname) SANE_Status scan_devices(){ + DBG (2, "scan_devices\n"); SANE_Char config_line[PATH_MAX]; FILE *fp; const char *lp; num_devices = 0; + + if(first_device){ + DBG (2, " free first_device\n"); + free(first_device); + } + first_device = NULL; fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); From 7efa04ff7823f95327ca38638167e730c36b439f Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 07:12:11 +0100 Subject: [PATCH 48/49] white spaces --- backend/lexmark_x2600.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index 2899c8ad8..e8542d2e9 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -625,7 +625,7 @@ attach_one (SANE_String_Const devname) SANE_Status scan_devices(){ - DBG (2, "scan_devices\n"); + DBG (2, "scan_devices\n"); SANE_Char config_line[PATH_MAX]; FILE *fp; const char *lp; @@ -635,7 +635,7 @@ scan_devices(){ DBG (2, " free first_device\n"); free(first_device); } - + first_device = NULL; fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); From c1e9a341ab78a82c7c514b69992d79faab67e749 Mon Sep 17 00:00:00 2001 From: Benoit JUIN Date: Sun, 3 Dec 2023 08:07:56 +0100 Subject: [PATCH 49/49] memory leak fix --- backend/lexmark_x2600.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/lexmark_x2600.c b/backend/lexmark_x2600.c index e8542d2e9..610064ed8 100644 --- a/backend/lexmark_x2600.c +++ b/backend/lexmark_x2600.c @@ -631,13 +631,14 @@ scan_devices(){ const char *lp; num_devices = 0; - if(first_device){ + // -- free existing device we are doning a full re-scan + while (first_device){ + Lexmark_Device *this_device = first_device; + first_device = first_device->next; DBG (2, " free first_device\n"); - free(first_device); + free(this_device); } - first_device = NULL; - fp = sanei_config_open (LEXMARK_X2600_CONFIG_FILE); if (!fp) {