diff options
author | Didier Raboud <odyx@debian.org> | 2019-09-13 17:56:14 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2019-09-13 17:56:14 +0200 |
commit | b38516f13a1f563aa1eb7faf80965755ac63e3e6 (patch) | |
tree | fd60cd4095a45f7327d28dfe04bbfb34b7d7215a /src/cups | |
parent | e50542121e724e851fc5d6c68bb773f80c0bc12c (diff) |
New upstream version 5.3.3
Diffstat (limited to 'src/cups')
30 files changed, 5316 insertions, 5879 deletions
diff --git a/src/cups/Makefile.am b/src/cups/Makefile.am index 2f70701..1812d55 100644 --- a/src/cups/Makefile.am +++ b/src/cups/Makefile.am @@ -99,11 +99,13 @@ endif AM_TESTS_ENVIRONMENT=$(STP_ENV) test-rastertogutenprint: min-pagesize -test-rastertogutenprint.check: test-rastertogutenprint -TESTS= test-ppds test-rastertogutenprint.check -noinst_SCRIPTS=test-ppds \ +test-rastertogutenprint.test: test-rastertogutenprint +TESTS= test-ppds.test test-rastertogutenprint.test +test-rastertogutenprint.log: test-ppds.log + +noinst_SCRIPTS=test-ppds.test \ test-rastertogutenprint \ - test-rastertogutenprint.check \ + test-rastertogutenprint.test \ min-pagesize endif @@ -121,7 +123,7 @@ commandtoepson_SOURCES = commandtoepson.c commandtoepson_LDADD = $(CUPS_LIBS) if BUILD_LIBUSB_BACKENDS -backend_gutenprint_SOURCES = backend_canonselphy.c backend_canonselphyneo.c backend_kodak1400.c backend_kodak6800.c backend_kodak605.c backend_shinkos2145.c backend_sonyupdr150.c backend_dnpds40.c backend_mitsu70x.c backend_mitsu9550.c backend_common.c backend_common.h backend_shinkos1245.c backend_shinkos6145.c backend_shinkos6245.c backend_mitsup95d.c backend_magicard.c backend_mitsud90.c +backend_gutenprint_SOURCES = backend_canonselphy.c backend_canonselphyneo.c backend_kodak1400.c backend_kodak6800.c backend_kodak605.c backend_shinkos2145.c backend_sonyupd.c backend_dnpds40.c backend_mitsu70x.c backend_mitsu9550.c backend_sinfonia.c backend_sinfonia.h backend_common.c backend_common.h backend_shinkos1245.c backend_shinkos6145.c backend_shinkos6245.c backend_mitsup95d.c backend_magicard.c backend_mitsud90.c backend_gutenprint_LDADD = $(LIBUSB_LIBS) $(LIBUSB_BACKEND_LIBDEPS) backend_gutenprint_CPPFLAGS = $(LIBUSB_CFLAGS) -DURI_PREFIX=\"gutenprint$(GUTENPRINT_MAJOR_VERSION)$(GUTENPRINT_MINOR_VERSION)+usb\" -DLIBUSB_PRE_1_0_10 @@ -229,7 +231,7 @@ all-local: $(INSTALL_DATA_LOCAL_DEPS) ppd: ppd-stamp -ppd-stamp: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(top_srcdir)/src/xml/xml-stamp +ppd-stamp: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(top_srcdir)/src/xml/xml-stamp ppd-stamp-pre $(MAKE) ppd-stamp-pre $(MAKE) ppd-stamp-phony touch ppd-stamp @@ -256,60 +258,60 @@ ppd-nonls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs:" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) ppd-nonls-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs (all):" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C -a + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C -a $(EXTRA_GENPPD_OPTS) ppd-nonls-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs (simplified):" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C -s + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C -s $(EXTRA_GENPPD_OPTS) ppd-global: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs:" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -a + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -a $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (simplified):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -s + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -s $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all, localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N -a + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N -a $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all, localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N -s + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N -s $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-nls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ ppd-nonls @@ -319,7 +321,7 @@ ppd-nls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l $$language -p $(PPD_DIR)/$$language; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l $$language -p $(PPD_DIR)/$$language $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean @@ -330,7 +332,7 @@ ppd-nls-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -a; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -a $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean @@ -341,7 +343,7 @@ ppd-nls-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -s; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -s $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean @@ -363,12 +365,11 @@ clean-local: ppd-catalog-clean ppd-clean ## Clean CLEANFILES = ppd-stamp -DISTCLEANFILES = cups-genppdupdate test-ppds +DISTCLEANFILES = cups-genppdupdate test-ppds.test MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = \ COPYING \ - README \ blacklist \ calibrate.ppm \ command.txt \ diff --git a/src/cups/Makefile.in b/src/cups/Makefile.in index 605047b..ecaf5a7 100644 --- a/src/cups/Makefile.in +++ b/src/cups/Makefile.in @@ -102,24 +102,25 @@ host_triplet = @host@ @BUILD_CUPS_TRUE@@BUILD_LIBUSB_BACKENDS_TRUE@cupsexec_backend_PROGRAMS = backend_gutenprint$(EXEEXT) subdir = src/cups ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ - $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4local/stp.m4 \ + $(top_srcdir)/m4local/stp_cups.m4 \ + $(top_srcdir)/m4local/stp_option.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ - $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stp.m4 \ - $(top_srcdir)/m4/stp_cups.m4 $(top_srcdir)/m4/stp_option.m4 \ - $(top_srcdir)/m4/stp_release.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stp_release.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = Info.plist cups-genppdupdate test-ppds \ +CONFIG_CLEAN_FILES = Info.plist cups-genppdupdate test-ppds.test \ min-pagesize test-rastertogutenprint \ - test-rastertogutenprint.check + test-rastertogutenprint.test CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(cupsexec_backenddir)" \ @@ -133,21 +134,22 @@ PROGRAMS = $(bin_PROGRAMS) $(cupsexec_backend_PROGRAMS) \ am__backend_gutenprint_SOURCES_DIST = backend_canonselphy.c \ backend_canonselphyneo.c backend_kodak1400.c \ backend_kodak6800.c backend_kodak605.c backend_shinkos2145.c \ - backend_sonyupdr150.c backend_dnpds40.c backend_mitsu70x.c \ - backend_mitsu9550.c backend_common.c backend_common.h \ - backend_shinkos1245.c backend_shinkos6145.c \ - backend_shinkos6245.c backend_mitsup95d.c backend_magicard.c \ - backend_mitsud90.c + backend_sonyupd.c backend_dnpds40.c backend_mitsu70x.c \ + backend_mitsu9550.c backend_sinfonia.c backend_sinfonia.h \ + backend_common.c backend_common.h backend_shinkos1245.c \ + backend_shinkos6145.c backend_shinkos6245.c \ + backend_mitsup95d.c backend_magicard.c backend_mitsud90.c @BUILD_LIBUSB_BACKENDS_TRUE@am_backend_gutenprint_OBJECTS = backend_gutenprint-backend_canonselphy.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_canonselphyneo.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_kodak1400.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_kodak6800.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_kodak605.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_shinkos2145.$(OBJEXT) \ -@BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_sonyupdr150.$(OBJEXT) \ +@BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_sonyupd.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_dnpds40.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_mitsu70x.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_mitsu9550.$(OBJEXT) \ +@BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_sinfonia.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_common.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_shinkos1245.$(OBJEXT) \ @BUILD_LIBUSB_BACKENDS_TRUE@ backend_gutenprint-backend_shinkos6145.$(OBJEXT) \ @@ -269,7 +271,8 @@ am__depfiles_remade = \ ./$(DEPDIR)/backend_gutenprint-backend_shinkos2145.Po \ ./$(DEPDIR)/backend_gutenprint-backend_shinkos6145.Po \ ./$(DEPDIR)/backend_gutenprint-backend_shinkos6245.Po \ - ./$(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po \ + ./$(DEPDIR)/backend_gutenprint-backend_sinfonia.Po \ + ./$(DEPDIR)/backend_gutenprint-backend_sonyupd.Po \ ./$(DEPDIR)/commandtocanon.Po ./$(DEPDIR)/commandtoepson.Po \ ./$(DEPDIR)/cups-calibrate.Po \ ./$(DEPDIR)/cups_genppd_@GUTENPRINT_RELEASE_VERSION@-cups-genppd.Po \ @@ -493,8 +496,12 @@ RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test -LOG_DRIVER = $(SHELL) $(top_srcdir)/scripts/test-driver -LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/scripts/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ @@ -505,19 +512,13 @@ am__set_b = \ *) \ b='$*';; \ esac -am__test_logs1 = $(TESTS:=.log) -am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) -TEST_LOGS = $(am__test_logs2:.test.log=.log) -TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/scripts/test-driver -TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ - $(TEST_LOG_FLAGS) am__DIST_COMMON = $(srcdir)/Info.plist.in $(srcdir)/Makefile.in \ $(srcdir)/cups-genppdupdate.in $(srcdir)/min-pagesize.in \ - $(srcdir)/test-ppds.in \ - $(srcdir)/test-rastertogutenprint.check.in \ + $(srcdir)/test-ppds.test.in \ $(srcdir)/test-rastertogutenprint.in \ + $(srcdir)/test-rastertogutenprint.test.in \ $(top_srcdir)/scripts/depcomp $(top_srcdir)/scripts/global.mk \ - $(top_srcdir)/scripts/test-driver COPYING README + $(top_srcdir)/scripts/test-driver COPYING DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) pkgdatadir = $(cups_conf_datadir) pkglibdir = $(cups_conf_serverbin) @@ -568,7 +569,6 @@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ FIND = @FIND@ GENPPD_LIBS = @GENPPD_LIBS@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GIMP2_CFLAGS = @GIMP2_CFLAGS@ GIMP2_LIBS = @GIMP2_LIBS@ GIMPTOOL2_CHECK = @GIMPTOOL2_CHECK@ @@ -677,7 +677,6 @@ VERSION = @VERSION@ WHICH_PPDS = @WHICH_PPDS@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ -XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XZ = @XZ@ YACC = @YACC@ YFLAGS = @YFLAGS@ @@ -771,10 +770,10 @@ STP_ENV = $(STP_NONLS_ENV) STP_LOCALEDIR=$(top_builddir)/src/cups/$(PPD_DIR)cata @BUILD_SIMPLIFIED_CUPS_PPDS_TRUE@BUILD_SIMPLE_PPDS = -DGENERATE_SIMPLIFIED_PPDS @BUILD_CUPS_TRUE@sbin_SCRIPTS = cups-genppdupdate @BUILD_CUPS_TRUE@AM_TESTS_ENVIRONMENT = $(STP_ENV) -@BUILD_CUPS_TRUE@TESTS = test-ppds test-rastertogutenprint.check -@BUILD_CUPS_TRUE@noinst_SCRIPTS = test-ppds \ +@BUILD_CUPS_TRUE@TESTS = test-ppds.test test-rastertogutenprint.test +@BUILD_CUPS_TRUE@noinst_SCRIPTS = test-ppds.test \ @BUILD_CUPS_TRUE@ test-rastertogutenprint \ -@BUILD_CUPS_TRUE@ test-rastertogutenprint.check \ +@BUILD_CUPS_TRUE@ test-rastertogutenprint.test \ @BUILD_CUPS_TRUE@ min-pagesize @BUILD_GENPPD_STATIC_TRUE@STATIC_LDOPTS = -static -export-dynamic @@ -784,7 +783,7 @@ commandtocanon_SOURCES = commandtocanon.c commandtocanon_LDADD = $(CUPS_LIBS) commandtoepson_SOURCES = commandtoepson.c commandtoepson_LDADD = $(CUPS_LIBS) -@BUILD_LIBUSB_BACKENDS_TRUE@backend_gutenprint_SOURCES = backend_canonselphy.c backend_canonselphyneo.c backend_kodak1400.c backend_kodak6800.c backend_kodak605.c backend_shinkos2145.c backend_sonyupdr150.c backend_dnpds40.c backend_mitsu70x.c backend_mitsu9550.c backend_common.c backend_common.h backend_shinkos1245.c backend_shinkos6145.c backend_shinkos6245.c backend_mitsup95d.c backend_magicard.c backend_mitsud90.c +@BUILD_LIBUSB_BACKENDS_TRUE@backend_gutenprint_SOURCES = backend_canonselphy.c backend_canonselphyneo.c backend_kodak1400.c backend_kodak6800.c backend_kodak605.c backend_shinkos2145.c backend_sonyupd.c backend_dnpds40.c backend_mitsu70x.c backend_mitsu9550.c backend_sinfonia.c backend_sinfonia.h backend_common.c backend_common.h backend_shinkos1245.c backend_shinkos6145.c backend_shinkos6245.c backend_mitsup95d.c backend_magicard.c backend_mitsud90.c @BUILD_LIBUSB_BACKENDS_TRUE@backend_gutenprint_LDADD = $(LIBUSB_LIBS) $(LIBUSB_BACKEND_LIBDEPS) @BUILD_LIBUSB_BACKENDS_TRUE@backend_gutenprint_CPPFLAGS = $(LIBUSB_CFLAGS) -DURI_PREFIX=\"gutenprint$(GUTENPRINT_MAJOR_VERSION)$(GUTENPRINT_MINOR_VERSION)+usb\" -DLIBUSB_PRE_1_0_10 cups_genppd_@GUTENPRINT_RELEASE_VERSION@_SOURCES = cups-genppd.c genppd.c genppd.h i18n.c i18n.h @@ -806,11 +805,10 @@ pkgsysconf_DATA = $(CUPS_CONF) @USE_NLS_TRUE@PPD_NLS_1 = ppd-nls @BUILD_LIBUSB_BACKENDS_TRUE@INSTALL_BLACKLIST = install-blacklist CLEANFILES = ppd-stamp -DISTCLEANFILES = cups-genppdupdate test-ppds +DISTCLEANFILES = cups-genppdupdate test-ppds.test MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = \ COPYING \ - README \ blacklist \ calibrate.ppm \ command.txt \ @@ -854,13 +852,13 @@ Info.plist: $(top_builddir)/config.status $(srcdir)/Info.plist.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ cups-genppdupdate: $(top_builddir)/config.status $(srcdir)/cups-genppdupdate.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -test-ppds: $(top_builddir)/config.status $(srcdir)/test-ppds.in +test-ppds.test: $(top_builddir)/config.status $(srcdir)/test-ppds.test.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ min-pagesize: $(top_builddir)/config.status $(srcdir)/min-pagesize.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ test-rastertogutenprint: $(top_builddir)/config.status $(srcdir)/test-rastertogutenprint.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ -test-rastertogutenprint.check: $(top_builddir)/config.status $(srcdir)/test-rastertogutenprint.check.in +test-rastertogutenprint.test: $(top_builddir)/config.status $(srcdir)/test-rastertogutenprint.test.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @@ -1193,7 +1191,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_shinkos2145.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_shinkos6145.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_shinkos6245.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_sinfonia.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_gutenprint-backend_sonyupd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandtocanon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandtoepson.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cups-calibrate.Po@am__quote@ # am--include-marker @@ -1317,19 +1316,19 @@ backend_gutenprint-backend_shinkos2145.obj: backend_shinkos2145.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_shinkos2145.obj `if test -f 'backend_shinkos2145.c'; then $(CYGPATH_W) 'backend_shinkos2145.c'; else $(CYGPATH_W) '$(srcdir)/backend_shinkos2145.c'; fi` -backend_gutenprint-backend_sonyupdr150.o: backend_sonyupdr150.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sonyupdr150.o -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Tpo -c -o backend_gutenprint-backend_sonyupdr150.o `test -f 'backend_sonyupdr150.c' || echo '$(srcdir)/'`backend_sonyupdr150.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Tpo $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sonyupdr150.c' object='backend_gutenprint-backend_sonyupdr150.o' libtool=no @AMDEPBACKSLASH@ +backend_gutenprint-backend_sonyupd.o: backend_sonyupd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sonyupd.o -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sonyupd.Tpo -c -o backend_gutenprint-backend_sonyupd.o `test -f 'backend_sonyupd.c' || echo '$(srcdir)/'`backend_sonyupd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sonyupd.Tpo $(DEPDIR)/backend_gutenprint-backend_sonyupd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sonyupd.c' object='backend_gutenprint-backend_sonyupd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sonyupdr150.o `test -f 'backend_sonyupdr150.c' || echo '$(srcdir)/'`backend_sonyupdr150.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sonyupd.o `test -f 'backend_sonyupd.c' || echo '$(srcdir)/'`backend_sonyupd.c -backend_gutenprint-backend_sonyupdr150.obj: backend_sonyupdr150.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sonyupdr150.obj -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Tpo -c -o backend_gutenprint-backend_sonyupdr150.obj `if test -f 'backend_sonyupdr150.c'; then $(CYGPATH_W) 'backend_sonyupdr150.c'; else $(CYGPATH_W) '$(srcdir)/backend_sonyupdr150.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Tpo $(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sonyupdr150.c' object='backend_gutenprint-backend_sonyupdr150.obj' libtool=no @AMDEPBACKSLASH@ +backend_gutenprint-backend_sonyupd.obj: backend_sonyupd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sonyupd.obj -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sonyupd.Tpo -c -o backend_gutenprint-backend_sonyupd.obj `if test -f 'backend_sonyupd.c'; then $(CYGPATH_W) 'backend_sonyupd.c'; else $(CYGPATH_W) '$(srcdir)/backend_sonyupd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sonyupd.Tpo $(DEPDIR)/backend_gutenprint-backend_sonyupd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sonyupd.c' object='backend_gutenprint-backend_sonyupd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sonyupdr150.obj `if test -f 'backend_sonyupdr150.c'; then $(CYGPATH_W) 'backend_sonyupdr150.c'; else $(CYGPATH_W) '$(srcdir)/backend_sonyupdr150.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sonyupd.obj `if test -f 'backend_sonyupd.c'; then $(CYGPATH_W) 'backend_sonyupd.c'; else $(CYGPATH_W) '$(srcdir)/backend_sonyupd.c'; fi` backend_gutenprint-backend_dnpds40.o: backend_dnpds40.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_dnpds40.o -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_dnpds40.Tpo -c -o backend_gutenprint-backend_dnpds40.o `test -f 'backend_dnpds40.c' || echo '$(srcdir)/'`backend_dnpds40.c @@ -1373,6 +1372,20 @@ backend_gutenprint-backend_mitsu9550.obj: backend_mitsu9550.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_mitsu9550.obj `if test -f 'backend_mitsu9550.c'; then $(CYGPATH_W) 'backend_mitsu9550.c'; else $(CYGPATH_W) '$(srcdir)/backend_mitsu9550.c'; fi` +backend_gutenprint-backend_sinfonia.o: backend_sinfonia.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sinfonia.o -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sinfonia.Tpo -c -o backend_gutenprint-backend_sinfonia.o `test -f 'backend_sinfonia.c' || echo '$(srcdir)/'`backend_sinfonia.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sinfonia.Tpo $(DEPDIR)/backend_gutenprint-backend_sinfonia.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sinfonia.c' object='backend_gutenprint-backend_sinfonia.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sinfonia.o `test -f 'backend_sinfonia.c' || echo '$(srcdir)/'`backend_sinfonia.c + +backend_gutenprint-backend_sinfonia.obj: backend_sinfonia.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_sinfonia.obj -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_sinfonia.Tpo -c -o backend_gutenprint-backend_sinfonia.obj `if test -f 'backend_sinfonia.c'; then $(CYGPATH_W) 'backend_sinfonia.c'; else $(CYGPATH_W) '$(srcdir)/backend_sinfonia.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_sinfonia.Tpo $(DEPDIR)/backend_gutenprint-backend_sinfonia.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend_sinfonia.c' object='backend_gutenprint-backend_sinfonia.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backend_gutenprint-backend_sinfonia.obj `if test -f 'backend_sinfonia.c'; then $(CYGPATH_W) 'backend_sinfonia.c'; else $(CYGPATH_W) '$(srcdir)/backend_sinfonia.c'; fi` + backend_gutenprint-backend_common.o: backend_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(backend_gutenprint_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backend_gutenprint-backend_common.o -MD -MP -MF $(DEPDIR)/backend_gutenprint-backend_common.Tpo -c -o backend_gutenprint-backend_common.o `test -f 'backend_common.c' || echo '$(srcdir)/'`backend_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backend_gutenprint-backend_common.Tpo $(DEPDIR)/backend_gutenprint-backend_common.Po @@ -1796,20 +1809,6 @@ recheck: all am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? -test-ppds.log: test-ppds - @p='test-ppds'; \ - b='test-ppds'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) -test-rastertogutenprint.check.log: test-rastertogutenprint.check - @p='test-rastertogutenprint.check'; \ - b='test-rastertogutenprint.check'; \ - $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ - --log-file $$b.log --trs-file $$b.trs \ - $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ - "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ @@ -1931,7 +1930,8 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos2145.Po -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos6145.Po -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos6245.Po - -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po + -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sinfonia.Po + -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sonyupd.Po -rm -f ./$(DEPDIR)/commandtocanon.Po -rm -f ./$(DEPDIR)/commandtoepson.Po -rm -f ./$(DEPDIR)/cups-calibrate.Po @@ -2010,7 +2010,8 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos2145.Po -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos6145.Po -rm -f ./$(DEPDIR)/backend_gutenprint-backend_shinkos6245.Po - -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sonyupdr150.Po + -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sinfonia.Po + -rm -f ./$(DEPDIR)/backend_gutenprint-backend_sonyupd.Po -rm -f ./$(DEPDIR)/commandtocanon.Po -rm -f ./$(DEPDIR)/commandtoepson.Po -rm -f ./$(DEPDIR)/cups-calibrate.Po @@ -2093,7 +2094,8 @@ $(top_builddir)/src/gutenprintui2/libgutenprintui2.la: @BUILD_CUPS_TRUE@@BUILD_LIBUSB_BACKENDS_TRUE@ chmod 700 $(DESTDIR)$(pkglibdir)/backend/backend_gutenprint @BUILD_CUPS_TRUE@@BUILD_LIBUSB_BACKENDS_TRUE@ mv $(DESTDIR)$(pkglibdir)/backend/backend_gutenprint "$(DESTDIR)$(pkglibdir)/backend/gutenprint$(GUTENPRINT_MAJOR_VERSION)$(GUTENPRINT_MINOR_VERSION)+usb" @BUILD_CUPS_TRUE@test-rastertogutenprint: min-pagesize -@BUILD_CUPS_TRUE@test-rastertogutenprint.check: test-rastertogutenprint +@BUILD_CUPS_TRUE@test-rastertogutenprint.test: test-rastertogutenprint +@BUILD_CUPS_TRUE@test-rastertogutenprint.log: test-ppds.log @BUILD_LIBUSB_BACKENDS_TRUE@install-blacklist: @BUILD_LIBUSB_BACKENDS_TRUE@ $(MKDIR_P) $(DESTDIR)$(cupsdata_blacklistdir) @BUILD_LIBUSB_BACKENDS_TRUE@ $(INSTALL_DATA) $(srcdir)/blacklist $(DESTDIR)$(cupsdata_blacklistdir)/net.sf.gimp-print.usb-quirks @@ -2158,7 +2160,7 @@ all-local: $(INSTALL_DATA_LOCAL_DEPS) ppd: ppd-stamp -ppd-stamp: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(top_srcdir)/src/xml/xml-stamp +ppd-stamp: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(top_srcdir)/src/xml/xml-stamp ppd-stamp-pre $(MAKE) ppd-stamp-pre $(MAKE) ppd-stamp-phony touch ppd-stamp @@ -2185,60 +2187,60 @@ ppd-nonls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs:" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) ppd-nonls-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs (all):" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C -a + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C -a $(EXTRA_GENPPD_OPTS) ppd-nonls-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Non-localized PPDs (simplified):" $(MKDIR_P) $(PPD_DIR)/C $(MAKE) ppd-catalog-clean - LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l C -p $(PPD_DIR)/C -s + LC_ALL= LANG= LANGUAGE= $(STP_NONLS_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l C -p $(PPD_DIR)/C -s $(EXTRA_GENPPD_OPTS) ppd-global: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs:" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -a + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -a $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (simplified):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -s + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -s $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N @WHICH_PPDS@ + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N @WHICH_PPDS@ $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all, localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N -a + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N -a $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-global-ln-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @echo "Global PPDs (all, localized numbers for testing):" $(MKDIR_P) $(PPD_DIR)/Global $(MAKE) ppd-catalog - LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -p $(PPD_DIR)/Global -N -s + LC_ALL= LANG= LANGUAGE= $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -p $(PPD_DIR)/Global -N -s $(EXTRA_GENPPD_OPTS) $(MAKE) ppd-catalog-clean ppd-nls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ ppd-nonls @@ -2248,7 +2250,7 @@ ppd-nls: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) -l $$language -p $(PPD_DIR)/$$language; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ -l $$language -p $(PPD_DIR)/$$language $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean @@ -2259,7 +2261,7 @@ ppd-nls-a: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -a; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -a $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean @@ -2270,7 +2272,7 @@ ppd-nls-s: cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ ppd-nonls for language in `$(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -L` ; do \ $(MKDIR_P) $(PPD_DIR)/$$language ; \ echo -n "$$language: " ; \ - LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ $(EXTRA_GENPPD_OPTS) @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -s; \ + LC_ALL=$$language LANG=$$language LANGUAGE=$$language $(STP_ENV) ./cups-genppd.@GUTENPRINT_RELEASE_VERSION@ @WHICH_PPDS@ -l $$language -p $(PPD_DIR)/$$language -s $(EXTRA_GENPPD_OPTS); \ done $(MAKE) ppd-catalog-clean diff --git a/src/cups/README b/src/cups/README deleted file mode 100644 index 5deadb2..0000000 --- a/src/cups/README +++ /dev/null @@ -1,116 +0,0 @@ -README.txt - 11/21/2001 - CUPS Drivers based on Gutenprint ----------------------------------------------------------- - -This file describes the CUPS drivers based on the Gutenprint project. - -Note: to use these drivers you must have CUPS 1.1.9 or higher. We -recommend use of CUPS 1.1.12 or higher. - -All code is Copyright 1997-2001 by Easy Software Products and/or the -Gutenprint project and is provided under the terms of the GNU General -Public License. The licensing details are provided in the file -"LICENSE.txt". - - -INTRODUCTION - -The CUPS drivers contain all of the files needed to support -photo-quality printing on any printer supported by the Gutenprint -project. You can find out more about the Common UNIX Printing System -("CUPS"), an IPP-based printing system for UNIX/Linux, at: - - http://www.cups.org - - -WHY DRIVERS FOR CUPS? - -CUPS is designed from the ground up to support printing to modern -printers. In order to support as many applications as possible, CUPS -provides a PostScript RIP (currently based on GNU GhostScript 5.50) as -well as an image file RIP and many file filters that handle conversion -of files to a format usable by a printer driver. The filter interface -is extensible to support new types of files that can be printed -(e.g. a GNOME metafile, etc.) All of this filtering happens "behind -the scenes" so is transparent to the user. - -In addition, CUPS uses PostScript Printer Description ("PPD") files to -describe printers, allowing applications to see the available printer -features and capabilities easily. The CUPS PPD files add a few -additional attributes to the standard PPD specification to support -printing to non-PS printers. - - -WHAT TOOLS ARE INCLUDED? - -We provide two tools for making CUPS drivers. - -The first is called "cups-calibrate" which allows you to do -super-simple color calibration of your printer drivers. It is an -interactive program that prints several calibration images through -your driver until a final profile is produced. - -The second is called "genppd" which generates PPD files. These PPD -files are created in several languages. The program reads printer -driver information from the Gutenprint driver database and produces a -PPD file for each driver. Normally, users do not have to use this -tool directly; it is run automatically in the build process. - - -WHAT DRIVERS ARE INCLUDED? - -We support all of the Gutenprint drivers supported by the project. The -Canon and EPSON drivers also support simple printer commands to do head -cleaning, test prints, and alignment, as well as an EPSON-specific -backend that provides ink level information to the user. - -The printer drivers in this distribution are so-called "raster" -printer drivers. This means that they receive a stream of images, one -per page, that contain all of the colors, etc. for the printer. The -printer driver then only needs to convert this to the appropriate -printer commands and raster data to get a printed page. - -We also have a new experimental interface for printer commands using -CUPS printer command files - ASCII text files with printer commands in -them. This allows you to do a head cleaning, align the print heads, -etc. - - -WHAT SOFTWARE DO I NEED? - -Currently, CUPS 1.1.9 or higher is required, as is an ANSI C compliant -compiler like GCC. The code has been tested on a number of vendor -compilers and should be quite portable. - - -HOW DO I START USING THESE DRIVERS? - -Please read the README file at top level. - - -WHO DO I CONTACT TO GET HELP? - -For support issues, you should contact -gimp-print-devel@sourceforge.net, the developer mailing list for the -Gutenprint project in general. - -The primary author of this driver is Michael Sweet of Easy Software -Products (mike@easysw.com). Mike is also the main developer for CUPS. -Please don't expect an instant response (or even a response within a -week) as Mike often accumulates a backlog of 100 or more messages each -day. - - -COMMERCIAL SUPPORT - -Easy Software Products provides commercial support for all of -its printing products. Please see our web site for more -information: - - http://www.easysw.com - - -LEGAL STUFF - -CUPS, the Common UNIX Printing System, and the CUPS logo are the -trademark property of Easy Software Products. Please see the -CUPS software license for the terms of its use. diff --git a/src/cups/backend_canonselphy.c b/src/cups/backend_canonselphy.c index 42b3f45..978df0d 100644 --- a/src/cups/backend_canonselphy.c +++ b/src/cups/backend_canonselphy.c @@ -691,15 +691,6 @@ static void canonselphy_cleanup_job(const void *vjob) { free((void*)job); } -static void canonselphy_teardown(void *vctx) { - struct canonselphy_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct canonselphy_ctx *ctx = vctx; @@ -725,8 +716,10 @@ static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, in job contents. Ignore it if it comes through here.. */ i = read(data_fd, rdbuf, 4); if (i != 4) { - if (i == 0) + if (i == 0) { + canonselphy_cleanup_job(job); return CUPS_BACKEND_CANCEL; + } ERROR("Read failed (%d/%d)\n", i, 4); perror("ERROR: Read failed"); canonselphy_cleanup_job(job); @@ -743,8 +736,10 @@ static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, in /* Read the rest of the header.. */ i = read(data_fd, rdbuf + offset, MAX_HEADER - offset); if (i != MAX_HEADER - offset) { - if (i == 0) + if (i == 0) { + canonselphy_cleanup_job(job); return CUPS_BACKEND_CANCEL; + } ERROR("Read failed (%d/%d)\n", i, MAX_HEADER - offset); perror("ERROR: Read failed"); @@ -763,8 +758,8 @@ static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, in } if (printer_type != ctx->type) { - ERROR("Printer/Job mismatch (%d/%d)\n", ctx->type, ctx->printer->type); - free(job); + ERROR("Printer/Job mismatch (%d/%d/%d)\n", ctx->type, ctx->printer->type, printer_type); + canonselphy_cleanup_job(job); return CUPS_BACKEND_CANCEL; } @@ -1161,7 +1156,6 @@ struct dyesub_backend canonselphy_backend = { .cmdline_arg = canonselphy_cmdline_arg, .init = canonselphy_init, .attach = canonselphy_attach, - .teardown = canonselphy_teardown, .read_parse = canonselphy_read_parse, .cleanup_job = canonselphy_cleanup_job, .main_loop = canonselphy_main_loop, diff --git a/src/cups/backend_canonselphyneo.c b/src/cups/backend_canonselphyneo.c index 93f539d..f822912 100644 --- a/src/cups/backend_canonselphyneo.c +++ b/src/cups/backend_canonselphyneo.c @@ -251,15 +251,6 @@ static void selphyneo_cleanup_job(const void *vjob) { free((void*)job); } -static void selphyneo_teardown(void *vctx) { - struct selphyneo_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int selphyneo_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct selphyneo_ctx *ctx = vctx; @@ -547,7 +538,6 @@ struct dyesub_backend canonselphyneo_backend = { .init = selphyneo_init, .attach = selphyneo_attach, .cleanup_job = selphyneo_cleanup_job, - .teardown = selphyneo_teardown, .read_parse = selphyneo_read_parse, .main_loop = selphyneo_main_loop, .query_markers = selphyneo_query_markers, diff --git a/src/cups/backend_common.c b/src/cups/backend_common.c index 09ea078..22e65d4 100644 --- a/src/cups/backend_common.c +++ b/src/cups/backend_common.c @@ -1,7 +1,7 @@ /* * CUPS Backend common code * - * Copyright (c) 2007-2018 Solomon Peachy <pizza@shaftnet.org> + * Copyright (c) 2007-2019 Solomon Peachy <pizza@shaftnet.org> * * The latest version of this program can be found at: * @@ -27,19 +27,19 @@ */ #include "backend_common.h" +#include <errno.h> -#define BACKEND_VERSION "0.88G" +#define BACKEND_VERSION "0.94G" #ifndef URI_PREFIX #error "Must Define URI_PREFIX" #endif -#define NUM_CLAIM_ATTEMPTS 10 - #define URB_XFER_SIZE (64*1024) #define XFER_TIMEOUT 15000 #define USB_SUBCLASS_PRINTER 0x1 #define USB_INTERFACE_PROTOCOL_BIDIR 0x2 +#define USB_INTERFACE_PROTOCOL_IPP 0x4 /* Global Variables */ int dyesub_debug = 0; @@ -48,16 +48,18 @@ int fast_return = 0; int extra_vid = -1; int extra_pid = -1; int extra_type = -1; -int copies = 1; +int ncopies = 1; +int collate = 0; int test_mode = 0; int old_uri = 0; +int quiet = 0; static int max_xfer_size = URB_XFER_SIZE; static int xfer_timeout = XFER_TIMEOUT; /* Support Functions */ -static int backend_claim_interface(struct libusb_device_handle *dev, int iface, - int num_claim_attempts) +int backend_claim_interface(struct libusb_device_handle *dev, int iface, + int num_claim_attempts) { int ret; do { @@ -300,7 +302,7 @@ int send_data(struct libusb_device_handle *dev, uint8_t endp, } if (ret < 0) { - ERROR("Failure to send data to printer (libusb error %d: (%d/%d to 0x%02x))\n", ret, num, len, endp); + ERROR("Failure to send data to printer (libusb error %d: (%d/%d to 0x%02x))\n", ret, num, len2, endp); return ret; } len -= num; @@ -435,8 +437,16 @@ static int probe_device(struct libusb_device *device, continue; } -#if 0 - // Make sure it's a printer class device that supports bidir comms (XXX Is this always true?) +#if 1 + /* Explicitly exclude IPP-over-USB interfaces */ + if (desc->bDeviceClass == LIBUSB_CLASS_PER_INTERFACE && + config->interface[iface].altsetting[altset].bInterfaceClass == LIBUSB_CLASS_PRINTER && + config->interface[iface].altsetting[altset].bInterfaceSubClass == USB_SUBCLASS_PRINTER && + config->interface[iface].altsetting[altset].bInterfaceProtocol == USB_INTERFACE_PROTOCOL_IPP) { + continue; + } +#else + // Make sure it's a printer class device that supports bidir comms (XXX Is this necessarily true?) if (desc->bDeviceClass == LIBUSB_CLASS_PRINTER || (desc->bDeviceClass == LIBUSB_CLASS_PER_INTERFACE && config->interface[iface].altsetting[altset].bInterfaceClass == LIBUSB_CLASS_PRINTER && @@ -544,9 +554,9 @@ candidate: if (!descr || !strlen(descr)) { /* Last-ditch, generate */ char *product2 = url_decode(product); char *manuf3 = url_decode(manuf); - descr = malloc(256); + descr = malloc(514); /* 256 + 256 + 1 + 1 */ if (!descr) { - ERROR("Memory allocation failure (%d bytes)\n", 256); + ERROR("Memory allocation failure (%d bytes)\n", 514); if (manuf3) free(manuf3); if (product2) @@ -554,7 +564,7 @@ candidate: return -1; } - sprintf(descr, "%s %s", manuf3, product2); + snprintf(descr, 514, "%s %s", manuf3, product2); free(product2); free(manuf3); } @@ -656,7 +666,16 @@ abort: return found; } -extern struct dyesub_backend updr150_backend; +void generic_teardown(void *vctx) +{ + if (!vctx) + return; + + free(vctx); +} + +extern struct dyesub_backend sonyupd_backend; +extern struct dyesub_backend sonyupdneo_backend; extern struct dyesub_backend kodak6800_backend; extern struct dyesub_backend kodak605_backend; extern struct dyesub_backend kodak1400_backend; @@ -683,7 +702,7 @@ static struct dyesub_backend *backends[] = { &shinkos2145_backend, &shinkos6145_backend, &shinkos6245_backend, - &updr150_backend, + &sonyupd_backend, &mitsu70x_backend, &mitsud90_backend, &mitsu9550_backend, @@ -812,7 +831,7 @@ static int query_markers(struct dyesub_backend *backend, void *ctx, int full) void print_license_blurb(void) { const char *license = "\n\ -Copyright 2007-2018 Solomon Peachy <pizza AT shaftnet DOT org>\n\ +Copyright 2007-2019 Solomon Peachy <pizza AT shaftnet DOT org>\n\ \n\ This program is free software; you can redistribute it and/or modify it\n\ under the terms of the GNU General Public License as published by the Free\n\ @@ -848,13 +867,13 @@ void print_help(char *argv0, struct dyesub_backend *backend) if (!backend) { int i; DEBUG("Environment variables:\n"); - DEBUG(" DYESUB_DEBUG EXTRA_PID EXTRA_VID EXTRA_TYPE BACKEND SERIAL OLD_URI_SCHEME\n"); + DEBUG(" DYESUB_DEBUG EXTRA_PID EXTRA_VID EXTRA_TYPE BACKEND SERIAL OLD_URI_SCHEME BACKEND_QUIET\n"); DEBUG("CUPS Usage:\n"); DEBUG("\tDEVICE_URI=someuri %s job user title num-copies options [ filename ]\n", URI_PREFIX); DEBUG("\n"); DEBUG("Standalone Usage:\n"); DEBUG("\t%s\n", URI_PREFIX); - DEBUG(" [ -D ] [ -G ] [ -f ]\n"); + DEBUG(" [ -D ] [ -G ] [ -f ] [ -v ]\n"); DEBUG(" [ backend_specific_args ] \n"); DEBUG(" [ -d copies ] \n"); DEBUG(" [ - | infile ] \n"); @@ -964,14 +983,9 @@ int main (int argc, char **argv) char *use_serno = NULL; int printer_type; - DEBUG("Multi-Call Dye-sublimation CUPS Backend version %s\n", - BACKEND_VERSION); - DEBUG("Copyright 2007-2018 Solomon Peachy\n"); - DEBUG("This free software comes with ABSOLUTELY NO WARRANTY! \n"); - DEBUG("Licensed under the GNU GPL. Run with '-G' for more details.\n"); - DEBUG("\n"); - - /* First pass at cmdline parsing */ + /* Handle environment variables */ + if (getenv("BACKEND_QUIET")) + quiet = atoi(getenv("BACKEND_QUIET")); if (getenv("DYESUB_DEBUG")) dyesub_debug = atoi(getenv("DYESUB_DEBUG")); if (getenv("EXTRA_PID")) @@ -998,6 +1012,13 @@ int main (int argc, char **argv) exit(1); } + DEBUG("Multi-Call Dye-sublimation CUPS Backend version %s\n", + BACKEND_VERSION); + DEBUG("Copyright 2007-2019 Solomon Peachy\n"); + DEBUG("This free software comes with ABSOLUTELY NO WARRANTY! \n"); + DEBUG("Licensed under the GNU GPL. Run with '-G' for more details.\n"); + DEBUG("\n"); + use_serno = getenv("SERIAL"); uri = getenv("DEVICE_URI"); /* CUPS backend mode! */ type = getenv("FINAL_CONTENT_TYPE"); /* CUPS content type -- ie raster or command */ @@ -1012,7 +1033,7 @@ int main (int argc, char **argv) if (argv[base]) jobid = atoi(argv[base]); if (argv[base + 3]) - copies = atoi(argv[base + 3]); + ncopies = atoi(argv[base + 3]); if (argc > 6) fname = argv[base + 5]; else @@ -1216,7 +1237,13 @@ bypass: if (!fname) { if (uri) - fprintf(stderr, "ERROR: No input file specified\n"); + ERROR("ERROR: No input file specified\n"); + goto done_claimed; + } + + if (ncopies < 1) { + ERROR("ERROR: need to have at least 1 copy!\n"); + ret = CUPS_BACKEND_FAILED; goto done_claimed; } @@ -1226,7 +1253,7 @@ bypass: if (data_fd < 0) { perror("ERROR:Can't open input file"); ret = CUPS_BACKEND_FAILED; - goto done; + goto done_claimed; } } @@ -1242,7 +1269,7 @@ bypass: if (i < 0) { perror("ERROR:Can't open input"); ret = CUPS_BACKEND_FAILED; - goto done; + goto done_claimed; } /* Ignore SIGPIPE */ @@ -1250,7 +1277,7 @@ bypass: signal(SIGTERM, sigterm_handler); /* Time for the main processing loop */ - INFO("Printing started (%d copies)\n", copies); + INFO("Printing started (%d copies)\n", ncopies); /* See if it's a CUPS command stream, and if yes, handle it! */ if (type && !strcmp("application/vnd.cups-command", type)) @@ -1262,7 +1289,7 @@ bypass: newpage: /* Read in data */ - if ((ret = backend->read_parse(backend_ctx, &job, data_fd, copies))) { + if ((ret = backend->read_parse(backend_ctx, &job, data_fd, ncopies))) { if (current_page) goto done_multiple; else @@ -1276,11 +1303,11 @@ newpage: /* Create our own joblist if necessary */ if (!(backend->flags & BACKEND_FLAG_JOBLIST)) { - struct dyesub_joblist *list = dyesub_joblist_create(backend, backend_ctx); + struct dyesub_joblist *jlist = dyesub_joblist_create(backend, backend_ctx); if (!list) goto done_claimed; - dyesub_joblist_addjob(list, job); - job = list; + dyesub_joblist_addjob(jlist, job); + job = jlist; } /* Dump the full marker dump */ @@ -1303,7 +1330,7 @@ newpage: /* Log the completed page */ if (!uri) - PAGE("%d %d\n", current_page, copies); + PAGE("%d %d\n", current_page, ncopies); /* Dump a marker status update */ ret = query_markers(backend, backend_ctx, !current_page); @@ -1320,7 +1347,7 @@ done_multiple: /* Done printing, log the total number of pages */ if (!uri) - PAGE("total %d\n", current_page * copies); + PAGE("total %d\n", current_page * ncopies); ret = CUPS_BACKEND_OK; done_claimed: @@ -1333,7 +1360,10 @@ done_close: done: if (backend && backend_ctx) { - backend->teardown(backend_ctx); + if (backend->teardown) + backend->teardown(backend_ctx); + else + generic_teardown(backend_ctx); // STATE("-org.gutenprint-attached-to-device"); } @@ -1354,7 +1384,7 @@ void dump_markers(struct marker *markers, int marker_count, int full) ATTR("marker-colors="); for (i = 0 ; i < marker_count; i++) { - DEBUG2(markers[i].color); + DEBUG2("%s", markers[i].color); if ((i+1) < marker_count) DEBUG2(","); } @@ -1433,6 +1463,35 @@ minimal: } } +int dyesub_read_file(char *filename, void *databuf, int datalen, + int *actual_len) +{ + int len; + int fd = open(filename, O_RDONLY); + + if (fd < 0) { + ERROR("Unable to open '%s'\n", filename); + return CUPS_BACKEND_FAILED; + } + len = read(fd, databuf, datalen); + if (len < 0) { + ERROR("Bad Read! (%d/%d)\n", len, errno); + close(fd); + return CUPS_BACKEND_FAILED; + } + if (!actual_len && (datalen != len)) { + ERROR("Read mismatch (%d vs %d)\n", len, datalen); + close(fd); + return CUPS_BACKEND_FAILED; + } + close(fd); + + if (actual_len) + *actual_len = len; + + return CUPS_BACKEND_OK; +} + uint16_t uint16_to_packed_bcd(uint16_t val) { uint16_t bcd; @@ -1481,7 +1540,11 @@ struct dyesub_joblist *dyesub_joblist_create(struct dyesub_backend *backend, voi list->backend = backend; list->ctx = ctx; list->num_entries = 0; - list->copies = 1; + + if (collate) + list->copies = ncopies; + else + list->copies = 1; return list; } diff --git a/src/cups/backend_common.h b/src/cups/backend_common.h index 3fd58db..2decab2 100644 --- a/src/cups/backend_common.h +++ b/src/cups/backend_common.h @@ -1,7 +1,7 @@ /* * CUPS Backend common code * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * The latest version of this program can be found at: * @@ -43,21 +43,40 @@ #define __BACKEND_COMMON_H #define STR_LEN_MAX 64 -#define STATE( ... ) fprintf(stderr, "STATE: " __VA_ARGS__ ) -#define ATTR( ... ) fprintf(stderr, "ATTR: " __VA_ARGS__ ) -#define PAGE( ... ) fprintf(stderr, "PAGE: " __VA_ARGS__ ) -#define DEBUG( ... ) fprintf(stderr, "DEBUG: " __VA_ARGS__ ) -#define DEBUG2( ... ) fprintf(stderr, __VA_ARGS__ ) -#define INFO( ... ) fprintf(stderr, "INFO: " __VA_ARGS__ ) -#define WARNING( ... ) fprintf(stderr, "WARNING: " __VA_ARGS__ ) +#define STATE( ... ) do { if (!quiet) fprintf(stderr, "STATE: " __VA_ARGS__ ); } while(0) +#define ATTR( ... ) do { if (!quiet) fprintf(stderr, "ATTR: " __VA_ARGS__ ); } while(0) +#define PAGE( ... ) do { if (!quiet) fprintf(stderr, "PAGE: " __VA_ARGS__ ); } while(0) +#define DEBUG( ... ) do { if (!quiet) fprintf(stderr, "DEBUG: " __VA_ARGS__ ); } while(0) +#define DEBUG2( ... ) do { if (!quiet) fprintf(stderr, __VA_ARGS__ ); } while(0) +#define INFO( ... ) do { if (!quiet) fprintf(stderr, "INFO: " __VA_ARGS__ ); } while(0) +#define WARNING( ... ) do { fprintf(stderr, "WARNING: " __VA_ARGS__ ); } while(0) #define ERROR( ... ) do { fprintf(stderr, "ERROR: " __VA_ARGS__ ); sleep(1); } while (0) #if (__BYTE_ORDER == __LITTLE_ENDIAN) +#define le64_to_cpu(__x) __x #define le32_to_cpu(__x) __x #define le16_to_cpu(__x) __x #define be16_to_cpu(__x) ntohs(__x) #define be32_to_cpu(__x) ntohl(__x) +#define be64_to_cpu(__x) ((__uint64_t)( \ + (((__uint64_t)(__x) & (__uint64_t)0x00000000000000ffULL) << 56) | \ + (((__uint64_t)(__x) & (__uint64_t)0x000000000000ff00ULL) << 40) | \ + (((__uint64_t)(__x) & (__uint64_t)0x0000000000ff0000ULL) << 24) | \ + (((__uint64_t)(__x) & (__uint64_t)0x00000000ff000000ULL) << 8) | \ + (((__uint64_t)(__x) & (__uint64_t)0x000000ff00000000ULL) >> 8) | \ + (((__uint64_t)(__x) & (__uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (((__uint64_t)(__x) & (__uint64_t)0x00ff000000000000ULL) >> 40) | \ + (((__uint64_t)(__x) & (__uint64_t)0xff00000000000000ULL) >> 56))) #else +#define le64_to_cpu(__x) ((__uint64_t)( \ + (((__uint64_t)(__x) & (__uint64_t)0x00000000000000ffULL) << 56) | \ + (((__uint64_t)(__x) & (__uint64_t)0x000000000000ff00ULL) << 40) | \ + (((__uint64_t)(__x) & (__uint64_t)0x0000000000ff0000ULL) << 24) | \ + (((__uint64_t)(__x) & (__uint64_t)0x00000000ff000000ULL) << 8) | \ + (((__uint64_t)(__x) & (__uint64_t)0x000000ff00000000ULL) >> 8) | \ + (((__uint64_t)(__x) & (__uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (((__uint64_t)(__x) & (__uint64_t)0x00ff000000000000ULL) >> 40) | \ + (((__uint64_t)(__x) & (__uint64_t)0xff00000000000000ULL) >> 56))) #define le32_to_cpu(x) \ ({ \ uint32_t __x = (x); \ @@ -74,6 +93,7 @@ (((uint16_t)(__x) & (uint16_t)0x00ff) << 8) | \ (((uint16_t)(__x) & (uint16_t)0xff00) >> 8))); \ }) +#define be64_to_cpu(__x) __x #define be32_to_cpu(__x) __x #define be16_to_cpu(__x) __x #endif @@ -132,7 +152,16 @@ enum { P_DNP_DSRX1 = 41, P_FUJI_ASK300 = 42, P_MAGICARD = 43, - P_SONY_UPD89x = 44, + P_SONY_UPD895 = 44, + P_SONY_UPD897 = 45, + P_SONY_UPD898 = 46, + P_SONY_UPCR20L = 47, + P_SONY_UPDR80 = 48, + P_KODAK_8810 = 49, + P_KODAK_7000 = 50, + P_KODAK_701X = 51, + P_KODAK_6900 = 52, + P_SHINKO_S2245 = 53, P_END, }; @@ -195,9 +224,19 @@ void dump_markers(struct marker *markers, int marker_count, int full); void print_license_blurb(void); void print_help(char *argv0, struct dyesub_backend *backend); +int dyesub_read_file(char *filename, void *databuf, int datalen, + int *actual_len); + uint16_t uint16_to_packed_bcd(uint16_t val); uint32_t packed_bcd_to_uint32(char *in, int len); +void generic_teardown(void *vctx); + +/* USB enumeration and attachment */ +#define NUM_CLAIM_ATTEMPTS 10 +int backend_claim_interface(struct libusb_device_handle *dev, int iface, + int num_claim_attempts); + /* Job list manipulation */ struct dyesub_joblist *dyesub_joblist_create(struct dyesub_backend *backend, void *ctx); int dyesub_joblist_addjob(struct dyesub_joblist *list, const void *job); @@ -211,8 +250,10 @@ extern int fast_return; extern int extra_vid; extern int extra_pid; extern int extra_type; -extern int copies; +extern int ncopies; +extern int collate; extern int test_mode; +extern int quiet; enum { TEST_MODE_NONE = 0, @@ -236,10 +277,10 @@ extern struct dyesub_backend BACKEND; #define CUPS_BACKEND_RETRY_CURRENT 7 /* Retry immediately */ /* Argument processing */ -#define GETOPT_LIST_GLOBAL "d:DfGh" +#define GETOPT_LIST_GLOBAL "d:DfGhv" #define GETOPT_PROCESS_GLOBAL \ case 'd': \ - copies = atoi(optarg); \ + ncopies = atoi(optarg); \ break; \ case 'D': \ dyesub_debug++; \ @@ -252,6 +293,9 @@ extern struct dyesub_backend BACKEND; exit(0); \ case 'h': \ print_help(argv[0], &BACKEND); \ - exit(0); + exit(0); \ + case 'v': \ + quiet++; \ + break; #endif /* __BACKEND_COMMON_H */ diff --git a/src/cups/backend_dnpds40.c b/src/cups/backend_dnpds40.c index b9ed3e4..c029bca 100644 --- a/src/cups/backend_dnpds40.c +++ b/src/cups/backend_dnpds40.c @@ -1,7 +1,7 @@ /* * Citizen / DNP Photo Printer CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * Development of this backend was sponsored by: * @@ -68,6 +68,7 @@ struct dnpds40_printjob { int printspeed; int can_rewind; int buf_needed; + int cut_paper; }; struct dnpds40_ctx { @@ -86,6 +87,7 @@ struct dnpds40_ctx { /* State */ uint32_t media; uint32_t duplex_media; + int duplex_media_status; uint16_t media_count_new; uint32_t last_multicut; @@ -95,7 +97,8 @@ struct dnpds40_ctx { int correct_count; int needs_mlot; - struct marker marker; + struct marker marker[2]; + int marker_count; /* Printer capabilities */ uint32_t native_width; @@ -175,7 +178,6 @@ struct dnpds40_cmd { #define MULTICUT_A4 41 #define MULTICUT_A4x5X2 43 - #define MULTICUT_S_SIMPLEX 100 #define MULTICUT_S_FRONT 200 #define MULTICUT_S_BACK 300 @@ -195,31 +197,14 @@ struct dnpds40_cmd { #define min(__x, __y) ((__x) < (__y)) ? __x : __y -/* Legacy CW-01 spool file support */ -struct cw01_spool_hdr { - uint8_t type; /* 0x00 -> 0x06 */ - uint8_t res; /* vertical resolution; 0x00 == 334dpi, 0x01 == 600dpi */ - uint8_t copies; /* number of prints */ - uint8_t null0; - uint32_t plane_len; /* LE */ - uint8_t null1[4]; -}; - -#define DPI_334 0 -#define DPI_600 1 - -#define TYPE_DSC 0 -#define TYPE_L 1 -#define TYPE_PC 2 -#define TYPE_2DSC 3 -#define TYPE_3L 4 -#define TYPE_A5 5 -#define TYPE_A6 6 -/* Legacy CW-01 spool file support */ +/* Legacy spool file support */ +static int legacy_cw01_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data); +static int legacy_dnp_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data); +static int legacy_dnp620_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data); +static int legacy_dnp820_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data); -static int cw01_read_parse(struct dnpds40_printjob *job, int data_fd, - struct cw01_spool_hdr *hdr, int read_data); static void dnpds40_cleanup_job(const void *vjob); +static int dnpds40_query_markers(void *vctx, struct marker **markers, int *count); #define JOB_EQUIV(__x) if (job1->__x != job2->__x) goto done @@ -419,7 +404,7 @@ static void dnpds40_cleanup_string(char *start, int len) } } -static char *dnpds40_printer_type(int type) +static const char *dnpds40_printer_type(int type) { switch(type) { case P_DNP_DS40: return "DS40"; @@ -435,7 +420,7 @@ static char *dnpds40_printer_type(int type) return "Unknown"; } -static char *dnpds40_media_types(int media) +static const char *dnpds40_media_types(int media) { switch (media) { case 100: return "UNKNOWN100"; // seen in driver dumps @@ -455,7 +440,7 @@ static char *dnpds40_media_types(int media) return "Unknown type"; } -static char *dnpds620_media_extension_code(int media) +static const char *dnpds620_media_extension_code(int media) { switch (media) { case 00: return "Normal Paper"; @@ -468,7 +453,7 @@ static char *dnpds620_media_extension_code(int media) return "Unknown type"; } -static char *dnpds820_media_subtypes(int media) +static const char *dnpds820_media_subtypes(int media) { switch (media) { case 0001: return "SD"; @@ -480,7 +465,7 @@ static char *dnpds820_media_subtypes(int media) return "Unknown type"; } -static char *dnpds80_duplex_media_types(int media) +static const char *dnpds80_duplex_media_types(int media) { switch (media) { case 100: return "8x10.75"; @@ -492,7 +477,22 @@ static char *dnpds80_duplex_media_types(int media) return "Unknown type"; } -static char *dnpds80_duplex_statuses(int status) +#define DUPLEX_UNIT_PAPER_NONE 0 +#define DUPLEX_UNIT_PAPER_PROTECTIVE 1 +#define DUPLEX_UNIT_PAPER_PRESENT 2 + +static const char *dnpds80_duplex_paper_status(int media) +{ + switch (media) { + case DUPLEX_UNIT_PAPER_NONE: return "No Paper"; + case DUPLEX_UNIT_PAPER_PROTECTIVE: return "Protective Sheet"; + case DUPLEX_UNIT_PAPER_PRESENT: return "Cut Paper Present"; + default: + return "Unknown"; + } +} + +static const char *dnpds80_duplex_statuses(int status) { switch (status) { case 5000: return "No Error"; @@ -564,7 +564,7 @@ static char *dnpds80_duplex_statuses(int status) return "Unknown Duplexer Error"; } -static char *dnpds40_statuses(int status) +static const char *dnpds40_statuses(int status) { if (status >= 5000 && status <= 5999) return dnpds80_duplex_statuses(status); @@ -746,6 +746,41 @@ static int dnpds40_query_mqty(struct dnpds40_ctx *ctx) return count; } +static int dnpds80dx_query_paper(struct dnpds40_ctx *ctx) +{ + struct dnpds40_cmd cmd; + uint8_t *resp; + int len = 0; + + /* Query Duplex Media Info */ + dnpds40_build_cmd(&cmd, "INFO", "UNIT_CUT_PAPER", 0); + + resp = dnpds40_resp_cmd(ctx, &cmd, &len); + if (resp) { + char tmp[5]; + char status; + + dnpds40_cleanup_string((char*)resp, len); + + memcpy(tmp, resp + 4, 4); + status = tmp[3]; + tmp[3] = '0'; + tmp[4] = 0; + + ctx->duplex_media = atoi(tmp); + + tmp[0] = tmp[1] = tmp[2] = '0'; + tmp[3] = status; + ctx->duplex_media_status = atoi(tmp); + + free(resp); + } else { + return CUPS_BACKEND_FAILED; + } + + return CUPS_BACKEND_OK; +} + static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, int type, uint8_t endp_up, uint8_t endp_down, uint8_t jobid) { @@ -819,32 +854,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, int type } if (ctx->type == P_DNP_DS80D) { - struct dnpds40_cmd cmd; - uint8_t *resp; - int len = 0; - - /* Query Duplex Media Info */ - dnpds40_build_cmd(&cmd, "INFO", "CUT_PAPER", 0); - - resp = dnpds40_resp_cmd(ctx, &cmd, &len); - if (resp) { - char tmp[5]; - - dnpds40_cleanup_string((char*)resp, len); - - memcpy(tmp, resp + 4, 4); - tmp[4] = 0; - - ctx->duplex_media = atoi(tmp); - - /* Subtract out the paper status */ - if (ctx->duplex_media & 3) - ctx->duplex_media -= (ctx->duplex_media & 3); - - free(resp); - } else { + if (dnpds80dx_query_paper(ctx)) return CUPS_BACKEND_FAILED; - } } #if (defined(DNP_ONLY) || defined(CITIZEN_ONLY)) @@ -948,7 +959,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, int type break; case P_DNP_DS620: ctx->native_width = 1920; - ctx->max_height = 5480; + ctx->max_height = 5604; ctx->correct_count = 1; ctx->supports_counterp = 1; ctx->supports_matte = 1; @@ -1153,10 +1164,19 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, int type } /* Fill out marker structure */ - ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = dnpds40_media_types(ctx->media); - ctx->marker.levelmax = ctx->media_count_new; - ctx->marker.levelnow = -2; + ctx->marker[0].color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker[0].name = dnpds40_media_types(ctx->media); + ctx->marker[0].levelmax = ctx->media_count_new; + ctx->marker[0].levelnow = -2; + ctx->marker_count = 1; + + if (ctx->type == P_DNP_DS80D) { + ctx->marker[1].color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker[1].name = dnpds80_duplex_media_types(ctx->duplex_media); + ctx->marker[1].levelmax = ctx->marker[0].levelmax/2; + ctx->marker[1].levelnow = -2; + ctx->marker_count++; + } return CUPS_BACKEND_OK; } @@ -1230,6 +1250,7 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co job->databuf = malloc(MAX_PRINTJOB_LEN); if (!job->databuf) { + dnpds40_cleanup_job(job); ERROR("Memory allocation failure!\n"); return CUPS_BACKEND_RETRY_CURRENT; } @@ -1250,29 +1271,36 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co return CUPS_BACKEND_CANCEL; } - if (job->databuf[job->datalen + 0] != 0x1b || - job->databuf[job->datalen + 1] != 0x50) { - struct cw01_spool_hdr hdr; - /* See if it's the "classic" CW01 header */ - memcpy(&hdr, job->databuf + job->datalen, sizeof(hdr)); - hdr.plane_len = le32_to_cpu(hdr.plane_len); - - if (hdr.type > 0x06 || - hdr.res > 0x01 || - hdr.null1[0] || hdr.null1[1] || hdr.null1[2] || hdr.null1[3]) { - ERROR("Unrecognized header data format @%d!\n", job->datalen); - dnpds40_cleanup_job(job); - } else { - job->dpi = (hdr.res == DPI_600) ? 600 : 334; - i = cw01_read_parse(job, data_fd, &hdr, i); - if (i == CUPS_BACKEND_OK) + /* Special case handling for beginning of job */ + if (job->datalen == 0) { + /* See if job lacks the standard ESC-P start sequence */ + if (job->databuf[job->datalen + 0] != 0x1b || + job->databuf[job->datalen + 1] != 0x50) { + switch(ctx->type) { + case P_CITIZEN_CW01: + i = legacy_cw01_read_parse(job, data_fd, i); + break; + case P_DNP_DS620: + i = legacy_dnp620_read_parse(job, data_fd, i); + break; + case P_DNP_DS820: + i = legacy_dnp820_read_parse(job, data_fd, i); + break; + case P_DNP_DSRX1: + case P_DNP_DS40: + case P_DNP_DS80: + case P_DNP_DS80D: + default: + i = legacy_dnp_read_parse(job, data_fd, i); + break; + } + + if (i == CUPS_BACKEND_OK) { goto parsed; - else { - dnpds40_cleanup_job(job); - return i; } + dnpds40_cleanup_job(job); + return i; } - return CUPS_BACKEND_CANCEL; } /* Parse out length of data chunk, if any */ @@ -1285,7 +1313,7 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co i = read(data_fd, job->databuf + job->datalen + sizeof(struct dnpds40_cmd), remain); if (i < 0) { - ERROR("Data Read Error: %d (%d/%d @%d)\n", i, remain, j, job->datalen); + ERROR("Data Read Error: %d (%d/%d @%d/%d)\n", i, remain, j, job->datalen,MAX_PRINTJOB_LEN); dnpds40_cleanup_job(job); return i; } @@ -1372,7 +1400,11 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co case 11808: job->dpi = 300; break; + case 13146: + job->dpi = 334; + break; case 23615: + case 23616: job->dpi = 600; break; default: @@ -1439,7 +1471,7 @@ parsed: /* And sanity-check whatever value is there */ if (job->printspeed == 0 && job->dpi == 600) { job->printspeed = 1; - } else if (job->printspeed == 1 && job->dpi == 300) { + } else if (job->printspeed >= 1 && job->dpi == 300) { job->printspeed = 0; } @@ -1455,11 +1487,14 @@ parsed: } /* Only DS80D supports Cut Paper types */ - if (job->multicut > 100 && - ctx->type != P_DNP_DS80D) { - ERROR("Only DS80D supports cut-paper sizes!\n"); - dnpds40_cleanup_job(job); - return CUPS_BACKEND_CANCEL; + if (job->multicut > 100) { + if ( ctx->type == P_DNP_DS80D) { + job->cut_paper = 1; + } else { + ERROR("Only DS80D supports cut-paper sizes!\n"); + dnpds40_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } } /* Figure out the number of buffers we need. */ @@ -1887,12 +1922,16 @@ top: { /* Figure out remaining native prints */ - ctx->marker.levelnow = dnpds40_query_mqty(ctx); - if (ctx->marker.levelnow < 0) + if (dnpds40_query_markers(ctx, NULL, NULL)) return CUPS_BACKEND_FAILED; - dump_markers(&ctx->marker, 1, 0); + if (ctx->marker[0].levelnow < 0) + return CUPS_BACKEND_FAILED; + dump_markers(ctx->marker, ctx->marker_count, 0); - count = ctx->marker.levelnow; // For logic below. + // For logic below. + count = ctx->marker[0].levelnow; + if (job->cut_paper && count > ctx->marker[1].levelnow) + count = ctx->marker[1].levelnow; /* See if we can rewind to save media */ if (job->can_rewind && ctx->supports_rewind) { @@ -1944,6 +1983,13 @@ top: } } + /* Work around a bug in older gutenprint releases. */ + if (ctx->last_multicut >= 200 && ctx->last_multicut < 300 && + multicut >= 200 && multicut < 300) { + WARNING("Bogus multicut value for duplex page, correcting\n"); + multicut += 100; + } + /* Store our last multicut state */ ctx->last_multicut = multicut; @@ -1995,7 +2041,7 @@ top: /* Program in the multicut setting, if one exists */ if (multicut) { - snprintf(buf, sizeof(buf), "%08u", multicut); + snprintf(buf, sizeof(buf), "%08d", multicut); dnpds40_build_cmd(&cmd, "IMAGE", "MULTICUT", 8); if ((ret = dnpds40_do_cmd(ctx, &cmd, (uint8_t*)buf, 8))) return CUPS_BACKEND_FAILED; @@ -2046,26 +2092,9 @@ top: } /* Figure out remaining native prints */ - dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0); - - resp = dnpds40_resp_cmd(ctx, &cmd, &len); - if (!resp) + if (dnpds40_query_markers(ctx, NULL, NULL)) return CUPS_BACKEND_FAILED; - - dnpds40_cleanup_string((char*)resp, len); - - count = atoi((char*)resp+4); - free(resp); - - if (count) { - /* Old-sk00l models report one less than they should */ - if (!ctx->correct_count) - count++; - - count -= ctx->mediaoffset; - } - ctx->marker.levelnow = count; - dump_markers(&ctx->marker, 1, 0); + dump_markers(ctx->marker, ctx->marker_count, 0); } /* Clean up */ @@ -2528,6 +2557,7 @@ static int dnpds40_get_status(struct dnpds40_ctx *ctx) count = atoi((char*)resp); INFO("Duplexer Status: %s\n", dnpds80_duplex_statuses(count)); + INFO("Duplexer Media Status: %s\n", dnpds80_duplex_paper_status(ctx->duplex_media_status)); free(resp); } @@ -2589,8 +2619,10 @@ static int dnpds40_get_status(struct dnpds40_ctx *ctx) } /* Report Cut Media */ - if (ctx->type == P_DNP_DS80D) - INFO("Duplex Media Type: %s\n", dnpds80_duplex_media_types(ctx->media)); + if (ctx->type == P_DNP_DS80D) { + INFO("Duplex Media Type: %s\n", dnpds80_duplex_media_types(ctx->duplex_media)); + INFO("Duplexer Media Status: %s\n", dnpds80_duplex_paper_status(ctx->duplex_media_status)); + } if (ctx->media_count_new) INFO("Native Prints Available on New Media: %u\n", ctx->media_count_new); @@ -2888,18 +2920,18 @@ static int dnpds40_cmdline_arg(void *vctx, int argc, char **argv) j = dnpds40_get_sensors(ctx); break; case 'k': { - int time = atoi(optarg); + int sleeptime = atoi(optarg); if (!ctx->supports_standby) { ERROR("Printer does not support standby\n"); j = -1; break; } - if (time < 0 || time > 99) { + if (sleeptime < 0 || sleeptime > 99) { ERROR("Value out of range (0-99)"); j = -1; break; } - j = dnpds620_standby_mode(ctx, time); + j = dnpds620_standby_mode(ctx, sleeptime); break; } case 'K': { @@ -2979,13 +3011,32 @@ static int dnpds40_query_markers(void *vctx, struct marker **markers, int *count { struct dnpds40_ctx *ctx = vctx; - *markers = &ctx->marker; - *count = 1; + if (markers) + *markers = ctx->marker; + if (count) + *count = ctx->marker_count; + + ctx->marker[0].levelnow = dnpds40_query_mqty(ctx); - ctx->marker.levelnow = dnpds40_query_mqty(ctx); - if (ctx->marker.levelnow < 0) + if (ctx->marker[0].levelnow < 0) return CUPS_BACKEND_FAILED; + if (ctx->type == P_DNP_DS80D) { + if (dnpds80dx_query_paper(ctx)) + return CUPS_BACKEND_FAILED; + switch (ctx->duplex_media_status) { + case DUPLEX_UNIT_PAPER_NONE: + ctx->marker[1].levelnow = 0; + break; + case DUPLEX_UNIT_PAPER_PROTECTIVE: + ctx->marker[1].levelnow = -1; + break; + case DUPLEX_UNIT_PAPER_PRESENT: + ctx->marker[1].levelnow = -3; + break; + } + } + return CUPS_BACKEND_OK; } @@ -3019,7 +3070,7 @@ static const char *dnpds40_prefixes[] = { /* Exported */ struct dyesub_backend dnpds40_backend = { .name = "DNP DS-series / Citizen C-series", - .version = "0.109", + .version = "0.117", .uri_prefixes = dnpds40_prefixes, .flags = BACKEND_FLAG_JOBLIST, .cmdline_usage = dnpds40_cmdline, @@ -3046,25 +3097,29 @@ struct dyesub_backend dnpds40_backend = { } }; -/* Legacy CW-01 spool file support */ - -static int cw01_read_parse(struct dnpds40_printjob *job, int data_fd, - struct cw01_spool_hdr *hdr, int read_data) +/* Windows spool file support */ +static int legacy_spool_helper(struct dnpds40_printjob *job, int data_fd, + int read_data, int hdrlen, uint32_t plane_len, + int parse_dpi) { + uint8_t *buf; + uint8_t bmp_hdr[14]; int i, remain; uint32_t j; - uint8_t *buf; - uint8_t plane_hdr[14]; - remain = hdr->plane_len * 3; + /* Allocate a temp processing buffer */ + remain = plane_len * 3; buf = malloc(remain); if (!buf) { ERROR("Memory allocation failure!\n"); return CUPS_BACKEND_RETRY_CURRENT; } - j = read_data - sizeof(*hdr); - memcpy(buf, job->databuf, j); + + /* Copy over the post-jobhdr crap into our processing buffer */ + j = read_data - hdrlen; + memcpy(buf, job->databuf + hdrlen, j); remain -= j; + /* Read in the remaining spool data */ while (remain) { i = read(data_fd, buf + j, remain); @@ -3078,58 +3133,67 @@ static int cw01_read_parse(struct dnpds40_printjob *job, int data_fd, j += i; } - /* Generate plane header (same for all planes) */ - j = cpu_to_le32(hdr->plane_len) + 24; - memset(plane_hdr, 0, sizeof(plane_hdr)); - plane_hdr[0] = 0x42; - plane_hdr[1] = 0x4d; - memcpy(plane_hdr + 2, &j, sizeof(j)); - plane_hdr[10] = 0x40; - plane_hdr[11] = 0x04; + if (parse_dpi) { + /* Parse out Y DPI */ + memcpy(&j, buf + 28, sizeof(j)); + j = le32_to_cpu(j); + switch(j) { + case 11808: + job->dpi = 300; + break; + case 23615: + case 23616: + job->dpi = 600; + break; + default: + ERROR("Unrecognized printjob resolution (%u ppm)\n", j); + free(buf); + return CUPS_BACKEND_CANCEL; + } + } - /* Okay, generate a new stream into job->databuf! */ -#if 0 - job->datalen += sprintf((char*)job->databuf + job->datalen, - "\033PCNTRL QTY 00000008%07d\r", hdr->copies); - job->datalen += sprintf((char*)job->databuf + job->datalen, - "\033PCNTRL CUTTER 0000000800000000"); -#else - /* QTY is stripped from the stream, and CUTTER is stashed away */ - job->cutter = 0; -#endif + /* Generate bitmap file header (same for all planes) */ + j = cpu_to_le32(plane_len + 24); + memset(bmp_hdr, 0, sizeof(bmp_hdr)); + bmp_hdr[0] = 0x42; + bmp_hdr[1] = 0x4d; + memcpy(bmp_hdr + 2, &j, sizeof(j)); + bmp_hdr[10] = 0x40; + bmp_hdr[11] = 0x04; + /* Set up planes */ j = 0; /* Y plane */ job->datalen += sprintf((char*)job->databuf + job->datalen, - "\033PIMAGE YPLANE %08u", hdr->plane_len + 24); - memcpy(job->databuf + job->datalen, plane_hdr, sizeof(plane_hdr)); - job->datalen += sizeof(plane_hdr); - memcpy(job->databuf + job->datalen, buf + j, hdr->plane_len); - job->datalen += hdr->plane_len; - j += hdr->plane_len; + "\033PIMAGE YPLANE %08u", plane_len + 24); + memcpy(job->databuf + job->datalen, bmp_hdr, sizeof(bmp_hdr)); + job->datalen += sizeof(bmp_hdr); + memcpy(job->databuf + job->datalen, buf + j, plane_len); + job->datalen += plane_len; + j += plane_len; memset(job->databuf + job->datalen, 0, 10); job->datalen += 10; /* M plane */ job->datalen += sprintf((char*)job->databuf + job->datalen, - "\033PIMAGE MPLANE %08u", hdr->plane_len + 24); - memcpy(job->databuf + job->datalen, plane_hdr, sizeof(plane_hdr)); - job->datalen += sizeof(plane_hdr); - memcpy(job->databuf + job->datalen, buf + j, hdr->plane_len); - job->datalen += hdr->plane_len; - j += hdr->plane_len; + "\033PIMAGE MPLANE %08u", plane_len + 24); + memcpy(job->databuf + job->datalen, bmp_hdr, sizeof(bmp_hdr)); + job->datalen += sizeof(bmp_hdr); + memcpy(job->databuf + job->datalen, buf + j, plane_len); + job->datalen += plane_len; + j += plane_len; memset(job->databuf + job->datalen, 0, 10); job->datalen += 10; /* C plane */ job->datalen += sprintf((char*)job->databuf + job->datalen, - "\033PIMAGE CPLANE %08u", hdr->plane_len + 24); - memcpy(job->databuf + job->datalen, plane_hdr, sizeof(plane_hdr)); - job->datalen += sizeof(plane_hdr); - memcpy(job->databuf + job->datalen, buf + j, hdr->plane_len); - job->datalen += hdr->plane_len; - j += hdr->plane_len; + "\033PIMAGE CPLANE %08u", plane_len + 24); + memcpy(job->databuf + job->datalen, bmp_hdr, sizeof(bmp_hdr)); + job->datalen += sizeof(bmp_hdr); + memcpy(job->databuf + job->datalen, buf + j, plane_len); + job->datalen += plane_len; + j += plane_len; memset(job->databuf + job->datalen, 0, 10); job->datalen += 10; @@ -3143,6 +3207,183 @@ static int cw01_read_parse(struct dnpds40_printjob *job, int data_fd, return CUPS_BACKEND_OK; } +struct cw01_spool_hdr { + uint8_t type; /* TYPE_??? */ + uint8_t res; /* DPI_??? */ + uint8_t copies; /* number of prints */ + uint8_t null0; + uint32_t plane_len; /* LE */ + uint8_t null1[4]; +}; + +#define DPI_334 0 +#define DPI_600 1 + +#define TYPE_DSC 0 +#define TYPE_L 1 +#define TYPE_PC 2 +#define TYPE_2DSC 3 +#define TYPE_3L 4 +#define TYPE_A5 5 +#define TYPE_A6 6 + +static int legacy_cw01_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data) +{ + struct cw01_spool_hdr hdr; + uint32_t plane_len; + + /* get original header out of structure */ + memcpy(&hdr, job->databuf + job->datalen, sizeof(hdr)); + + /* Early parsing and sanity checking */ + plane_len = le32_to_cpu(hdr.plane_len); + + if (hdr.type > TYPE_A6 || + hdr.res > DPI_600 || + hdr.null1[0] || hdr.null1[1] || hdr.null1[2] || hdr.null1[3]) { + ERROR("Unrecognized header data format @%d!\n", job->datalen); + return CUPS_BACKEND_CANCEL; + } + job->dpi = (hdr.res == DPI_600) ? 600 : 334; + job->cutter = 0; + + return legacy_spool_helper(job, data_fd, read_data, + sizeof(hdr), plane_len, 0); +} + +struct rx1_spool_hdr { + uint8_t type; /* equals MULTICUT_?? - 1 */ + uint8_t null0; + uint8_t copies; /* number of copies, always fixed at 01.. */ + uint8_t null1; + uint32_t plane_len; /* LE */ + uint8_t flags; /* combination of FLAG_?? */ + uint8_t null2[3]; +}; + +#define FLAG_MATTE 0x02 +#define FLAG_NORETRY 0x08 +#define FLAG_2INCH 0x10 + +static int legacy_dnp_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data) +{ + struct rx1_spool_hdr hdr; + uint32_t plane_len; + + /* get original header out of structure */ + memcpy(&hdr, job->databuf + job->datalen, sizeof(hdr)); + + /* Early parsing and sanity checking */ + plane_len = le32_to_cpu(hdr.plane_len); + + if (hdr.type >= MULTICUT_A4x5X2 || + hdr.null2[0] || hdr.null2[1] || hdr.null2[2]) { + ERROR("Unrecognized header data format @%d!\n", job->datalen); + return CUPS_BACKEND_CANCEL; + } + + /* Don't bother with FW version checks for legacy stuff */ + job->multicut = hdr.type + 1; + job->matte = (hdr.flags & FLAG_MATTE) ? 1 : 0; + job->cutter = (hdr.flags & FLAG_2INCH) ? 120 : 0; + + return legacy_spool_helper(job, data_fd, read_data, + sizeof(hdr), plane_len, 1); +} + +struct ds620_spool_hdr { + uint8_t type; /* MULTICUT_?? -1, but >0x90 is a flag for rewind */ + uint8_t copies; /* Always fixed at 01..*/ + uint8_t null0[2]; + uint8_t quality; /* 0x02 is HQ, 0x00 is HS. Equivalent to DPI. */ + uint8_t unk[3]; /* Always 00 01 00 */ + uint32_t plane_len; /* LE */ + uint8_t flags; /* FLAG_?? */ + uint8_t null1[3]; +}; +#define FLAG_LUSTER 0x04 +#define FLAG_FINEMATTE 0x06 + +static int legacy_dnp620_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data) +{ + struct ds620_spool_hdr hdr; + uint32_t plane_len; + + /* get original header out of structure */ + memcpy(&hdr, job->databuf + job->datalen, sizeof(hdr)); + + /* Early parsing and sanity checking */ + plane_len = le32_to_cpu(hdr.plane_len); + + /* Used to signify rewind request. Backend handles automatically. */ + if (hdr.type > 0x90) + hdr.type -= 0x90; + + if (hdr.type > MULTICUT_A4x5X2 || + hdr.null1[0] || hdr.null1[1] || hdr.null1[2]) { + ERROR("Unrecognized header data format @%d!\n", job->datalen); + return CUPS_BACKEND_CANCEL; + } + + /* Don't bother with FW version checks for legacy stuff */ + job->multicut = hdr.type + 1; + if ((hdr.flags & FLAG_FINEMATTE) == FLAG_FINEMATTE) + job->matte = 21; + else if (hdr.flags & FLAG_LUSTER) + job->matte = 22; + else if (hdr.flags & FLAG_MATTE) + job->matte = 1; + + job->cutter = (hdr.flags & FLAG_2INCH) ? 120 : 0; + + return legacy_spool_helper(job, data_fd, read_data, + sizeof(hdr), plane_len, 1); +} + +#define FLAG_820_HD 0x80 +#define FLAG_820_RETRY 0x20 +#define FLAG_820_LUSTER 0x06 +#define FLAG_820_FMATTE 0x04 +#define FLAG_820_MATTE 0x02 + +static int legacy_dnp820_read_parse(struct dnpds40_printjob *job, int data_fd, int read_data) +{ + struct ds620_spool_hdr hdr; + uint32_t plane_len; + + /* get original header out of structure */ + memcpy(&hdr, job->databuf + job->datalen, sizeof(hdr)); + + /* Early parsing and sanity checking */ + plane_len = le32_to_cpu(hdr.plane_len); + + /* Used to signify rewind request. Backend handles automatically. */ + if (hdr.type > 0x90) + hdr.type -= 0x90; + + if (hdr.type > MULTICUT_A4x5X2 || + hdr.null1[0] || hdr.null1[1] || hdr.null1[2]) { + ERROR("Unrecognized header data format @%d!\n", job->datalen); + return CUPS_BACKEND_CANCEL; + } + + /* Don't bother with FW version checks for legacy stuff */ + job->multicut = hdr.type + 1; + if ((hdr.flags & FLAG_820_FMATTE) == FLAG_820_FMATTE) + job->matte = 21; + else if (hdr.flags & FLAG_820_LUSTER) + job->matte = 22; + else if (hdr.flags & FLAG_820_MATTE) + job->matte = 1; + + if (hdr.flags & FLAG_820_HD) + job->printspeed = 3; + + return legacy_spool_helper(job, data_fd, read_data, + sizeof(hdr), plane_len, 1); +} + + /* Basic spool file format for CW01 @@ -3151,11 +3392,11 @@ TT RR NN 00 XX XX XX XX 00 00 00 00 <- FILE header. NN : copies (0x01 or more) RR : resolution; 0 == 334 dpi, 1 == 600dpi - TT : type 0x02 == 4x6, 0x01 == 5x3.5 + TT : type 0x02 == 4x6, 0x01 == 5x3.5, 0x06 = 6x9 XX XX XX XX : plane length (LE) plane length * 3 + 12 == file length. -Followed by three planes, each with this header: +Followed by three planes, each with this 40b header: 28 00 00 00 00 08 00 00 RR RR 00 00 01 00 08 00 00 00 00 00 00 00 00 00 5a 33 00 00 YY YY 00 00 diff --git a/src/cups/backend_kodak1400.c b/src/cups/backend_kodak1400.c index 99bd678..88fe9b0 100644 --- a/src/cups/backend_kodak1400.c +++ b/src/cups/backend_kodak1400.c @@ -1,7 +1,7 @@ /* * Kodak Professional 1400/805 CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * The latest version of this program can be found at: * @@ -154,7 +154,7 @@ static int send_plane(struct kodak1400_ctx *ctx, return 0; } -#define UPDATE_SIZE 1552 +#define TONE_CURVE_SIZE 1552 static int kodak1400_set_tonecurve(struct kodak1400_ctx *ctx, char *fname) { libusb_device_handle *dev = ctx->dev; @@ -167,7 +167,7 @@ static int kodak1400_set_tonecurve(struct kodak1400_ctx *ctx, char *fname) INFO("Set Tone Curve from '%s'\n", fname); - uint16_t *data = malloc(UPDATE_SIZE); + uint16_t *data = malloc(TONE_CURVE_SIZE); if (!data) { ERROR("Memory Allocation Failure!\n"); @@ -175,23 +175,17 @@ static int kodak1400_set_tonecurve(struct kodak1400_ctx *ctx, char *fname) } /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) { + ERROR("Failed to read Tone Curve file\n"); goto done; } - if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) { - ret = -2; - goto done; - } - close(tc_fd); /* Byteswap data to printer's format */ - for (ret = 0; ret < (UPDATE_SIZE-16)/2 ; ret++) { + for (ret = 0; ret < (TONE_CURVE_SIZE-16)/2 ; ret++) { data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); } /* Null-terminate */ - memset(data + (UPDATE_SIZE-16)/2, 0, 16); + memset(data + (TONE_CURVE_SIZE-16)/2, 0, 16); /* Clear tables */ memset(cmdbuf, 0, sizeof(cmdbuf)); @@ -226,14 +220,14 @@ static int kodak1400_set_tonecurve(struct kodak1400_ctx *ctx, char *fname) cmdbuf[2] = 0x02; cmdbuf[3] = 0x03; cmdbuf[4] = 0x06; - cmdbuf[5] = 0x10; /* 06 10 == UPDATE_SIZE */ + cmdbuf[5] = 0x10; /* 06 10 == TONE_CURVE_SIZE */ if ((ret = send_data(dev, endp_down, cmdbuf, 6))) goto done; /* Send the payload over */ if ((ret = send_data(dev, endp_down, - (uint8_t *) data, UPDATE_SIZE))) + (uint8_t *) data, TONE_CURVE_SIZE))) goto done; /* get the response */ @@ -334,15 +328,6 @@ static void kodak1400_cleanup_job(const void *vjob) free((void*)job); } -static void kodak1400_teardown(void *vctx) { - struct kodak1400_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int kodak1400_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct kodak1400_ctx *ctx = vctx; int i, ret; @@ -661,13 +646,12 @@ static const char *kodak1400_prefixes[] = { struct dyesub_backend kodak1400_backend = { .name = "Kodak 1400/805", - .version = "0.39", + .version = "0.40", .uri_prefixes = kodak1400_prefixes, .cmdline_usage = kodak1400_cmdline, .cmdline_arg = kodak1400_cmdline_arg, .init = kodak1400_init, .attach = kodak1400_attach, - .teardown = kodak1400_teardown, .cleanup_job = kodak1400_cleanup_job, .read_parse = kodak1400_read_parse, .main_loop = kodak1400_main_loop, diff --git a/src/cups/backend_kodak605.c b/src/cups/backend_kodak605.c index 64524d4..423308b 100644 --- a/src/cups/backend_kodak605.c +++ b/src/cups/backend_kodak605.c @@ -1,7 +1,7 @@ /* * Kodak 605 Photo Printer CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * The latest version of this program can be found at: * @@ -39,58 +39,34 @@ #define BACKEND kodak605_backend #include "backend_common.h" +#include "backend_sinfonia.h" #define USB_VID_KODAK 0x040A #define USB_PID_KODAK_605 0x402E +#define USB_PID_KODAK_7000 0x4035 +#define USB_PID_KODAK_7010 0x4037 +#define USB_PID_KODAK_7015 0x4038 -/* Command Header */ -struct kodak605_cmd { - uint16_t cmd; /* LE */ - uint16_t len; /* LE, not counting this header */ -} __attribute__((packed)); - -struct kodak605_sts_hdr { - uint8_t result; /* RESULT_* */ - uint8_t unk_1[5]; /* 00 00 00 00 00 */ - uint8_t sts_1; /* 01/02 */ - uint8_t sts_2; /* 00/61->6b ?? temperature? */ - uint16_t length; /* LE, not counting this header */ -} __attribute__((packed)); - -#define RESULT_SUCCESS 0x01 -#define RESULT_FAIL 0x02 +/* List of confirmed commands */ +//#define SINFONIA_CMD_GETSTATUS 0x0001 +//#define SINFONIA_CMD_MEDIAINFO 0x0002 +//#define SINFONIA_CMD_PRINTJOB 0x4001 +//#define SINFONIA_CMD_UPDATE 0xC004 /* Media structure */ -struct kodak605_medium { - uint8_t index; - uint16_t cols; /* LE */ - uint16_t rows; /* LE */ - uint8_t type; /* MEDIA_TYPE_* */ - uint8_t unk[4]; /* 00 00 00 00 */ -} __attribute__((packed)); - -#define MEDIA_TYPE_UNKNOWN 0x00 -#define MEDIA_TYPE_PAPER 0x01 - struct kodak605_media_list { - struct kodak605_sts_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t unk; /* always seen 02 */ uint8_t type; /* KODAK68x0_MEDIA_* */ uint8_t count; - struct kodak605_medium entries[]; + struct sinfonia_mediainfo_item entries[]; } __attribute__((packed)); -#define KODAK68x0_MEDIA_6R 0x0b // 197-4096 -#define KODAK68x0_MEDIA_UNK 0x03 -#define KODAK68x0_MEDIA_6TR2 0x2c // 396-2941 -#define KODAK68x0_MEDIA_NONE 0x00 -/* 6R: Also seen: 101-0867, 141-9597, 659-9054, 169-6418, DNP 900-060 */ - #define MAX_MEDIA_LEN 128 /* Status response */ struct kodak605_status { - struct kodak605_sts_hdr hdr; + struct sinfonia_status_hdr hdr; /*@10*/ uint32_t ctr_life; /* Lifetime Prints */ uint32_t ctr_maint; /* Prints since last maintenance */ uint32_t ctr_media; /* Prints on current media */ @@ -98,12 +74,12 @@ struct kodak605_status { uint32_t ctr_head; /* Prints on current head */ /*@30*/ uint8_t donor; /* Donor Percentage remaining */ /*@31*/ uint8_t null_1[7]; /* 00 00 00 00 00 00 00 */ -/*@38*/ uint8_t b1_id; /* 00/01/02 */ +/*@38*/ uint8_t b1_id; /* jobid */ uint16_t b1_remain; uint16_t b1_complete; uint16_t b1_total; /*@45*/ uint8_t b1_sts; /* See BANK_STATUS_* */ - uint8_t b2_id; /* 00/01/02 */ + uint8_t b2_id; /* jobid */ uint16_t b2_remain; uint16_t b2_complete; uint16_t b2_total; @@ -113,141 +89,236 @@ struct kodak605_status { /*@57*/ uint16_t complete; /* in current job */ /*@59*/ uint16_t total; /* in current job */ /*@61*/ uint8_t null_2[9]; /* 00 00 00 00 00 00 00 00 00 */ -/*@70*/ uint8_t unk_12[6]; /* 01 00 00 00 00 00 */ -} __attribute__((packed)); - -/* File header */ -struct kodak605_hdr { - uint8_t hdr[4]; /* 01 40 0a 00 */ - uint8_t jobid; - uint16_t copies; /* LE, 0x0001 or more */ - uint16_t columns; /* LE, always 0x0734 */ - uint16_t rows; /* LE */ - uint8_t media; /* 0x03 for 6x8, 0x01 for 6x4 */ - uint8_t laminate; /* 0x02 to laminate, 0x01 for not */ - uint8_t mode; /* Print mode -- 0x00, 0x01 seen */ +/*@70*/ uint8_t unk_12[6]; /* 01 00 00 00 00 00 (605) 01 01 01 01 00 00 (EK7000) */ +/*@76*/ uint8_t unk_13[1]; // EK7000-series only? } __attribute__((packed)); -#define BANK_STATUS_FREE 0x00 -#define BANK_STATUS_XFER 0x01 -#define BANK_STATUS_FULL 0x02 -#define BANK_STATUS_PRINTING 0x12 - -static char *bank_statuses(uint8_t v) -{ - switch (v) { - case BANK_STATUS_FREE: - return "Free"; - case BANK_STATUS_XFER: - return "Xfer"; - case BANK_STATUS_FULL: - return "Full"; - case BANK_STATUS_PRINTING: - return "Printing"; - default: - return "Unknown"; - } -} - -static const char *kodak68xx_mediatypes(int type) -{ - switch(type) { - case KODAK68x0_MEDIA_NONE: - return "No media"; - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: - return "Kodak 6R"; - default: - return "Unknown"; - } - return "Unknown"; -} - #define CMDBUF_LEN 4 /* Private data structure */ -struct kodak605_printjob { - struct kodak605_hdr hdr; - uint8_t *databuf; - int datalen; -}; - struct kodak605_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; + struct sinfonia_usbdev dev; + uint8_t jobid; struct kodak605_media_list *media; struct marker marker; - }; +/* Note this is for Kodak 7000-series only! */ +static const char *error_codes(uint8_t major, uint8_t minor) +{ + switch(major) { + case 0x01: /* "Controller Error" */ + switch(minor) { + case 0x01: + return "Controller: EEPROM Write Timeout"; + case 0x02: + return "Controller: EEPROM Verify"; + case 0x09: + return "Controller: DSP FW Boot"; + case 0x0A: + return "Controller: Invalid Print Parameter Table"; + case 0x0B: + return "Controller: DSP FW Mismatch"; + case 0x0C: + return "Controller: Print Parameter Table Mismatch"; + case 0x0D: + return "Controller: ASIC Error"; + case 0x0E: + return "Controller: FPGA Error"; + case 0x0F: + return "Controller: Main FW Checksum"; + case 0x10: + return "Controller: Main FW Write Failed"; + case 0x11: + return "Controller: DSP Checksum"; + case 0x12: + return "Controller: DSP FW Write Failed"; + case 0x13: + return "Controller: Print Parameter Table Checksum"; + case 0x14: + return "Controller: Print Parameter Table Write Failed"; + case 0x15: + return "Controller: User Tone Curve Write Failed"; + case 0x16: + return "Controller: Main-DSP Communication"; + case 0x17: + return "Controller: DSP DMA Failed"; + case 0x18: + return "Controller: Matte Pattern Write Failed"; + case 0x19: + return "Controller: Matte not Initialized"; + case 0x20: + return "Controller: Serial Number Error"; + default: + return "Controller: Unknown"; + } + case 0x02: /* "Mechanical Error" */ + switch (minor) { + case 0x01: + return "Mechanical: Pinch Head Up"; + case 0x02: + return "Mechanical: Pinch Head Down"; + case 0x03: + return "Mechanical: Pinch Roll Main Up Feed Up"; + case 0x04: + return "Mechanical: Pinch Roll Main Dn Feed Up"; + case 0x05: + return "Mechanical: Pinch Roll Main Dn Feed Dn"; + case 0x06: + return "Mechanical: Pinch Roll Eject Up"; + case 0x07: + return "Mechanical: Pinch Roll Eject Dn"; + case 0x0B: + return "Mechanical: Cutter (Left->Right)"; + case 0x0C: + return "Mechanical: Cutter (Right->Left)"; + default: + return "Mechanical: Unknown"; + } + case 0x03: /* "Sensor Error" */ + switch (minor) { + case 0x01: + return "Sensor: Head Up/Dn All On"; + case 0x02: + return "Sensor: Feed Pitch Roll Up/Dn All On"; + case 0x05: + return "Sensor: Cutter L/R All On"; + case 0x06: + return "Sensor: Cutter L Stuck On"; + case 0x07: + return "Sensor: Cutter Move not Detected"; + case 0x08: + return "Sensor: Cutter R Stuck On"; + case 0x09: + return "Sensor: Head Up Unstable"; + case 0x0A: + return "Sensor: Head Dn Unstable"; + case 0x0B: + return "Sensor: Main/Feed Pinch Up Unstabe"; + case 0x0C: + return "Sensor: Main/Feed Pinch Dn Unstable"; + case 0x0D: + return "Sensor: Eject Up Unstable"; + case 0x0E: + return "Sensor: Eject Dn Unstable"; + case 0x0F: + return "Sensor: Left Cutter Unstable"; + case 0x10: + return "Sensor: Right Cutter Unstable"; + case 0x11: + return "Sensor: Center Cutter Unstable"; + case 0x12: + return "Sensor: Upper Cover Unstable"; + case 0x13: + return "Sensor: Paper Cover Unstable"; + case 0x14: + return "Sensor: Ribbon Takeup Unstable"; + case 0x15: + return "Sensor: Ribbon Supply Unstable"; + default: + return "Sensor: Unknown"; + } + case 0x04: /* "Temperature Sensor Error" */ + switch (minor) { + case 0x01: + return "Temp Sensor: Thermal Head High"; + case 0x02: + return "Temp Sensor: Thermal Head Low"; + case 0x05: + return "Temp Sensor: Environment High"; + case 0x09: + return "Temp Sensor: Environment Low"; + case 0x0A: + return "Temp Sensor: Preheat"; + default: + return "Temp Sensor: Unknown"; + } + case 0x5: /* "Paper Jam" */ + switch (minor) { + // XXX these have been seen on EK7000: + // case 0x0c: + // case 0x36: + case 0x3D: + return "Paper Jam: Feed Cut->Home"; + case 0x3E: + return "Paper Jam: Feed Cut->Exit Stuck Off"; + case 0x3F: + return "Paper Jam: Feed Cut->Exit Stuck On"; + case 0x4A: + return "Paper Jam: Idle / Paper Set"; + case 0x51: + return "Paper Jam: Paper Exit On"; + case 0x52: + return "Paper Jam: Print Position On"; + case 0x53: + return "Paper Jam: Paper Empty On"; + case 0x54: + return "Paper Jam: Idle / Paper Not Set"; + default: + return "Paper Jam: Unknown"; + } + case 0x06: /* User Error */ + switch (minor) { + case 0x01: + return "Drawer Unit Open"; + case 0x02: + return "Incorrect Ribbon"; + case 0x03: + return "No/Empty Ribbon"; + case 0x04: + return "Mismatched Ribbon"; + case 0x08: + return "No Paper"; + case 0x0C: + return "Paper End"; + default: + return "User: Unknown"; + } + default: + return "Unknown"; + } +} + static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media) { - uint8_t cmdbuf[4]; + struct sinfonia_cmd_hdr cmd; - int ret, num = 0; + int i, ret, num = 0; - /* Send Media Query */ - cmdbuf[0] = 0x02; - cmdbuf[1] = 0x00; - cmdbuf[2] = 0x00; - cmdbuf[3] = 0x00; - if ((ret = send_data(ctx->dev, ctx->endp_down, - cmdbuf, sizeof(cmdbuf)))) - return ret; + cmd.cmd = cpu_to_le16(SINFONIA_CMD_MEDIAINFO); + cmd.len = cpu_to_le16(0); - /* Read in the printer status */ - ret = read_data(ctx->dev, ctx->endp_up, - (uint8_t*) media, MAX_MEDIA_LEN, &num); - if (ret < 0) + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)media, MAX_MEDIA_LEN, + &num))) { return ret; - - if (num < (int)sizeof(*media)) { - ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*media)); - return CUPS_BACKEND_FAILED; } - if (media->hdr.result != RESULT_SUCCESS) { - ERROR("Unexpected response from media query (%x)!\n", media->hdr.result); - return CUPS_BACKEND_FAILED; - } + for (i = 0 ; i < media->count; i++) { + media->entries[i].rows = le16_to_cpu(media->entries[i].rows); + media->entries[i].columns = le16_to_cpu(media->entries[i].columns); + } return 0; } static int kodak605_get_status(struct kodak605_ctx *ctx, struct kodak605_status *sts) { - uint8_t cmdbuf[4]; + struct sinfonia_cmd_hdr cmd; int ret, num = 0; - /* Send Status Query */ - cmdbuf[0] = 0x01; - cmdbuf[1] = 0x00; - cmdbuf[2] = 0x00; - cmdbuf[3] = 0x00; - if ((ret = send_data(ctx->dev, ctx->endp_down, - cmdbuf, sizeof(cmdbuf)))) - return ret; + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); - /* Read in the printer status */ - ret = read_data(ctx->dev, ctx->endp_up, - (uint8_t*) sts, sizeof(*sts), &num); - if (ret < 0) + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)sts, sizeof(*sts), &num)) < 0) { return ret; - - if (num < (int)sizeof(*sts)) { - ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*sts)); - return CUPS_BACKEND_FAILED; - } - - if (sts->hdr.result != RESULT_SUCCESS) { - ERROR("Unexpected response from status query (%x)!\n", sts->hdr.result); - return CUPS_BACKEND_FAILED; } return 0; @@ -272,10 +343,11 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, int typ { struct kodak605_ctx *ctx = vctx; - ctx->dev = dev; - ctx->endp_up = endp_up; - ctx->endp_down = endp_down; - ctx->type = type; + ctx->dev.dev = dev; + ctx->dev.endp_up = endp_up; + ctx->dev.endp_down = endp_down; + ctx->dev.type = type; + ctx->dev.error_codes = &error_codes; /* Make sure jobid is sane */ ctx->jobid = jobid & 0x7f; @@ -289,7 +361,7 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, int typ return CUPS_BACKEND_FAILED; } } else { - int media_code = KODAK68x0_MEDIA_6TR2; + int media_code = KODAK6_MEDIA_6TR2; if (getenv("MEDIA_CODE")) media_code = atoi(getenv("MEDIA_CODE")); @@ -297,37 +369,18 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, int typ } ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = kodak68xx_mediatypes(ctx->media->type); + ctx->marker.name = kodak6_mediatypes(ctx->media->type); ctx->marker.levelmax = 100; /* Ie percentage */ ctx->marker.levelnow = -2; return CUPS_BACKEND_OK; } -static void kodak605_cleanup_job(const void *vjob) -{ - const struct kodak605_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void kodak605_teardown(void *vctx) { - struct kodak605_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int kodak605_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct kodak605_ctx *ctx = vctx; int ret; - struct kodak605_printjob *job = NULL; + struct sinfonia_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_CANCEL; @@ -339,51 +392,16 @@ static int kodak605_read_parse(void *vctx, const void **vjob, int data_fd, int c } memset(job, 0, sizeof(*job)); - /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - if (ret == 0) - return CUPS_BACKEND_CANCEL; - ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); - perror("ERROR: Read failed"); - return CUPS_BACKEND_CANCEL; - } - - if (job->hdr.hdr[0] != 0x01 || - job->hdr.hdr[1] != 0x40 || - job->hdr.hdr[2] != 0x0a || - job->hdr.hdr[3] != 0x00) { - ERROR("Unrecognized data format!\n"); - return CUPS_BACKEND_CANCEL; - } - - job->datalen = le16_to_cpu(job->hdr.rows) * le16_to_cpu(job->hdr.columns) * 3; - job->databuf = malloc(job->datalen); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - return CUPS_BACKEND_RETRY_CURRENT; - } - - { - int remain = job->datalen; - uint8_t *ptr = job->databuf; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%d)\n", - ret, remain, job->datalen); - perror("ERROR: Read failed"); - return CUPS_BACKEND_CANCEL; - } - ptr += ret; - remain -= ret; - } while (remain); + /* Read in header */ + ret = sinfonia_raw10_read_parse(data_fd, job); + if (ret) { + free(job); + return ret; } /* Printer handles generating copies.. */ - if (le16_to_cpu(job->hdr.copies) < copies) - job->hdr.copies = cpu_to_le16(copies); + if (le16_to_cpu(job->jp.copies) < (uint16_t)copies) + job->jp.copies = cpu_to_le16(copies); *vjob = job; @@ -397,20 +415,17 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { int num, ret; - const struct kodak605_printjob *job = vjob; + const struct sinfonia_printjob *job = vjob; if (!ctx) return CUPS_BACKEND_FAILED; if (!job) return CUPS_BACKEND_FAILED; - struct kodak605_hdr hdr; - memcpy(&hdr, &job->hdr, sizeof(hdr)); - /* Validate against supported media list */ for (num = 0 ; num < ctx->media->count; num++) { - if (ctx->media->entries[num].rows == hdr.rows && - ctx->media->entries[num].cols == hdr.columns) + if (ctx->media->entries[num].rows == job->jp.rows && + ctx->media->entries[num].columns == job->jp.columns) break; } if (num == ctx->media->count) { @@ -429,7 +444,16 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { dump_markers(&ctx->marker, 1, 0); } - // XXX check for errors + if (sts.hdr.result != RESULT_SUCCESS) { + ERROR("Printer Status: %02x (%s)\n", sts.hdr.status, + sinfonia_status_str(sts.hdr.status)); + ERROR("Result: %02x Error: %02x (%s) %02x/%02x = %s\n", + sts.hdr.result, sts.hdr.error, + sinfonia_error_str(sts.hdr.error), + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); + return CUPS_BACKEND_FAILED; + } /* Make sure we're not colliding with an existing jobid */ @@ -450,35 +474,55 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { sleep(1); } - /* Use specified jobid */ + /* Send print job */ + struct sinfonia_printcmd10_hdr hdr; + + INFO("Sending print job (internal id %u)\n", ctx->jobid); + + /* Set up header */ + hdr.hdr.cmd = cpu_to_le16(SINFONIA_CMD_PRINTJOB); + hdr.hdr.len = cpu_to_le16(10); hdr.jobid = ctx->jobid; + hdr.rows = cpu_to_le16(job->jp.rows); + hdr.columns = cpu_to_le16(job->jp.columns); + hdr.copies = cpu_to_le16(job->jp.copies); + hdr.media = job->jp.media; + hdr.oc_mode = job->jp.oc_mode; + hdr.method = job->jp.method; + +retry_print: + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&hdr, sizeof(hdr), + (uint8_t*)&sts.hdr, sizeof(sts.hdr), + &num)) < 0) { + return ret; + } - { - INFO("Sending image header (internal id %u)\n", ctx->jobid); - if ((ret = send_data(ctx->dev, ctx->endp_down, - (uint8_t*)&hdr, sizeof(hdr)))) - return CUPS_BACKEND_FAILED; + if (sts.hdr.result != RESULT_SUCCESS) { + if (sts.hdr.error == ERROR_BUFFER_FULL) { + INFO("Printer Buffers full, retrying\n"); + sleep(1); + goto retry_print; + } else if ((sts.hdr.status & 0xf0) == 0x30 || sts.hdr.status == ERROR_BUFFER_FULL) { + INFO("Printer busy (%02x : %s), retrying\n", sts.hdr.status, sinfonia_status_str(sts.hdr.status)); - struct kodak605_sts_hdr resp; - if ((ret = read_data(ctx->dev, ctx->endp_up, - (uint8_t*) &resp, sizeof(resp), &num))) - return CUPS_BACKEND_FAILED; + } else { + ERROR("Unexpected response from print command!\n"); + ERROR("Printer Status: %02x: %s\n", sts.hdr.status, sinfonia_status_str(sts.hdr.status)); + ERROR("Result: %02x Error: %02x (%02x %02x = %s)\n", + sts.hdr.result, sts.hdr.error, + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); - if (resp.result != RESULT_SUCCESS) { - ERROR("Unexpected response from print command (%x)!\n", resp.result); return CUPS_BACKEND_FAILED; } - // XXX what about resp.sts1 or resp.sts2? } - sleep(1); INFO("Sending image data\n"); - if ((ret = send_data(ctx->dev, ctx->endp_down, + if ((ret = send_data(ctx->dev.dev, ctx->dev.endp_down, job->databuf, job->datalen))) return CUPS_BACKEND_FAILED; - INFO("Image data sent\n"); - INFO("Waiting for printer to acknowledge completion\n"); do { sleep(1); @@ -489,7 +533,19 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { ctx->marker.levelnow = sts.donor; dump_markers(&ctx->marker, 1, 0); } - // XXX check for errors + + INFO("Printer Status: %02x (%s)\n", sts.hdr.status, + sinfonia_status_str(sts.hdr.status)); + + if (sts.hdr.result != RESULT_SUCCESS || + sts.hdr.error == ERROR_PRINTER) { + INFO("Result: %02x Error: %02x (%s) %02x/%02x = %s\n", + sts.hdr.result, sts.hdr.error, + sinfonia_error_str(sts.hdr.error), + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); + return CUPS_BACKEND_STOP; + } /* Wait for completion */ if (sts.b1_id == ctx->jobid && sts.b1_complete == sts.b1_total) @@ -497,6 +553,9 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { if (sts.b2_id == ctx->jobid && sts.b2_complete == sts.b2_total) break; + if (sts.hdr.status == STATUS_READY) + break; + if (fast_return) { INFO("Fast return mode enabled.\n"); break; @@ -504,40 +563,49 @@ static int kodak605_main_loop(void *vctx, const void *vjob) { } while(1); INFO("Print complete\n"); - return CUPS_BACKEND_OK; } static void kodak605_dump_status(struct kodak605_ctx *ctx, struct kodak605_status *sts) { + INFO("Status: %02x (%s)\n", + sts->hdr.status, sinfonia_status_str(sts->hdr.status)); + INFO("Error: %02x (%s) %02x/%02x = %s\n", + sts->hdr.error, sinfonia_error_str(sts->hdr.error), + sts->hdr.printer_major, sts->hdr.printer_minor, + error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + INFO("Bank 1: %s Job %03u @ %03u/%03u\n", - bank_statuses(sts->b1_sts), sts->b1_id, + sinfonia_bank_statuses(sts->b1_sts), sts->b1_id, le16_to_cpu(sts->b1_complete), le16_to_cpu(sts->b1_total)); INFO("Bank 2: %s Job %03u @ %03u/%03u\n", - bank_statuses(sts->b2_sts), sts->b2_id, + sinfonia_bank_statuses(sts->b2_sts), sts->b2_id, le16_to_cpu(sts->b2_complete), le16_to_cpu(sts->b2_total)); - INFO("Lifetime prints : %u\n", be32_to_cpu(sts->ctr_life)); - INFO("Cutter actuations : %u\n", be32_to_cpu(sts->ctr_cut)); - INFO("Head prints : %u\n", be32_to_cpu(sts->ctr_head)); - INFO("Media prints : %u\n", be32_to_cpu(sts->ctr_media)); + INFO("Lifetime prints : %u\n", le32_to_cpu(sts->ctr_life)); + INFO("Cutter actuations : %u\n", le32_to_cpu(sts->ctr_cut)); + INFO("Head prints : %u\n", le32_to_cpu(sts->ctr_head)); + INFO("Media prints : %u\n", le32_to_cpu(sts->ctr_media)); { int max; switch(ctx->media->type) { - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: + case KODAK6_MEDIA_6R: + case KODAK6_MEDIA_6TR2: max = 375; break; + case KODAK7_MEDIA_6R: + max = 570; + break; default: max = 0; break; } if (max) { - INFO("\t Remaining : %u\n", max - be32_to_cpu(sts->ctr_media)); + INFO("\t Remaining : %u\n", max - le32_to_cpu(sts->ctr_media)); } else { - INFO("\t Remaining : Unknown\n"); + INFO("\t Remaining : Unknown\n"); } } @@ -548,112 +616,36 @@ static void kodak605_dump_mediainfo(struct kodak605_media_list *media) { int i; - if (media->type == KODAK68x0_MEDIA_NONE) { + if (media->type == KODAK6_MEDIA_NONE) { DEBUG("No Media Loaded\n"); return; } - - switch (media->type) { - case KODAK68x0_MEDIA_6R: - INFO("Media type: 6R (Kodak 197-4096 or equivalent)\n"); - break; - case KODAK68x0_MEDIA_6TR2: - INFO("Media type: 6R (Kodak 396-2941 or equivalent)\n"); - break; - default: - INFO("Media type %02x (unknown, please report!)\n", media->type); - break; - } + kodak6_dumpmediacommon(media->type); DEBUG("Legal print sizes:\n"); for (i = 0 ; i < media->count ; i++) { - DEBUG("\t%d: %ux%u\n", i, - le16_to_cpu(media->entries[i].cols), - le16_to_cpu(media->entries[i].rows)); + DEBUG("\t%d: %ux%u (%x)\n", i, + media->entries[i].columns, + media->entries[i].rows, + media->entries[i].code); } DEBUG("\n"); } -#define UPDATE_SIZE 1536 -static int kodak605_set_tonecurve(struct kodak605_ctx *ctx, char *fname) -{ - libusb_device_handle *dev = ctx->dev; - uint8_t endp_down = ctx->endp_down; - uint8_t endp_up = ctx->endp_up; - - uint8_t cmdbuf[16]; - uint8_t respbuf[16]; - int ret, num = 0; - - uint16_t *data = malloc(UPDATE_SIZE); - - INFO("Set Tone Curve from '%s'\n", fname); - - /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) { - ret = 4; - goto done; - } - close(tc_fd); - - /* Byteswap data to printer's format */ - for (ret = 0; ret < (UPDATE_SIZE/2) ; ret++) { - data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); - } - - /* Initial Request */ - cmdbuf[0] = 0x04; - cmdbuf[1] = 0xc0; - cmdbuf[2] = 0x0a; - cmdbuf[3] = 0x00; - cmdbuf[4] = 0x03; - cmdbuf[5] = 0x01; - cmdbuf[6] = 0x00; - cmdbuf[7] = 0x00; - cmdbuf[8] = 0x00; - cmdbuf[9] = 0x00; - cmdbuf[10] = 0x00; /* 00 06 in LE means 1536 bytes */ - cmdbuf[11] = 0x06; - cmdbuf[12] = 0x00; - cmdbuf[13] = 0x00; - - if ((ret = send_data(dev, endp_down, - cmdbuf, 14))) - goto done; - - /* Get response back */ - ret = read_data(dev, endp_up, - respbuf, sizeof(respbuf), &num); - if (ret < 0) - goto done; - - if (num != 10) { - ERROR("Short Read! (%d/%d)\n", num, 10); - ret = 4; - goto done; - } - - /* Send the data over! */ - ret = send_data(dev, endp_up, - (uint8_t*)data, sizeof(data)); - - done: - /* We're done */ - free(data); - return ret; -} - - static void kodak605_cmdline(void) { + DEBUG("\t\t[ -c filename ] # Get user/NV tone curve\n"); DEBUG("\t\t[ -C filename ] # Set tone curve\n"); + DEBUG("\t\t[ -e ] # Query error log\n"); + DEBUG("\t\t[ -F ] # Flash Printer LED\n"); + DEBUG("\t\t[ -i ] # Query printer info\n"); + DEBUG("\t\t[ -l filename ] # Get current tone curve\n"); + DEBUG("\t\t[ -L filename ] # Set current tone curve\n"); DEBUG("\t\t[ -m ] # Query media\n"); + DEBUG("\t\t[ -r ] # Reset user/NV tone curve\n"); + DEBUG("\t\t[ -R ] # Reset printer to factory defaults\n"); DEBUG("\t\t[ -s ] # Query status\n"); + DEBUG("\t\t[ -X jobid ] # Cancel job\n"); } static int kodak605_cmdline_arg(void *vctx, int argc, char **argv) @@ -664,15 +656,39 @@ static int kodak605_cmdline_arg(void *vctx, int argc, char **argv) if (!ctx) return -1; - while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "C:ms")) >= 0) { + while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFil:L:mrRsX:")) >= 0) { switch(i) { GETOPT_PROCESS_GLOBAL + case 'c': + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_USER, optarg); + break; case 'C': - j = kodak605_set_tonecurve(ctx, optarg); + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_USER, optarg); + break; + case 'e': + j = sinfonia_geterrorlog(&ctx->dev); + break; + case 'F': + j = sinfonia_flashled(&ctx->dev); + break; + case 'i': + j = sinfonia_getfwinfo(&ctx->dev); + break; + case 'l': + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); + break; + case 'L': + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); break; case 'm': kodak605_dump_mediainfo(ctx->media); break; + case 'r': + j = sinfonia_resetcurve(&ctx->dev, RESET_TONE_CURVE, TONE_CURVE_ID); + break; + case 'R': + j = sinfonia_resetcurve(&ctx->dev, RESET_PRINTER, 0); + break; case 's': { struct kodak605_status sts; @@ -680,6 +696,9 @@ static int kodak605_cmdline_arg(void *vctx, int argc, char **argv) if (!j) kodak605_dump_status(ctx, &sts); break; + case 'X': + j = sinfonia_canceljob(&ctx->dev, atoi(optarg)); + break; } default: break; /* Ignore completely */ @@ -710,34 +729,37 @@ static int kodak605_query_markers(void *vctx, struct marker **markers, int *coun static const char *kodak605_prefixes[] = { "kodak605", // Family driver, do NOT nuke. - "kodak-605", + "kodak-605", "kodak-7000", "kodak-7010", "kodak-7015", NULL, }; /* Exported */ struct dyesub_backend kodak605_backend = { - .name = "Kodak 605", - .version = "0.33", + .name = "Kodak 605/70xx", + .version = "0.45" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = kodak605_prefixes, .cmdline_usage = kodak605_cmdline, .cmdline_arg = kodak605_cmdline_arg, .init = kodak605_init, .attach = kodak605_attach, - .teardown = kodak605_teardown, - .cleanup_job = kodak605_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = kodak605_read_parse, .main_loop = kodak605_main_loop, .query_markers = kodak605_query_markers, .devices = { { USB_VID_KODAK, USB_PID_KODAK_605, P_KODAK_605, "Kodak", "kodak-605"}, + { USB_VID_KODAK, USB_PID_KODAK_7000, P_KODAK_7000, "Kodak", "kodak-7000"}, + { USB_VID_KODAK, USB_PID_KODAK_7010, P_KODAK_701X, "Kodak", "kodak-7010"}, + { USB_VID_KODAK, USB_PID_KODAK_7015, P_KODAK_701X, "Kodak", "kodak-7015"}, { 0, 0, 0, NULL, NULL} } }; -/* Kodak 605 data format +/* Kodak 605/70xx data format Spool file consists of 14-byte header followed by plane-interleaved BGR data. - Native printer resolution is 1844 pixels per row, and 1240 or 2434 rows. + Native printer resolution is 1844 pixels per row on all models but 7015, + which is 1548 pixels per row. All fields are LITTLE ENDIAN unless otherwise specified @@ -746,15 +768,18 @@ struct dyesub_backend kodak605_backend = { 01 40 0a 00 Fixed header XX Job ID CC CC Number of copies (1-???) - WW WW Number of columns (Fixed at 1844) - HH HH Number of rows (1240 or 2434) + WW WW Number of columns (Fixed at 1844 or 1548) + HH HH Number of rows DD 0x01 (4x6) 0x03 (8x6) - LL Laminate, 0x01 (off) or 0x02 (on) + LL Laminate, 0x01/0x02/0x03 (off/on/satin[70xx only]) 00 Print Mode (???) ************************************************************************ - Note: Kodak 605 is actually a Shinko CHC-S1545-5A + Note: Kodak 605 is actually a Shinko CHC-S1545-5A + Note: Kodak 7000 is actually a Shinko CHC-S1645-5A + Note: Kodak 7010 is actually a Shinko CHC-S1645-5B + Note: Kodak 7015 is actually a Shinko CHC-S1645-5C ************************************************************************ diff --git a/src/cups/backend_kodak6800.c b/src/cups/backend_kodak6800.c index 79d950b..06c54cb 100644 --- a/src/cups/backend_kodak6800.c +++ b/src/cups/backend_kodak6800.c @@ -1,7 +1,7 @@ /* * Kodak 6800/6850 Photo Printer CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * Development of this backend was sponsored by: * @@ -43,6 +43,7 @@ #define BACKEND kodak6800_backend #include "backend_common.h" +#include "backend_sinfonia.h" #define USB_VID_KODAK 0x040A #define USB_PID_KODAK_6800 0x4021 @@ -55,9 +56,9 @@ struct kodak6800_hdr { uint16_t copies; /* BE, in BCD format (1-9999) */ uint16_t columns; /* BE */ uint16_t rows; /* BE */ - uint8_t size; /* 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ + uint8_t size; /* media size; 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ uint8_t laminate; /* 0x01 to laminate, 0x00 for not */ - uint8_t mode; /* 0x00 or 0x01 (for 4x6 on 6x8 media) */ + uint8_t method; /* 0x00 or 0x01 (for 4x6 on 6x8 media), 0x21 for 2x6, 0x23 for 3x6 */ } __attribute__((packed)); struct kodak68x0_status_readback { @@ -68,15 +69,15 @@ struct kodak68x0_status_readback { uint8_t errcode; /* Error ## */ uint32_t lifetime; /* Lifetime Prints (BE) */ uint32_t maint; /* Maint Prints (BE) */ - uint32_t media; /* Media Prints (6850), Unknown (6800) (BE) */ - uint32_t cutter; /* Cutter Actuations (BE) */ + uint32_t media; /* Media Prints (6850), Unknown (6800) (BE) */ + uint32_t cutter; /* Cutter Actuations (BE) */ uint8_t nullB[2]; uint8_t errtype; /* seen 0x00 or 0xd0 */ uint8_t donor; /* Percentage, 0-100 */ uint16_t main_boot; /* Always 003 */ - uint16_t main_fw; /* seen 652, 656, 670, 671 (6850) and 232 (6800) */ + uint16_t main_fw; /* seen 6xx/8xx (6850) and 2xx/3xx/4xx (6800) */ uint16_t dsp_boot; /* Always 001 */ - uint16_t dsp_fw; /* Seen 540, 541, 560 (6850) and 131 (6800) */ + uint16_t dsp_fw; /* Seen 5xx (6850) and 1xx (6800) */ uint8_t b1_jobid; uint8_t b2_jobid; uint16_t b1_remain; /* Remaining prints in job */ @@ -88,181 +89,43 @@ struct kodak68x0_status_readback { uint8_t curve_status; /* Always seems to be 0x00 */ } __attribute__((packed)); -enum { - CMD_CODE_OK = 1, - CMD_CODE_BAD = 2, -}; - -enum { - STATUS_PRINTING = 1, - STATUS_IDLE = 2, -}; - -enum { - STATE_STATUS1_STANDBY = 1, - STATE_STATUS1_ERROR = 2, - STATE_STATUS1_WAIT = 3, -}; - -#define STATE_STANDBY_STATUS2 0x0 - -enum { - WAIT_STATUS2_INIT = 0, - WAIT_STATUS2_RIBBON = 1, - WAIT_STATUS2_THERMAL = 2, - WAIT_STATUS2_OPERATING = 3, - WAIT_STATUS2_BUSY = 4, -}; - -#define ERROR_STATUS2_CTRL_CIRCUIT (0x80000000) -#define ERROR_STATUS2_MECHANISM_CTRL (0x40000000) -#define ERROR_STATUS2_SENSOR (0x00002000) -#define ERROR_STATUS2_COVER_OPEN (0x00001000) -#define ERROR_STATUS2_TEMP_SENSOR (0x00000200) -#define ERROR_STATUS2_PAPER_JAM (0x00000100) -#define ERROR_STATUS2_PAPER_EMPTY (0x00000040) -#define ERROR_STATUS2_RIBBON_ERR (0x00000010) - -enum { - CTRL_CIR_ERROR_EEPROM1 = 0x01, - CTRL_CIR_ERROR_EEPROM2 = 0x02, - CTRL_CIR_ERROR_DSP = 0x04, - CTRL_CIR_ERROR_CRC_MAIN = 0x06, - CTRL_CIR_ERROR_DL_MAIN = 0x07, - CTRL_CIR_ERROR_CRC_DSP = 0x08, - CTRL_CIR_ERROR_DL_DSP = 0x09, - CTRL_CIR_ERROR_ASIC = 0x0a, - CTRL_CIR_ERROR_DRAM = 0x0b, - CTRL_CIR_ERROR_DSPCOMM = 0x29, -}; - -enum { - MECH_ERROR_HEAD_UP = 0x01, - MECH_ERROR_HEAD_DOWN = 0x02, - MECH_ERROR_MAIN_PINCH_UP = 0x03, - MECH_ERROR_MAIN_PINCH_DOWN = 0x04, - MECH_ERROR_SUB_PINCH_UP = 0x05, - MECH_ERROR_SUB_PINCH_DOWN = 0x06, - MECH_ERROR_FEEDIN_PINCH_UP = 0x07, - MECH_ERROR_FEEDIN_PINCH_DOWN = 0x08, - MECH_ERROR_FEEDOUT_PINCH_UP = 0x09, - MECH_ERROR_FEEDOUT_PINCH_DOWN = 0x0a, - MECH_ERROR_CUTTER_LR = 0x0b, - MECH_ERROR_CUTTER_RL = 0x0c, -}; - -enum { - SENSOR_ERROR_CUTTER = 0x05, - SENSOR_ERROR_HEAD_DOWN = 0x09, - SENSOR_ERROR_HEAD_UP = 0x0a, - SENSOR_ERROR_MAIN_PINCH_DOWN = 0x0b, - SENSOR_ERROR_MAIN_PINCH_UP = 0x0c, - SENSOR_ERROR_FEED_PINCH_DOWN = 0x0d, - SENSOR_ERROR_FEED_PINCH_UP = 0x0e, - SENSOR_ERROR_EXIT_PINCH_DOWN = 0x0f, - SENSOR_ERROR_EXIT_PINCH_UP = 0x10, - SENSOR_ERROR_LEFT_CUTTER = 0x11, - SENSOR_ERROR_RIGHT_CUTTER = 0x12, - SENSOR_ERROR_CENTER_CUTTER = 0x13, - SENSOR_ERROR_UPPER_CUTTER = 0x14, - SENSOR_ERROR_PAPER_FEED_COVER = 0x15, -}; - -enum { - TEMP_SENSOR_ERROR_HEAD_HIGH = 0x01, - TEMP_SENSOR_ERROR_HEAD_LOW = 0x02, - TEMP_SENSOR_ERROR_ENV_HIGH = 0x03, - TEMP_SENSOR_ERROR_ENV_LOW = 0x04, -}; - -enum { - COVER_OPEN_ERROR_UPPER = 0x01, - COVER_OPEN_ERROR_LOWER = 0x02, -}; - -enum { - PAPER_EMPTY_ERROR = 0x00, -}; - -enum { - RIBBON_ERROR = 0x00, -}; - -enum { - CURVE_TABLE_STATUS_INITIAL = 0x00, - CURVE_TABLE_STATUS_USERSET = 0x01, - CURVE_TABLE_STATUS_CURRENT = 0x02, -}; - -struct kodak6800_printsize { - uint8_t hdr; /* Always 0x06 */ - uint16_t width; /* BE */ - uint16_t height; /* BE */ - uint8_t type; /* MEDIA_TYPE_* [ ie paper ] */ - uint8_t code; /* 00, 01, 02, 03, 04, 05 seen. An index? */ - uint8_t code2; /* 00, 01 seen. Alternates every other 4x6 printed, but only 1 on unknown/1844x2490 print size. */ - uint8_t null[2]; -} __attribute__((packed)); - -#define MAX_MEDIA_LEN 128 +#define MAX_MEDIAS 16 struct kodak68x0_media_readback { uint8_t hdr; /* Always 0x01 */ uint8_t type; /* Media code, KODAK68x0_MEDIA_xxx */ uint8_t null[5]; uint8_t count; /* Always 0x04 (6800) or 0x06 (6850)? */ - struct kodak6800_printsize sizes[]; + struct sinfonia_mediainfo_item sizes[]; } __attribute__((packed)); -#define KODAK68x0_MEDIA_6R 0x0b // 197-4096 -#define KODAK68x0_MEDIA_UNK 0x03 -#define KODAK68x0_MEDIA_6TR2 0x2c // 396-2941 -#define KODAK68x0_MEDIA_NONE 0x00 -/* 6R: Also seen: 101-0867, 141-9597, 659-9054, 169-6418, DNP 900-060 */ - #define CMDBUF_LEN 17 /* Private data structure */ -struct kodak6800_printjob { - struct kodak6800_hdr hdr; - uint8_t *databuf; - int datalen; - int copies; -}; - struct kodak6800_ctx { struct libusb_device_handle *dev; uint8_t endp_up; uint8_t endp_down; int type; + int supports_sub4x6; uint8_t jobid; - struct kodak68x0_media_readback *media; + struct sinfonia_mediainfo_item sizes[MAX_MEDIAS]; + uint8_t media_count; + uint8_t media_type; + + struct kodak68x0_status_readback sts; struct marker marker; }; -static const char *kodak68xx_mediatypes(int type) -{ - switch(type) { - case KODAK68x0_MEDIA_NONE: - return "No media"; - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: - return "Kodak 6R"; - default: - return "Unknown"; - } - return "Unknown"; -} - /* Baseline commands */ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx, - void *cmd, int cmd_len, - void *resp, int resp_len, - int *actual_len) + void *cmd, int cmd_len, + void *resp, int resp_len, + int *actual_len) { int ret; @@ -280,66 +143,82 @@ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx, return 0; } -static void kodak68x0_dump_mediainfo(struct kodak68x0_media_readback *media) +static void kodak68x0_dump_mediainfo(struct sinfonia_mediainfo_item *sizes, + uint8_t media_count, uint8_t media_type) { int i; - if (media->type == KODAK68x0_MEDIA_NONE) { + + if (media_type == KODAK6_MEDIA_NONE) { INFO("No Media Loaded\n"); return; } + kodak6_dumpmediacommon(media_type); - switch (media->type) { - case KODAK68x0_MEDIA_6R: - INFO("Media type: 6R (Kodak 197-4096 or equivalent)\n"); - break; - case KODAK68x0_MEDIA_6TR2: - INFO("Media type: 6R (Kodak 396-2941 or equivalent)\n"); - break; - default: - INFO("Media type %02x (unknown, please report!)\n", media->type); - break; - } INFO("Legal print sizes:\n"); - for (i = 0 ; i < media->count ; i++) { - INFO("\t%d: %dx%d (%02x) %s\n", i, - be16_to_cpu(media->sizes[i].width), - be16_to_cpu(media->sizes[i].height), - media->sizes[i].code, - media->sizes[i].code2? "Disallowed?" : ""); + for (i = 0 ; i < media_count ; i++) { + INFO("\t%d: %dx%d (%02x)\n", i, + sizes[i].columns, + sizes[i].rows, + sizes[i].method); } INFO("\n"); } -static int kodak6800_get_mediainfo(struct kodak6800_ctx *ctx, struct kodak68x0_media_readback *media) +#define MAX_MEDIA_LEN (sizeof(struct kodak68x0_media_readback) + MAX_MEDIAS * sizeof(struct sinfonia_mediainfo_item)) + +static int kodak6800_get_mediainfo(struct kodak6800_ctx *ctx) { + struct kodak68x0_media_readback *media; uint8_t req[16]; - int ret, num; + int ret, num, i, j; memset(req, 0, sizeof(req)); - memset(media, 0, sizeof(*media)); + media = malloc(MAX_MEDIA_LEN); + if (!media) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } - req[0] = 0x03; - req[1] = 0x1b; - req[2] = 0x43; - req[3] = 0x48; - req[4] = 0x43; - req[5] = 0x1a; - req[6] = 0x00; /* This can be non-zero for additional "banks" */ + for (j = 0 ; j < 2 ; j ++) { + memset(media, 0, sizeof(*media)); - /* Issue command and get response */ - if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - media, MAX_MEDIA_LEN, - &num))) - return ret; + req[0] = 0x03; + req[1] = 0x1b; + req[2] = 0x43; + req[3] = 0x48; + req[4] = 0x43; + req[5] = 0x1a; + req[6] = j; - /* Validate proper response */ - if (media->hdr != CMD_CODE_OK || - media->null[0] != 0x00) { - ERROR("Unexpected response from media query!\n"); - return CUPS_BACKEND_STOP; + /* Issue command and get response */ + if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), + media, MAX_MEDIA_LEN, + &num))) { + free(media); + return ret; + } + + /* Validate proper response */ + if (media->hdr != CMD_CODE_OK || + media->null[0] != 0x00) { + ERROR("Unexpected response from media query!\n"); + free(media); + return CUPS_BACKEND_STOP; + } + ctx->media_type = media->type; + + for (i = 0; i < media->count ; i++) { + memcpy(&ctx->sizes[ctx->media_count], &media->sizes[i], sizeof(struct sinfonia_mediainfo_item)); + ctx->sizes[ctx->media_count].rows = be16_to_cpu(ctx->sizes[ctx->media_count].rows); + ctx->sizes[ctx->media_count].columns = be16_to_cpu(ctx->sizes[ctx->media_count].columns); + ctx->media_count++; + } + if (i < 6) + break; } - return 0; + free(media); + return CUPS_BACKEND_OK; } static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, @@ -347,7 +226,6 @@ static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, { uint8_t req[16]; int ret, num; - struct kodak68x0_status_readback sts; memset(req, 0, sizeof(req)); @@ -361,12 +239,12 @@ static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, /* Issue command and get response */ if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - &sts, sizeof(sts), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; /* Validate proper response */ - if (sts.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from job cancel!\n"); return -99; } @@ -378,7 +256,6 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) { uint8_t req[16]; int ret, num; - struct kodak68x0_status_readback sts; memset(req, 0, sizeof(req)); @@ -390,12 +267,12 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) /* Issue command and get response */ if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - &sts, sizeof(sts), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; /* Validate proper response */ - if (sts.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from job cancel!\n"); return -99; } @@ -403,153 +280,6 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) return 0; } - -/* Structure dumps */ -static char *kodak68x0_status_str(struct kodak68x0_status_readback *resp) -{ - switch(resp->status1) { - case STATE_STATUS1_STANDBY: - return "Standby (Ready)"; - case STATE_STATUS1_WAIT: - switch (be32_to_cpu(resp->status2)) { - case WAIT_STATUS2_INIT: - return "Wait (Initializing)"; - case WAIT_STATUS2_RIBBON: - return "Wait (Ribbon Winding)"; - case WAIT_STATUS2_THERMAL: - return "Wait (Thermal Protection)"; - case WAIT_STATUS2_OPERATING: - return "Wait (Operating)"; - case WAIT_STATUS2_BUSY: - return "Wait (Busy)"; - default: - return "Wait (Unknown)"; - } - case STATE_STATUS1_ERROR: - switch (be32_to_cpu(resp->status2)) { - case ERROR_STATUS2_CTRL_CIRCUIT: - switch (resp->errcode) { - case CTRL_CIR_ERROR_EEPROM1: - return "Error (EEPROM1)"; - case CTRL_CIR_ERROR_EEPROM2: - return "Error (EEPROM2)"; - case CTRL_CIR_ERROR_DSP: - return "Error (DSP)"; - case CTRL_CIR_ERROR_CRC_MAIN: - return "Error (Main CRC)"; - case CTRL_CIR_ERROR_DL_MAIN: - return "Error (Main Download)"; - case CTRL_CIR_ERROR_CRC_DSP: - return "Error (DSP CRC)"; - case CTRL_CIR_ERROR_DL_DSP: - return "Error (DSP Download)"; - case CTRL_CIR_ERROR_ASIC: - return "Error (ASIC)"; - case CTRL_CIR_ERROR_DRAM: - return "Error (DRAM)"; - case CTRL_CIR_ERROR_DSPCOMM: - return "Error (DSP Communincation)"; - default: - return "Error (Unknown Circuit)"; - } - case ERROR_STATUS2_MECHANISM_CTRL: - switch (resp->errcode) { - case MECH_ERROR_HEAD_UP: - return "Error (Head Up Mechanism)"; - case MECH_ERROR_HEAD_DOWN: - return "Error (Head Down Mechanism)"; - case MECH_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Mechanism)"; - case MECH_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Mechanism)"; - case MECH_ERROR_SUB_PINCH_UP: - return "Error (Sub Pinch Up Mechanism)"; - case MECH_ERROR_SUB_PINCH_DOWN: - return "Error (Sub Pinch Down Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_UP: - return "Error (Feed-in Pinch Up Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_DOWN: - return "Error (Feed-in Pinch Down Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_UP: - return "Error (Feed-out Pinch Up Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_DOWN: - return "Error (Feed-out Pinch Down Mechanism)"; - case MECH_ERROR_CUTTER_LR: - return "Error (Left->Right Cutter)"; - case MECH_ERROR_CUTTER_RL: - return "Error (Right->Left Cutter)"; - default: - return "Error (Unknown Mechanism)"; - } - case ERROR_STATUS2_SENSOR: - switch (resp->errcode) { - case SENSOR_ERROR_CUTTER: - return "Error (Cutter Sensor)"; - case SENSOR_ERROR_HEAD_DOWN: - return "Error (Head Down Sensor)"; - case SENSOR_ERROR_HEAD_UP: - return "Error (Head Up Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Sensor)"; - case SENSOR_ERROR_FEED_PINCH_DOWN: - return "Error (Feed Pinch Down Sensor)"; - case SENSOR_ERROR_FEED_PINCH_UP: - return "Error (Feed Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_DOWN: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_UP: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_LEFT_CUTTER: - return "Error (Left Cutter Sensor)"; - case SENSOR_ERROR_RIGHT_CUTTER: - return "Error (Right Cutter Sensor)"; - case SENSOR_ERROR_CENTER_CUTTER: - return "Error (Center Cutter Sensor)"; - case SENSOR_ERROR_UPPER_CUTTER: - return "Error (Upper Cutter Sensor)"; - case SENSOR_ERROR_PAPER_FEED_COVER: - return "Error (Paper Feed Cover)"; - default: - return "Error (Unknown Sensor)"; - } - case ERROR_STATUS2_COVER_OPEN: - switch (resp->errcode) { - case COVER_OPEN_ERROR_UPPER: - return "Error (Upper Cover Open)"; - case COVER_OPEN_ERROR_LOWER: - return "Error (Lower Cover Open)"; - default: - return "Error (Unknown Cover Open)"; - } - case ERROR_STATUS2_TEMP_SENSOR: - switch (resp->errcode) { - case TEMP_SENSOR_ERROR_HEAD_HIGH: - return "Error (Head Temperature High)"; - case TEMP_SENSOR_ERROR_HEAD_LOW: - return "Error (Head Temperature Low)"; - case TEMP_SENSOR_ERROR_ENV_HIGH: - return "Error (Environmental Temperature High)"; - case TEMP_SENSOR_ERROR_ENV_LOW: - return "Error (Environmental Temperature Low)"; - default: - return "Error (Unknown Temperature)"; - } - case ERROR_STATUS2_PAPER_JAM: - return "Error (Paper Jam)"; - case ERROR_STATUS2_PAPER_EMPTY: - return "Error (Paper Empty)"; - case ERROR_STATUS2_RIBBON_ERR: - return "Error (Ribbon)"; - default: - return "Error (Unknown)"; - } - default: - return "Unknown!"; - } -} - static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_status_readback *status) { char *detail; @@ -568,8 +298,8 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st INFO("Printer Status : %s\n", detail); INFO("Printer State : %s # %02x %08x %02x\n", - kodak68x0_status_str(status), - status->status1, be32_to_cpu(status->status2), status->errcode); + sinfonia_1x45_status_str(status->status1, status->status2, status->errcode), + status->status1, status->status2, status->errcode); INFO("Bank 1 ID: %u\n", status->b1_jobid); INFO("\tPrints: %d/%d complete\n", @@ -604,9 +334,9 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st INFO("\tMedia : %u\n", be32_to_cpu(status->media)); - switch(ctx->media->type) { - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: + switch(ctx->media_type) { + case KODAK6_MEDIA_6R: + case KODAK6_MEDIA_6TR2: max = 375; break; default: @@ -615,7 +345,7 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st } if (max) { - INFO("\t Remaining : %d\n", max - be32_to_cpu(status->media)); + INFO("\t Remaining : %u\n", max - be32_to_cpu(status->media)); } else { INFO("\t Remaining : Unknown\n"); } @@ -654,11 +384,12 @@ static int kodak6800_get_status(struct kodak6800_ctx *ctx, return -99; } + /* Byteswap important stuff */ + status->status2 = be32_to_cpu(status->status2); + return 0; } - -#define UPDATE_SIZE 1536 static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) { uint8_t cmdbuf[16]; @@ -666,7 +397,7 @@ static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) int ret, num = 0; int i; - uint16_t *data = malloc(UPDATE_SIZE); + uint16_t *data = malloc(TONE_CURVE_SIZE); if (!data) { ERROR("Memory Allocation Failure\n"); return -1; @@ -745,7 +476,7 @@ static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) for (i = 0 ; i < 768; i++) { /* Byteswap appropriately */ data[i] = cpu_to_be16(le16_to_cpu(data[i])); - write(tc_fd, &data[i], sizeof(uint16_t)); + ret = write(tc_fd, &data[i], sizeof(uint16_t)); } close(tc_fd); } @@ -764,7 +495,7 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) int ret, num = 0; int remain; - uint16_t *data = malloc(UPDATE_SIZE); + uint16_t *data = malloc(TONE_CURVE_SIZE); uint8_t *ptr; if (!data) { @@ -775,19 +506,13 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) INFO("Set Tone Curve from '%s'\n", fname); /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) { - ret = -2; + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) { + ERROR("Failed to read Tone Curve file\n"); goto done; } - close(tc_fd); /* Byteswap data to printer's format */ - for (ret = 0; ret < (UPDATE_SIZE)/2 ; ret++) { + for (ret = 0; ret < (TONE_CURVE_SIZE)/2 ; ret++) { data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); } @@ -828,7 +553,7 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) } ptr = (uint8_t*) data; - remain = UPDATE_SIZE; + remain = TONE_CURVE_SIZE; while (remain > 0) { int count = remain > 63 ? 63 : remain; @@ -971,16 +696,15 @@ static int kodak6800_cmdline_arg(void *vctx, int argc, char **argv) j = kodak6800_set_tonecurve(ctx, optarg); break; case 'm': - kodak68x0_dump_mediainfo(ctx->media); + kodak68x0_dump_mediainfo(ctx->sizes, ctx->media_count, ctx->media_type); break; case 'R': kodak68x0_reset(ctx); break; case 's': { - struct kodak68x0_status_readback status; - j = kodak6800_get_status(ctx, &status); + j = kodak6800_get_status(ctx, &ctx->sts); if (!j) - kodak68x0_dump_status(ctx, &status); + kodak68x0_dump_status(ctx, &ctx->sts); break; } case 'X': @@ -1005,8 +729,6 @@ static void *kodak6800_init(void) } memset(ctx, 0, sizeof(struct kodak6800_ctx)); - ctx->media = malloc(MAX_MEDIA_LEN); - return ctx; } @@ -1026,51 +748,57 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev, int ty ctx->jobid++; if (test_mode < TEST_MODE_NOATTACH) { + /* Query printer status */ + if (kodak6800_get_status(ctx, &ctx->sts)) { + ERROR("Can't query status\n"); + return CUPS_BACKEND_FAILED; + } + uint16_t fw = be16_to_cpu(ctx->sts.main_fw); + if (ctx->type == P_KODAK_6850) { + if ((fw >= 878) || + (fw < 800 && fw >= 678)) { + ctx->supports_sub4x6 = 1; + } else { + WARNING("Printer FW out of date, recommend updating for current media and features\n"); + } + } else { + if ((fw >= 459) || + (fw < 400 && fw >= 359) || + (fw < 300 && fw >= 259)) { + ctx->supports_sub4x6 = 1; + } else { + WARNING("Printer FW out of date, recommend updating for current media and features\n"); + } + } + /* Query media info */ - if (kodak6800_get_mediainfo(ctx, ctx->media)) { + if (kodak6800_get_mediainfo(ctx)) { ERROR("Can't query media\n"); return CUPS_BACKEND_FAILED; } } else { - int media_code = KODAK68x0_MEDIA_6TR2; + int media_code = KODAK6_MEDIA_6TR2; if (getenv("MEDIA_CODE")) media_code = atoi(getenv("MEDIA_CODE")); - ctx->media->type = media_code; + ctx->media_type = media_code; + ctx->supports_sub4x6 = 1; } ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = kodak68xx_mediatypes(ctx->media->type); + ctx->marker.name = kodak6_mediatypes(ctx->media_type); ctx->marker.levelmax = 100; /* Ie percentage */ ctx->marker.levelnow = -2; return CUPS_BACKEND_OK; } -static void kodak6800_cleanup_job(const void *vjob) -{ - const struct kodak6800_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void kodak6800_teardown(void *vctx) { - struct kodak6800_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct kodak6800_ctx *ctx = vctx; int ret; - struct kodak6800_printjob *job = NULL; + struct kodak6800_hdr hdr; + struct sinfonia_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1083,31 +811,51 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int memset(job, 0, sizeof(*job)); /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - if (ret == 0) + ret = read(data_fd, &hdr, sizeof(hdr)); + if (ret < 0 || ret != sizeof(hdr)) { + if (ret == 0) { + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; + } ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); + ret, 0, (int)sizeof(hdr)); perror("ERROR: Read failed"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } - if (job->hdr.hdr[0] != 0x03 || - job->hdr.hdr[1] != 0x1b || - job->hdr.hdr[2] != 0x43 || - job->hdr.hdr[3] != 0x48 || - job->hdr.hdr[4] != 0x43) { + if (hdr.hdr[0] != 0x03 || + hdr.hdr[1] != 0x1b || + hdr.hdr[2] != 0x43 || + hdr.hdr[3] != 0x48 || + hdr.hdr[4] != 0x43) { ERROR("Unrecognized data format!\n"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } - job->datalen = be16_to_cpu(job->hdr.rows) * be16_to_cpu(job->hdr.columns) * 3; + uint16_t rows = be16_to_cpu(hdr.rows); + uint16_t cols = be16_to_cpu(hdr.columns); + if (rows != 1240 && rows != 2434 && rows != 2140 && !ctx->supports_sub4x6) { + ERROR("Printer Firmware does not support non-4x6/8x6/5x7 prints, please upgrade!\n"); + sinfonia_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + + job->datalen = rows * cols * 3; job->databuf = malloc(job->datalen); if (!job->databuf) { ERROR("Memory allocation failure!\n"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_RETRY_CURRENT; } + /* Windows driver only sends 634 rows of data, work around */ + if (rows == 636 && hdr.size == 6 && hdr.method == 0) { + rows = 634; + job->datalen -= 1844*2*3; + } + + /* Read in the spool data */ { int remain = job->datalen; uint8_t *ptr = job->databuf; @@ -1117,6 +865,7 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int ERROR("Read failed (%d/%d/%d)\n", ret, remain, job->datalen); perror("ERROR: Read failed"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } ptr += ret; @@ -1124,13 +873,47 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int } while (remain); } - /* Fix max print count. */ - if (copies > 9999) // XXX test against remaining media - copies = 9999; + /* Undo the Windows workaround... */ + if (rows == 634) { + rows = 636; + job->datalen += 1844*2*3; + } + + /* Perform some header re-jiggery */ + if (hdr.size == 0) { + if (cols == 1844) + hdr.size = 6; + else if (cols == 1548) + hdr.size = 7; + } + if (hdr.method == 0) { + if (rows == 636) { + hdr.method = 0x21; + } else if (rows == 936) { + hdr.method = 0x23; + } else if (rows == 1240) { + hdr.method = 0x01; + } else if (rows == 1282) { + hdr.method = 0x20; + } else if (rows == 1882) { + hdr.method = 0x22; + } else if (rows == 2490) { + hdr.method = 0x2; + } + } + + hdr.copies = be16_to_cpu(hdr.copies); + hdr.copies = packed_bcd_to_uint32((char*)&hdr.copies, 2); + if (hdr.copies > 1) + copies = hdr.copies; - /* Printer handles generating copies.. */ - if (le16_to_cpu(job->hdr.copies) < copies) - job->hdr.copies = cpu_to_be16(uint16_to_packed_bcd(copies)); + /* Fill out job structure */ + job->jp.copies = copies; + job->jp.rows = rows; + job->jp.columns = cols; + job->jp.media = hdr.size; + job->jp.oc_mode = hdr.laminate; + job->jp.method = hdr.method; *vjob = job; @@ -1139,28 +922,27 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int static int kodak6800_main_loop(void *vctx, const void *vjob) { struct kodak6800_ctx *ctx = vctx; - struct kodak68x0_status_readback status; int num, ret; + int copies; - const struct kodak6800_printjob *job = vjob; + const struct sinfonia_printjob *job = vjob; if (!ctx) return CUPS_BACKEND_FAILED; if (!job) return CUPS_BACKEND_FAILED; - struct kodak6800_hdr hdr; - memcpy(&hdr, &job->hdr, sizeof(hdr)); + copies = job->jp.copies; /* Validate against supported media list */ - for (num = 0 ; num < ctx->media->count; num++) { - if (ctx->media->sizes[num].height == hdr.rows && - ctx->media->sizes[num].width == hdr.columns && - ctx->media->sizes[num].code2 == 0x00) // XXX code2? + for (num = 0 ; num < ctx->media_count; num++) { + if (ctx->sizes[num].rows == job->jp.rows && + ctx->sizes[num].columns == job->jp.columns && + ctx->sizes[num].method == job->jp.method) break; } - if (num == ctx->media->count) { + if (num == ctx->media_count) { ERROR("Print size unsupported by media!\n"); return CUPS_BACKEND_HOLD; } @@ -1168,28 +950,25 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { INFO("Waiting for printer idle\n"); while(1) { - if (kodak6800_get_status(ctx, &status)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - if (ctx->marker.levelnow != status.donor) { - ctx->marker.levelnow = status.donor; + if (ctx->marker.levelnow != ctx->sts.donor) { + ctx->marker.levelnow = ctx->sts.donor; dump_markers(&ctx->marker, 1, 0); } - if (status.status1 == STATE_STATUS1_ERROR) { + if (ctx->sts.status1 == STATE_STATUS1_ERROR) { INFO("Printer State: %s # %02x %08x %02x\n", - kodak68x0_status_str(&status), - status.status1, be32_to_cpu(status.status2), status.errcode); + sinfonia_1x45_status_str(ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode), + ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode); return CUPS_BACKEND_FAILED; } - if (status.status == STATUS_IDLE) - break; - /* make sure we're not colliding with an existing jobid */ - while (ctx->jobid == status.b1_jobid || - ctx->jobid == status.b2_jobid) { + while (ctx->jobid == ctx->sts.b1_jobid || + ctx->jobid == ctx->sts.b2_jobid) { ctx->jobid++; ctx->jobid &= 0x7f; if (!ctx->jobid) @@ -1197,8 +976,8 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { } /* See if we have an open bank */ - if (!status.b1_remain || - !status.b2_remain) + if (!ctx->sts.b1_remain || + !ctx->sts.b2_remain) break; sleep(1); @@ -1211,25 +990,34 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { return ret; } - hdr.jobid = ctx->jobid; + /* Fix max print count. */ + if (copies > 9999) + copies = 9999; -#if 0 - /* If we want to disable 4x6 rewind on 8x6 media.. */ - // XXX not sure about this...? - if (hdr.size == 0x00 && - be16_to_cpu(ctx->media->sizes[0].width) == 0x0982) { - hdr.size = 0x06; - hdr.mode = 0x01; - } -#endif + /* Fill out printjob header */ + struct kodak6800_hdr hdr; + hdr.hdr[0] = 0x03; + hdr.hdr[1] = 0x1b; + hdr.hdr[2] = 0x43; + hdr.hdr[3] = 0x48; + hdr.hdr[4] = 0x43; + hdr.hdr[5] = 0x0a; + hdr.hdr[6] = 0x00; + hdr.jobid = ctx->jobid; + hdr.copies = uint16_to_packed_bcd(copies); + hdr.columns = cpu_to_be16(job->jp.columns); + hdr.rows = cpu_to_be16(job->jp.rows); + hdr.size = job->jp.media; + hdr.laminate = job->jp.oc_mode; + hdr.method = job->jp.method; INFO("Sending Print Job (internal id %u)\n", ctx->jobid); if ((ret = kodak6800_do_cmd(ctx, (uint8_t*) &hdr, sizeof(hdr), - &status, sizeof(status), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; - if (status.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from print command!\n"); return CUPS_BACKEND_FAILED; } @@ -1243,25 +1031,25 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { INFO("Waiting for printer to acknowledge completion\n"); do { sleep(1); - if (kodak6800_get_status(ctx, &status)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - if (ctx->marker.levelnow != status.donor) { - ctx->marker.levelnow = status.donor; + if (ctx->marker.levelnow != ctx->sts.donor) { + ctx->marker.levelnow = ctx->sts.donor; dump_markers(&ctx->marker, 1, 0); } - if (status.status1 == STATE_STATUS1_ERROR) { + if (ctx->sts.status1 == STATE_STATUS1_ERROR) { INFO("Printer State: %s # %02x %08x %02x\n", - kodak68x0_status_str(&status), - status.status1, be32_to_cpu(status.status2), status.errcode); + sinfonia_1x45_status_str(ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode), + ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode); return CUPS_BACKEND_FAILED; } /* If all prints are complete, we're done! */ - if (status.b1_jobid == hdr.jobid && status.b1_complete == status.b1_total) + if (ctx->sts.b1_jobid == hdr.jobid && ctx->sts.b1_complete == ctx->sts.b1_total) break; - if (status.b2_jobid == hdr.jobid && status.b2_complete == status.b2_total) + if (ctx->sts.b2_jobid == hdr.jobid && ctx->sts.b2_complete == ctx->sts.b2_total) break; if (fast_return) { @@ -1279,13 +1067,12 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { static int kodak6800_query_markers(void *vctx, struct marker **markers, int *count) { struct kodak6800_ctx *ctx = vctx; - struct kodak68x0_status_readback status; /* Query printer status */ - if (kodak6800_get_status(ctx, &status)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - ctx->marker.levelnow = status.donor; + ctx->marker.levelnow = ctx->sts.donor; *markers = &ctx->marker; *count = 1; @@ -1304,14 +1091,13 @@ static const char *kodak6800_prefixes[] = { /* Exported */ struct dyesub_backend kodak6800_backend = { .name = "Kodak 6800/6850", - .version = "0.65", + .version = "0.73" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = kodak6800_prefixes, .cmdline_usage = kodak6800_cmdline, .cmdline_arg = kodak6800_cmdline_arg, .init = kodak6800_init, .attach = kodak6800_attach, - .teardown = kodak6800_teardown, - .cleanup_job = kodak6800_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = kodak6800_read_parse, .main_loop = kodak6800_main_loop, .query_serno = kodak6800_query_serno, @@ -1341,7 +1127,7 @@ struct dyesub_backend kodak6800_backend = { HH HH Number of rows. SS Print size -- 0x00 (4x6) 0x06 (8x6) 0x07 (5x7 on 6850) LL Laminate mode -- 0x00 (off) or 0x01 (on) - UU Print mode -- 0x00 (normal) or (0x01) 4x6 on 8x6 + UU Print mode -- 0x00 (normal) or 0x01 (4x6 on 8x6) 0x21 (2x6) 0x23 (3x6) ************************************************************************ @@ -1366,4 +1152,18 @@ struct dyesub_backend kodak6800_backend = { 00 01 02 1c 00 00 00 00 00 01 00 01 00 00 00 00 00 00 00 + An additional command that's also unknown + +-> 03 1b 43 48 43 4d 01 00 00 00 00 00 00 00 00 00 +<- 01 02 01 00 00 00 00 00 00 00 5d ca 00 00 5d ca + 00 00 00 15 00 00 b8 f8 00 00 00 40 00 03 02 a6 + 00 01 02 31 1e 00 00 00 00 01 00 01 00 00 00 00 + 00 00 00 + + One more note for the 6850. These sizes have been seen: + + 1844x2434, method 0x03 + 1844x2490, method 0x05 + 1844x2222, method 0x00 + */ diff --git a/src/cups/backend_magicard.c b/src/cups/backend_magicard.c index d356bba..64da470 100644 --- a/src/cups/backend_magicard.c +++ b/src/cups/backend_magicard.c @@ -475,15 +475,6 @@ static void magicard_cleanup_job(const void *vjob) free((void*)job); } -static void magicard_teardown(void *vctx) { - struct magicard_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static void downscale_and_extract(int gamma, uint32_t pixels, uint8_t *y_i, uint8_t *m_i, uint8_t *c_i, uint8_t *y_o, uint8_t *m_o, uint8_t *c_o, uint8_t *k_o) @@ -552,7 +543,8 @@ static void downscale_and_extract(int gamma, uint32_t pixels, } } -#define MAX_PRINTJOB_LEN (1016*672*4) + 1024 /* 1016*672 * 4color */ +#define MAX_HEADERS_LEN 2048 +#define MAX_PRINTJOB_LEN (1016*672*4) + MAX_HEADERS_LEN /* 1016*672 * 4color */ #define INITIAL_BUF_LEN 1024 static int magicard_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct magicard_ctx *ctx = vctx; @@ -629,7 +621,10 @@ static int magicard_read_parse(void *vctx, const void **vjob, int data_fd, int c char *ptr; ptr = strtok((char*)initial_buf + ++buf_offset, ",\x1c"); - while (ptr && *ptr != 0x1c) { + while (ptr + && ((ptr - (char*)initial_buf) < INITIAL_BUF_LEN) + && ((ptr - (char*)initial_buf) + strnlen(ptr, INITIAL_BUF_LEN) < INITIAL_BUF_LEN) + && *ptr != 0x1c) { if (!strcmp("X-GP-8", ptr)) { x_gp_8bpp = 1; } else if (!strncmp("TDT", ptr, 3)) { @@ -655,6 +650,13 @@ static int magicard_read_parse(void *vctx, const void **vjob, int data_fd, int c len_k = atoi(ptr + 3); } } else { + /* Safety valve */ + if (strlen(ptr) + job->datalen > MAX_HEADERS_LEN) { + ERROR("headers too long, bogus job!\n"); + magicard_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + /* Everything else goes in */ job->datalen += sprintf((char*)job->databuf + job->datalen, ",%s", ptr); } @@ -843,6 +845,7 @@ static int magicard_read_parse(void *vctx, const void **vjob, int data_fd, int c static int magicard_main_loop(void *vctx, const void *vjob) { struct magicard_ctx *ctx = vctx; int ret; + int copies; const struct magicard_printjob *job = vjob; @@ -945,13 +948,12 @@ static const char *magicard_prefixes[] = { struct dyesub_backend magicard_backend = { .name = "Magicard family", - .version = "0.15", + .version = "0.16", .uri_prefixes = magicard_prefixes, .cmdline_arg = magicard_cmdline_arg, .cmdline_usage = magicard_cmdline, .init = magicard_init, .attach = magicard_attach, - .teardown = magicard_teardown, .cleanup_job = magicard_cleanup_job, .read_parse = magicard_read_parse, .main_loop = magicard_main_loop, diff --git a/src/cups/backend_mitsu70x.c b/src/cups/backend_mitsu70x.c index 154fabb..687caac 100644 --- a/src/cups/backend_mitsu70x.c +++ b/src/cups/backend_mitsu70x.c @@ -324,8 +324,8 @@ struct mitsu70x_status_deck { uint8_t media_brand; uint8_t media_type; uint8_t rsvd_b[2]; - uint16_t capacity; /* media capacity */ - uint16_t remain; /* media remaining */ + int16_t capacity; /* media capacity */ + int16_t remain; /* media remaining */ uint8_t rsvd_c[2]; uint8_t lifetime_prints[4]; /* lifetime prints on deck + 10, in BCD! */ uint8_t rsvd_d[2]; // Unknown @@ -805,6 +805,7 @@ static int mitsu70x_attach(void *vctx, struct libusb_device_handle *dev, int typ resp.upper.media_type = media_code; resp.lower.media_type = media_code; resp.dual_deck = 0x80; /* Make it a dual deck */ + resp.vers[0].ver[0] = 0; } /* Figure out if we're a D707 with two decks */ @@ -833,10 +834,11 @@ static int mitsu70x_attach(void *vctx, struct libusb_device_handle *dev, int typ if (ctx->type == P_KODAK_305) { /* Known versions: v1.02: M 316E81 1433 (Add Ultrafine and matte support) - v1.04: M 316F83 2878 (Add 2x6 strip and support "Triton" media) + v1.04: M 316F83 2878 (Add 2x6 strip and support new "Triton" media) + v3.01: M 443A12 8908 (add 5" media support) */ - if (strncmp(resp.vers[0].ver, "316F83", 6) < 0) - WARNING("Printer FW out of date. Highly recommend upgrading EK305 to v1.04 or newer!\n"); + if (strncmp(resp.vers[0].ver, "443A12", 6) < 0) + WARNING("Printer FW out of date. Highly recommend upgrading EK305 to v3.01 or newer!\n"); } else if (ctx->type == P_MITSU_K60) { /* Known versions: v1.05: M 316M31 148C (Add HG media support) @@ -1295,7 +1297,7 @@ repeat: } if (job->lutfname && ctx->lut) { - DEBUG("Running print data through LUT\n"); + DEBUG("Running print data through 3D LUT\n"); ctx->DoColorConv(ctx->lut, job->spoolbuf, job->cols, job->rows, job->cols * 3, COLORCONV_BGR); } @@ -1721,7 +1723,7 @@ static int mitsu70x_main_loop(void *vctx, const void *vjob) int ret; int copies; - int deck; + int deck, legal, reqdeck; struct mitsu70x_printjob *job = (struct mitsu70x_printjob *) vjob; // XXX not clean. // const struct mitsu70x_printjob *job = vjob; @@ -1734,6 +1736,9 @@ static int mitsu70x_main_loop(void *vctx, const void *vjob) copies = job->copies; hdr = (struct mitsu70x_hdr*) job->databuf; + /* Keep track of deck requested */ + reqdeck = hdr->deck; + if (job->raw_format) goto bypass; @@ -1865,7 +1870,7 @@ top: /* First, try to respect requested deck */ if (ctx->type == P_MITSU_D70X) { - deck = hdr->deck; /* Respect D70 deck choice, 0 is automatic. */ + deck = reqdeck; /* Respect D70 deck choice, 0 is automatic. */ } else { deck = 1; /* All others have one deck only */ } @@ -1901,6 +1906,7 @@ top: job->decks_ok[0], job->decks_ok[1]); /* Okay, we know which decks are _legal_, pick one to use */ + legal = deck; if (deck & 1) { if (jobstatus.temperature == TEMPERATURE_COOLING) { if (ctx->num_decks == 2) @@ -1909,7 +1915,8 @@ top: INFO("Printer cooling down...\n"); deck &= ~1; } else if (jobstatus.error_status[0]) { - ERROR("%s/%s -> %s: %02x/%02x/%02x\n", + ERROR("%s %s/%s -> %s: %02x/%02x/%02x\n", + ctx->num_decks == 2 ? "LOWER:": "", mitsu70x_errorclass(jobstatus.error_status), mitsu70x_errors(jobstatus.error_status), mitsu70x_errorrecovery(jobstatus.error_status), @@ -1917,8 +1924,9 @@ top: jobstatus.error_status[1], jobstatus.error_status[2]); deck &= ~1; + legal &= ~1; /* Deck is offline! */ } else if (jobstatus.mecha_status[0] != MECHA_STATUS_IDLE) { - deck = ~1; + deck &= ~1; } } if (deck & 2) { @@ -1934,8 +1942,9 @@ top: jobstatus.error_status_up[1], jobstatus.error_status_up[2]); deck &= ~2; + legal &= ~2; /* Deck is offline! */ } else if (jobstatus.mecha_status_up[0] != MECHA_STATUS_IDLE) { - deck = ~2; + deck &= ~2; } } @@ -1950,18 +1959,28 @@ top: if (ctx->num_decks > 1) DEBUG("Deck selected: %d\n", deck); + /* Great, we have no decks we can currently print this job on.. */ if (deck == 0) { /* Halt queue if printer is entirely offline */ if (ctx->num_decks == 2) { - if (jobstatus.error_status[0] && jobstatus.error_status_up[0]) + if (jobstatus.error_status[0] && jobstatus.error_status_up[0]) { + ERROR("Both decks offline due to errors\n"); return CUPS_BACKEND_STOP; - // XXX what if we only have one legal deck, and it's unavailable? We don't want to retry indefinitely here.. + } } else { - if (jobstatus.error_status[0]) + if (jobstatus.error_status[0]) { + ERROR("Printer offline due to errors\n"); return CUPS_BACKEND_STOP; + } } - /* No decks available yet, retry */ + /* Hold job if we have no legal decks for it, but printer is online. */ + if (!legal) { + ERROR("Legal deck for printjob has errors, aborting job"); + return CUPS_BACKEND_HOLD; + } + + /* Legal decks are busy, retry */ sleep(1); goto top; } @@ -2085,7 +2104,7 @@ top: return CUPS_BACKEND_FAILED; /* See if we hit a printer error. */ - if (deck == 0) { + if (deck == 1) { if (jobstatus.error_status[0]) { ERROR("%s/%s -> %s: %02x/%02x/%02x\n", mitsu70x_errorclass(jobstatus.error_status), @@ -2094,9 +2113,14 @@ top: jobstatus.error_status[0], jobstatus.error_status[1], jobstatus.error_status[2]); + + /* Retry job on the other deck.. */ + if (ctx->num_decks == 2) + goto top; + return CUPS_BACKEND_STOP; } - } else if (deck == 1) { + } else if (deck == 2) { if (jobstatus.error_status_up[0]) { ERROR("UPPER: %s/%s -> %s: %02x/%02x/%02x\n", mitsu70x_errorclass(jobstatus.error_status_up), @@ -2105,6 +2129,11 @@ top: jobstatus.error_status_up[0], jobstatus.error_status_up[1], jobstatus.error_status_up[2]); + + /* Retry job on the other deck.. */ + if (ctx->num_decks == 2) + goto top; + return CUPS_BACKEND_STOP; } } @@ -2136,16 +2165,20 @@ top: break; } + /* See if we can return early, but wait until printing has started! */ + if (fast_return && copies <= 1 && /* Copies generated by backend! */ + jobstatus.job_status[0] == JOB_STATUS0_PRINT && + jobstatus.job_status[1] > JOB_STATUS1_PRINT_MEDIALOAD) + { + INFO("Fast return mode enabled.\n"); + break; + } + /* On a two deck system, try to use the second deck for additional copies. If we can't use it, we'll block. */ if (ctx->num_decks > 1 && copies > 1) break; - if (fast_return && copies <= 1) { /* Copies generated by backend! */ - INFO("Fast return mode enabled.\n"); - break; - } - /* Update cache for the next round */ memcpy(last_status, jobstatus.job_status, 4); } while(1); @@ -2167,6 +2200,7 @@ static void mitsu70x_dump_printerstatus(struct mitsu70x_ctx *ctx, struct mitsu70x_printerstatus_resp *resp) { uint32_t i; + uint8_t memory = ~resp->memory; INFO("Model : "); for (i = 0 ; i < 6 ; i++) { @@ -2198,6 +2232,15 @@ static void mitsu70x_dump_printerstatus(struct mitsu70x_ctx *ctx, INFO("Standby Timeout: %d minutes\n", resp->sleeptime); INFO("iSerial Reporting: %s\n", resp->iserial ? "No" : "Yes" ); INFO("Power Status: %s\n", resp->power ? "Sleeping" : "Awake"); + INFO("Available Memory Banks: %s%s%s%s%s%s%s%s\n", + (memory & 0x01) ? "mem8 " : "", + (memory & 0x02) ? "mem7 " : "", + (memory & 0x04) ? "mem6 " : "", + (memory & 0x08) ? "mem5 " : "", + (memory & 0x10) ? "mem4 " : "", + (memory & 0x20) ? "mem3 " : "", + (memory & 0x40) ? "mem2 " : "", + (memory & 0x80) ? "mem1 " : ""); if (resp->lower.error_status[0]) { INFO("Lower Error Status: %s/%s -> %s\n", @@ -2292,6 +2335,7 @@ static int mitsu70x_query_jobs(struct mitsu70x_ctx *ctx) } INFO("Temperature: %s\n", mitsu70x_temperatures(jobstatus.temperature)); } + // memory status? #if 0 @@ -2354,7 +2398,6 @@ static void mitsu70x_cmdline(void) DEBUG("\t\t[ -j ] # Query job status\n"); DEBUG("\t\t[ -w ] # Wake up printer\n"); DEBUG("\t\t[ -W ] # Wake up printer and wait\n"); - DEBUG("\t\t[ -f ] # Use fast return mode\n"); DEBUG("\t\t[ -k num ] # Set standby time (1-60 minutes, 0 disables)\n"); DEBUG("\t\t[ -x num ] # Set USB iSerialNumber Reporting (1 on, 0 off)\n"); DEBUG("\t\t[ -X jobid ] # Abort a printjob\n");} @@ -2437,7 +2480,7 @@ static int mitsu70x_query_markers(void *vctx, struct marker **markers, int *coun static const char *mitsu70x_prefixes[] = { "mitsu70x", // Family entry, do not nuke. - "mitsubishi-d70dw", "mitsubishi-d80dw", "mitsubishi-k60dw", "kodak-305", "fujifilm-ask-300" + "mitsubishi-d70dw", "mitsubishi-d80dw", "mitsubishi-k60dw", "kodak-305", "fujifilm-ask-300", // Extras "mitsubishi-d707dw", "mitsubishi-k60dws", // backwards compatibility @@ -2448,7 +2491,7 @@ static const char *mitsu70x_prefixes[] = { /* Exported */ struct dyesub_backend mitsu70x_backend = { .name = "Mitsubishi CP-D70 family", - .version = "0.88", + .version = "0.95", .uri_prefixes = mitsu70x_prefixes, .flags = BACKEND_FLAG_JOBLIST, .cmdline_usage = mitsu70x_cmdline, @@ -2471,7 +2514,7 @@ struct dyesub_backend mitsu70x_backend = { } }; -/* Mitsubish CP-D70DW/D707DW/K60DW-S/D80DW, Kodak 305, Fuji ASK-300 +/* Mitsubish CP-D70DW/D707DW/K60DW-S/D80DW, Kodak 305, Fujifilm ASK-300 data format: Spool file consists of two headers followed by three image planes diff --git a/src/cups/backend_mitsu9550.c b/src/cups/backend_mitsu9550.c index ab7530a..98473ca 100644 --- a/src/cups/backend_mitsu9550.c +++ b/src/cups/backend_mitsu9550.c @@ -1,7 +1,7 @@ /* * Mitsubishi CP-9xxx Photo Printer Family CUPS backend * - * (c) 2014-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2014-2019 Solomon Peachy <pizza@shaftnet.org> * * The latest version of this program can be found at: * @@ -43,21 +43,59 @@ #define BACKEND mitsu9550_backend + +#if defined(USE_DLOPEN) +#define WITH_DYNAMIC +#include <dlfcn.h> +#define DL_INIT() do {} while(0) +#define DL_OPEN(__x) dlopen(__x, RTLD_NOW) +#define DL_SYM(__x, __y) dlsym(__x, __y) +#define DL_CLOSE(__x) dlclose(__x) +#define DL_EXIT() do {} while(0) +#elif defined(USE_LTDL) +#define WITH_DYNAMIC +#include <ltdl.h> +#define DL_INIT() lt_dlinit() +#define DL_OPEN(__x) lt_dlopen(__x) +#define DL_SYM(__x, __y) lt_dlsym(__x, __y) +#define DL_CLOSE(__x) do {} while(0) +#define DL_EXIT() lt_dlexit() +#else +#define DL_INIT() do {} while(0) +#define DL_CLOSE(__x) do {} while(0) +#define DL_EXIT() do {} while(0) +#warning "No dynamic loading support!" +#endif + #include "backend_common.h" -#define USB_VID_MITSU 0x06D3 -#define USB_PID_MITSU_9500D 0x0393 -#define USB_PID_MITSU_9000D 0x0394 -#define USB_PID_MITSU_9000AM 0x0395 -#define USB_PID_MITSU_9550D 0x03A1 -#define USB_PID_MITSU_9550DS 0x03A5 // or DZ/DZS/DZU -#define USB_PID_MITSU_9600D 0x03A9 -//#define USB_PID_MITSU_9600DS XXXXXX -#define USB_PID_MITSU_9800D 0x03AD -#define USB_PID_MITSU_9800DS 0x03AE -#define USB_PID_MITSU_98__D 0x3B21 -//#define USB_PID_MITSU_9810D XXXXXX -//#define USB_PID_MITSU_9820DS XXXXXX +// #include "lib70x/libMitsuD70ImageReProcess.h" + +#ifndef LUT_LEN +#define COLORCONV_RGB 0 +#define COLORCONV_BGR 1 + +#define LUT_LEN 14739 +struct BandImage { + void *imgbuf; + int32_t bytes_per_row; + uint16_t origin_cols; + uint16_t origin_rows; + uint16_t cols; + uint16_t rows; +}; +#endif + +#define REQUIRED_LIB_APIVERSION 4 + +/* Image processing library function prototypes */ +#define LIB_NAME_RE "libMitsuD70ImageReProcess.so" // Reimplemented library + +typedef int (*lib70x_getapiversionFN)(void); +typedef int (*Get3DColorTableFN)(uint8_t *buf, const char *filename); +typedef struct CColorConv3D *(*Load3DColorTableFN)(const uint8_t *ptr); +typedef void (*Destroy3DColorTableFN)(struct CColorConv3D *this); +typedef void (*DoColorConvFN)(struct CColorConv3D *this, uint8_t *data, uint16_t cols, uint16_t rows, uint32_t bytes_per_row, int rgb_bgr); #ifndef CORRTABLE_PATH #ifdef PACKAGE_DATA_DIR @@ -73,80 +111,90 @@ #define LAMINATE_STRIDE 1868 #define DATATABLE_SIZE 42204 +/* USB VIDs and PIDs */ + +#define USB_VID_MITSU 0x06D3 +#define USB_PID_MITSU_9500D 0x0393 +#define USB_PID_MITSU_9000D 0x0394 +#define USB_PID_MITSU_9000AM 0x0395 +#define USB_PID_MITSU_9550D 0x03A1 +#define USB_PID_MITSU_9550DS 0x03A5 // or DZ/DZS/DZU +#define USB_PID_MITSU_9600D 0x03A9 +//#define USB_PID_MITSU_9600DS XXXXXX +#define USB_PID_MITSU_9800D 0x03AD +#define USB_PID_MITSU_9800DS 0x03AE +#define USB_PID_MITSU_98__D 0x3B21 +//#define USB_PID_MITSU_9810D XXXXXX +//#define USB_PID_MITSU_9820DS XXXXXX + /* Spool file structures */ /* Print parameters1 */ struct mitsu9550_hdr1 { - uint8_t cmd[4]; /* 1b 57 20 2e */ + uint8_t cmd[4]; /* 1b 57 20 2e */ uint8_t unk[10]; /* 00 0a 10 00 [...] */ - uint16_t cols; /* BE */ - uint16_t rows; /* BE */ - uint8_t matte; /* CP9810/9820 only. 01 for matte, 00 glossy */ + uint16_t cols; /* BE */ + uint16_t rows; /* BE */ + uint8_t matte; /* CP9810/9820 only. 01 for matte, 00 glossy */ uint8_t null[31]; } __attribute__((packed)); /* Print parameters2 */ struct mitsu9550_hdr2 { - uint8_t cmd[4]; /* 1b 57 21 2e */ - uint8_t unk[24]; /* 00 80 00 22 08 03 [...] */ - uint16_t copies; /* BE, 1-680 */ + uint8_t cmd[4]; /* 1b 57 21 2e */ + uint8_t unk[24]; /* 00 80 00 22 08 03 [...] */ + uint16_t copies; /* BE, 1-680 */ uint8_t null[2]; - uint8_t cut; /* 00 == normal, 83 == 2x6*2 */ + uint8_t cut; /* 00 == normal, 83 == 2x6*2 */ uint8_t unkb[5]; - uint8_t mode; /* 00 == fine, 80 == superfine */ + uint8_t mode; /* 00 == fine, 80 == superfine */ uint8_t unkc[11]; /* 00 [...] 00 01 */ } __attribute__((packed)); /* Fine Deep selection (9550 only) */ struct mitsu9550_hdr3 { - uint8_t cmd[4]; /* 1b 57 22 2e */ - uint8_t unk[7]; /* 00 40 00 [...] */ - uint8_t mode2; /* 00 == normal, 01 == finedeep */ + uint8_t cmd[4]; /* 1b 57 22 2e */ + uint8_t unk[7]; /* 00 40 00 [...] */ + uint8_t mode2; /* 00 == normal, 01 == finedeep */ uint8_t null[38]; } __attribute__((packed)); /* Error policy? */ struct mitsu9550_hdr4 { - uint8_t cmd[4]; /* 1b 57 26 2e */ - uint8_t unk[46]; /* 00 70 00 00 00 00 00 00 01 01 00 [...] */ + uint8_t cmd[4]; /* 1b 57 26 2e */ + uint8_t unk[46]; /* 00 70 00 00 00 00 00 00 01 01 00 [...] */ } __attribute__((packed)); /* Data plane header */ struct mitsu9550_plane { - uint8_t cmd[4]; /* 1b 5a 54 XX */ /* XX == 0x10 if 16bpp, 0x00 for 8bpp */ + uint8_t cmd[4]; /* 1b 5a 54 XX */ /* XX == 0x10 if 16bpp, 0x00 for 8bpp */ uint16_t col_offset; /* BE, normally 0, where we start dumping data */ uint16_t row_offset; /* BE, normally 0, where we start dumping data */ uint16_t cols; /* BE */ uint16_t rows; /* BE */ } __attribute__((packed)); -/* CP98xx Tabular Data */ +/* CP98xx Tabular Data, as stored in data file! */ struct mitsu98xx_data { - uint16_t GNMby[256]; // @0 - uint16_t GNMgm[256]; // @512 - uint16_t GNMrc[256]; // @1024 - double GammaParams[3]; // @1536 - uint8_t KH[2048]; // @1560 - uint32_t unk_b[3]; // @3608 - - struct { - double unka[256]; // @0 - double unkb[256]; // @2048 - uint32_t unkc[10]; // @4096 - double unkd[256]; // @4136 - double unke[256]; // @6184 // *= sharp->coef[X] - uint32_t unkf[10]; // @8232 - double unkg[256]; // @8272 - // @10320 - } WMAM; // @3620 - uint8_t unc_d[4]; // @13940 @10320 (from wmam start) - struct { - uint32_t unk_a; // @13944/10324 (padding?) - double coef[10]; // @13948/10328 (sharpness coefficients, level 0-9) - uint32_t unk_b[5]; // @14028/10408 - } sharp; // total 104, @13944/10324 - uint8_t unk_e[20]; // @14048/10428 - // @14068/10448 + /* @ 0 */ uint16_t GNMby[256]; /* BGR Order uncertain */ + /* @ 512 */ uint16_t GNMgm[256]; + /* @ 1024 */ uint16_t GNMrc[256]; + /* @ 1536 */ uint16_t unk_sharp[20]; /* Actual format is: u16, u16[9], u16, u16[9] */ + /* @ 1576 */ double GammaAdj[3]; /* Assumed to be same order as tables (BGR?) */ + /* @ 1600 */ struct { + /* @ 0 */ double unka[256]; + /* @ 2048 */ double unkb[256]; + /* @ 4096 */ uint32_t unkc[10]; + /* @ 4136 */ double unkd[256]; + /* @ 6184 */ double unke[256]; // *= sharp->coef[X] + /* @ 8232 */ uint32_t unkf[10]; + /* @ 8272 */ double unkg[256]; + /* @10320 */ + } WMAM; + /* @11920 */ double sharp_coef[11]; /* 0 is off, 1-10 are the levels. Default is 5. [4 in settings] */ + /* @12008 */ uint32_t unk_kh[3]; + /* @12020 */ uint8_t KH[2048]; + /* @14068 */ } __attribute__((packed)); struct mitsu98xx_tables { @@ -194,8 +242,15 @@ struct mitsu9550_ctx { struct marker marker; /* CP98xx stuff */ - struct mitsu98xx_tables *m98xxdata; + void *dl_handle; + lib70x_getapiversionFN GetAPIVersion; + Get3DColorTableFN Get3DColorTable; + Load3DColorTableFN Load3DColorTable; + Destroy3DColorTableFN Destroy3DColorTable; + DoColorConvFN DoColorConv; + struct CColorConv3D *lut; + struct mitsu98xx_tables *m98xxdata; }; /* Printer data structures */ @@ -290,11 +345,9 @@ static void mitsu98xx_dogamma(uint8_t *src, uint16_t *dest, uint8_t plane, { src += plane; while(len--) { - *dest++ = table[*src]; + *dest++ = cpu_to_be16(table[*src]); src += 3; } - /* TODO: Eventually, when we do real processing of this data, we will need to - have the gamma table in native endian format and generate BE data at the end. */ } static int mitsu98xx_fillmatte(struct mitsu9550_printjob *job) @@ -302,7 +355,7 @@ static int mitsu98xx_fillmatte(struct mitsu9550_printjob *job) int fd, i; uint32_t j, remain; - DEBUG("Reading %d bytes of matte data from disk (%d/%d)\n", job->cols * job->rows, job->cols, LAMINATE_STRIDE); + DEBUG("Reading %d bytes of matte data from disk (%d/%d)\n", job->cols * job->rows * 2, job->cols, LAMINATE_STRIDE); fd = open(MITSU_M98xx_LAMINATE_FILE, O_RDONLY); if (fd < 0) { WARNING("Unable to open matte lamination data file '%s'\n", MITSU_M98xx_LAMINATE_FILE); @@ -318,8 +371,8 @@ static int mitsu98xx_fillmatte(struct mitsu9550_printjob *job) matte->cmd[3] = 0x10; matte->row_offset = 0; matte->col_offset = 0; - matte->cols = job->hdr1.cols; - matte->rows = job->hdr1.rows; + matte->cols = cpu_to_be16(job->hdr1.cols); + matte->rows = cpu_to_be16(job->hdr1.rows); job->datalen += sizeof(struct mitsu9550_plane); /* Read in the matte data plane */ @@ -355,173 +408,12 @@ done: return CUPS_BACKEND_OK; } -/*** 3D color Lookup table stuff. Taken out of lib70x ****/ +#ifndef LUT_LEN #define LUT_LEN 14739 #define COLORCONV_RGB 0 #define COLORCONV_BGR 1 - -struct CColorConv3D { - uint8_t lut[17][17][17][3]; -}; - -/* Load the Lookup table off of disk into *PRE-ALLOCATED* buffer */ -int CColorConv3D_Get3DColorTable(uint8_t *buf, const char *filename) -{ - FILE *stream; - - if (!filename) - return 1; - if (!*filename) - return 2; - if (!buf) - return 3; - - stream = fopen(filename, "rb"); - if (!stream) - return 4; - - fseek(stream, 0, SEEK_END); - if (ftell(stream) < LUT_LEN) { - fclose(stream); - return 5; - } - fseek(stream, 0, SEEK_SET); - fread(buf, 1, LUT_LEN, stream); - fclose(stream); - - return 0; -} - -/* Parse the on-disk LUT data into the structure.... */ -struct CColorConv3D *CColorConv3D_Load3DColorTable(const uint8_t *ptr) -{ - struct CColorConv3D *this; - this = malloc(sizeof(*this)); - if (!this) - return NULL; - - int i, j, k; - - for (i = 0 ; i <= 16 ; i++) { - for (j = 0 ; j <= 16 ; j++) { - for (k = 0; k <= 16; k++) { - this->lut[k][j][i][2] = *ptr++; - this->lut[k][j][i][1] = *ptr++; - this->lut[k][j][i][0] = *ptr++; - } - } - } - return this; -} -void CColorConv3D_Destroy3DColorTable(struct CColorConv3D *this) -{ - free(this); -} - -/* Transform a single pixel. */ -static void CColorConv3D_DoColorConvPixel(struct CColorConv3D *this, uint8_t *redp, uint8_t *grnp, uint8_t *blup) -{ - int red_h; - int grn_h; - int blu_h; - int grn_li; - int red_li; - int blu_li; - int red_l; - int grn_l; - int blu_l; - - uint8_t *tab0; // @ 14743 - uint8_t *tab1; // @ 14746 - uint8_t *tab2; // @ 14749 - uint8_t *tab3; // @ 14752 - uint8_t *tab4; // @ 14755 - uint8_t *tab5; // @ 14758 - uint8_t *tab6; // @ 14761 - uint8_t *tab7; // @ 14764 - - red_h = *redp >> 4; - red_l = *redp & 0xF; - red_li = 16 - red_l; - - grn_h = *grnp >> 4; - grn_l = *grnp & 0xF; - grn_li = 16 - grn_l; - - blu_h = *blup >> 4; - blu_l = *blup & 0xF; - blu_li = 16 - blu_l; - -// printf("%d %d %d =>", *redp, *grnp, *blup); - - tab0 = this->lut[red_h+0][grn_h+0][blu_h+0]; - tab1 = this->lut[red_h+1][grn_h+0][blu_h+0]; - tab2 = this->lut[red_h+0][grn_h+1][blu_h+0]; - tab3 = this->lut[red_h+1][grn_h+1][blu_h+0]; - tab4 = this->lut[red_h+0][grn_h+0][blu_h+1]; - tab5 = this->lut[red_h+1][grn_h+0][blu_h+1]; - tab6 = this->lut[red_h+0][grn_h+1][blu_h+1]; - tab7 = this->lut[red_h+1][grn_h+1][blu_h+1]; - -#if 0 - printf(" %d %d %d ", tab0[0], tab0[1], tab0[2]); - printf(" %d %d %d ", tab1[0], tab1[1], tab1[2]); - printf(" %d %d %d ", tab2[0], tab2[1], tab2[2]); - printf(" %d %d %d ", tab3[0], tab3[1], tab3[2]); - printf(" %d %d %d ", tab4[0], tab4[1], tab4[2]); - printf(" %d %d %d ", tab5[0], tab5[1], tab5[2]); - printf(" %d %d %d ", tab6[0], tab6[1], tab6[2]); - printf(" %d %d %d ", tab7[0], tab7[1], tab7[2]); #endif - *redp = (blu_li - * (grn_li * (red_li * tab0[0] + red_l * tab1[0]) - + grn_l * (red_li * tab2[0] + red_l * tab3[0])) - + blu_l - * (grn_li * (red_li * tab4[0] + red_l * tab5[0]) - + grn_l * (red_li * tab6[0] + red_l * tab7[0])) - + 2048) >> 12; - *grnp = (blu_li - * (grn_li * (red_li * tab0[1] + red_l * tab1[1]) - + grn_l * (red_li * tab2[1] + red_l * tab3[1])) - + blu_l - * (grn_li * (red_li * tab4[1] + red_l * tab5[1]) - + grn_l * (red_li * tab6[1] + red_l * tab7[1])) - + 2048) >> 12; - *blup = (blu_li - * (grn_li * (red_li * tab0[2] + red_l * tab1[2]) - + grn_l * (red_li * tab2[2] + red_l * tab3[2])) - + blu_l - * (grn_li * (red_li * tab4[2] + red_l * tab5[2]) - + grn_l * (red_li * tab6[2] + red_l * tab7[2])) - + 2048) >> 12; - -// printf("=> %d %d %d\n", *redp, *grnp, *blup); -} - -/* Perform a total conversion on an entire image */ -void CColorConv3D_DoColorConv(struct CColorConv3D *this, uint8_t *data, uint16_t cols, uint16_t rows, uint32_t stride, int rgb_bgr) -{ - uint16_t i, j; - - uint8_t *ptr; - - for ( i = 0; i < rows ; i++ ) - { - ptr = data; - for ( j = 0; cols > j; j++ ) - { - if (rgb_bgr) { - CColorConv3D_DoColorConvPixel(this, ptr + 2, ptr + 1, ptr); - } else { - CColorConv3D_DoColorConvPixel(this, ptr, ptr + 1, ptr + 2); - } - ptr += 3; - } - data += stride; - } -} -/* ---- end 3D LUT ---- */ static int mitsu9550_get_status(struct mitsu9550_ctx *ctx, uint8_t *resp, int status, int status2, int media); static char *mitsu9550_media_types(uint8_t type, uint8_t is_s); @@ -534,6 +426,8 @@ static void *mitsu9550_init(void) } memset(ctx, 0, sizeof(struct mitsu9550_ctx)); + DL_INIT(); + return ctx; } @@ -559,6 +453,46 @@ static int mitsu9550_attach(void *vctx, struct libusb_device_handle *dev, int ty ctx->type == P_MITSU_9810) ctx->is_98xx = 1; + /* Attempt to open the library */ +#if defined(WITH_DYNAMIC) + if (!ctx->is_98xx) goto skip; + + DEBUG("Attempting to load image processing library\n"); + ctx->dl_handle = DL_OPEN(LIB_NAME_RE); + if (!ctx->dl_handle) + WARNING("Image processing library not found, using internal fallback code\n"); + if (ctx->dl_handle) { + ctx->GetAPIVersion = DL_SYM(ctx->dl_handle, "lib70x_getapiversion"); + if (!ctx->GetAPIVersion) { + ERROR("Problem resolving API Version symbol in imaging processing library, too old or not installed?\n"); + DL_CLOSE(ctx->dl_handle); + ctx->dl_handle = NULL; + return CUPS_BACKEND_FAILED; + } + if (ctx->GetAPIVersion() != REQUIRED_LIB_APIVERSION) { + ERROR("Image processing library API version mismatch!\n"); + DL_CLOSE(ctx->dl_handle); + ctx->dl_handle = NULL; + return CUPS_BACKEND_FAILED; + } + + ctx->Get3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Get3DColorTable"); + ctx->Load3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Load3DColorTable"); + ctx->Destroy3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Destroy3DColorTable"); + ctx->DoColorConv = DL_SYM(ctx->dl_handle, "CColorConv3D_DoColorConv"); + if (!ctx->Get3DColorTable || !ctx->Load3DColorTable || + !ctx->Destroy3DColorTable || !ctx->DoColorConv ) { + ERROR("Problem resolving symbols in imaging processing library\n"); + DL_CLOSE(ctx->dl_handle); + ctx->dl_handle = NULL; + return CUPS_BACKEND_FAILED; + } else { + DEBUG("Image processing library successfully loaded\n"); + } + } +skip: +#endif + if (test_mode < TEST_MODE_NOATTACH) { if (mitsu9550_get_status(ctx, (uint8_t*) &media, 0, 0, 1)) return CUPS_BACKEND_FAILED; @@ -596,10 +530,14 @@ static void mitsu9550_teardown(void *vctx) { if (!ctx) return; - if (ctx->lut) - CColorConv3D_Destroy3DColorTable(ctx->lut); - if (ctx->m98xxdata) - free(ctx->m98xxdata); + if (ctx->dl_handle) { + if (ctx->lut) + ctx->Destroy3DColorTable(ctx->lut); + if (ctx->m98xxdata) + free(ctx->m98xxdata); + DL_CLOSE(ctx->dl_handle); + } + free(ctx); } @@ -700,31 +638,56 @@ hdr_done: /* Read in CP98xx data tables if necessary */ if (ctx->is_98xx && !job->is_raw && !ctx->m98xxdata) { - int fd; - - DEBUG("Reading in 98xx data from disk\n"); - fd = open(MITSU_M98xx_DATATABLE_FILE, O_RDONLY); - if (fd < 0) { - ERROR("Unable to open 98xx data table file '%s'\n", MITSU_M98xx_DATATABLE_FILE); - mitsu9550_cleanup_job(job); - return CUPS_BACKEND_FAILED; - } + int ret; ctx->m98xxdata = malloc(DATATABLE_SIZE); if (!ctx->m98xxdata) { ERROR("Memory allocation Failure!\n"); mitsu9550_cleanup_job(job); return CUPS_BACKEND_RETRY_CURRENT; } - remain = DATATABLE_SIZE; - while (remain) { - i = read(fd, ((uint8_t*)ctx->m98xxdata) + (DATATABLE_SIZE - remain), remain); - if (i < 0) { - mitsu9550_cleanup_job(job); - return CUPS_BACKEND_CANCEL; + + DEBUG("Reading in 98xx data from disk\n"); + if ((ret = dyesub_read_file(MITSU_M98xx_DATATABLE_FILE, ctx->m98xxdata, DATATABLE_SIZE, NULL))) { + ERROR("Unable to read 98xx data table file '%s'\n", MITSU_M98xx_DATATABLE_FILE); + free(ctx->m98xxdata); + return ret; + } + + /* Byteswap data table to native endianness, if necessary */ +#if (__BYTE_ORDER == __LITTLE_ENDIAN) + int j; + struct mitsu98xx_data *ptr = &ctx->m98xxdata->superfine; + for (j = 0 ; j < 3 ; j++) { + for (i = 3 ; i < 3 ; i++) { + ptr->GammaAdj[i] = be64_to_cpu(ptr->GammaAdj[i]); + ptr->unk_kh[i] = be32_to_cpu(ptr->unk_kh[i]); } - remain -= i; + for (i = 0 ; i < 10 ; i++) { + ptr->WMAM.unkc[i] = be32_to_cpu(ptr->WMAM.unkc[i]); + ptr->WMAM.unkf[i] = be32_to_cpu(ptr->WMAM.unkf[i]); + } + for (i = 0 ; i < 11 ; i++) { + ptr->sharp_coef[i] = be64_to_cpu(ptr->sharp_coef[i]); + } + for (i = 0 ; i < 20 ; i++) { + ptr->unk_sharp[i] = be16_to_cpu(ptr->unk_sharp[i]); + } + for (i = 0 ; i < 256 ; i++) { + ptr->WMAM.unka[i] = be64_to_cpu(ptr->WMAM.unka[i]); + ptr->WMAM.unkb[i] = be64_to_cpu(ptr->WMAM.unkb[i]); + ptr->WMAM.unkd[i] = be64_to_cpu(ptr->WMAM.unkd[i]); + ptr->WMAM.unke[i] = be64_to_cpu(ptr->WMAM.unke[i]); + ptr->WMAM.unkg[i] = be64_to_cpu(ptr->WMAM.unkg[i]); + + ptr->GNMby[i] = be16_to_cpu(ptr->GNMby[i]); + ptr->GNMgm[i] = be16_to_cpu(ptr->GNMgm[i]); + ptr->GNMrc[i] = be16_to_cpu(ptr->GNMrc[i]); + + } + // XXX TODO: KH[2048] + ptr++; } - close(fd); +#endif } if (job->is_raw) { @@ -832,8 +795,10 @@ hdr_done: memcpy(job->databuf + job->datalen, buf, 4); job->datalen += 4; - /* Unless we have a matte plane following, we're done */ - if (job->hdr1.matte != 0x01) + /* Unless we have a raw matte plane following, + we're done */ + if (job->hdr1.matte != 0x01 || + !job->is_raw) break; remain = sizeof(buf); } else { @@ -856,31 +821,40 @@ hdr_done: } } - /* Apply LUT */ + /* Apply LUT, if job calls for it.. */ if (ctx->is_98xx && !job->is_raw && job->hdr2.unkc[9]) { - DEBUG("Applying 3D LUT\n"); + + if (!ctx->dl_handle) { + // XXXFALLBACK write fallback code? + ERROR("!!! Image Processing Library not found, aborting!\n"); + mitsu9550_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + if (!ctx->lut) { - uint8_t *buf = malloc(LUT_LEN); - if (!buf) { + uint8_t *lbuf = malloc(LUT_LEN); + if (!lbuf) { ERROR("Memory allocation failure!\n"); mitsu9550_cleanup_job(job); return CUPS_BACKEND_RETRY_CURRENT; } - if (CColorConv3D_Get3DColorTable(buf, MITSU_M98xx_LUT_FILE)) { + if (ctx->Get3DColorTable(lbuf, MITSU_M98xx_LUT_FILE)) { ERROR("Unable to open LUT file '%s'\n", MITSU_M98xx_LUT_FILE); mitsu9550_cleanup_job(job); return CUPS_BACKEND_CANCEL; } - ctx->lut = CColorConv3D_Load3DColorTable(buf); - free(buf); + ctx->lut = ctx->Load3DColorTable(lbuf); + free(lbuf); if (!ctx->lut) { ERROR("Unable to parse LUT\n"); mitsu9550_cleanup_job(job); return CUPS_BACKEND_CANCEL; } } - CColorConv3D_DoColorConv(ctx->lut, job->databuf + sizeof(struct mitsu9550_plane), - job->cols, job->rows, job->cols * 3, COLORCONV_BGR); + + DEBUG("Running print data through 3D LUT\n"); + ctx->DoColorConv(ctx->lut, job->databuf + sizeof(struct mitsu9550_plane), + job->cols, job->rows, job->cols * 3, COLORCONV_BGR); job->hdr2.unkc[9] = 0; } @@ -1199,7 +1173,7 @@ static int mitsu9550_main_loop(void *vctx, const void *vjob) { int i, remain, planelen; planelen = job->rows * job->cols * 2; - remain = (job->hdr1.matte ? 3 : 4) * (planelen + sizeof(struct mitsu9550_plane)) + sizeof(struct mitsu9550_cmd); + remain = (job->hdr1.matte ? 4 : 3) * (planelen + sizeof(struct mitsu9550_plane)) + sizeof(struct mitsu9550_cmd) * (job->hdr1.matte? 2 : 1) + LAMINATE_STRIDE * 2; newbuf = malloc(remain); if (!newbuf) { ERROR("Memory allocation Failure!\n"); @@ -1254,7 +1228,7 @@ static int mitsu9550_main_loop(void *vctx, const void *vjob) { newlen += planelen; /* And finally, the job footer. */ - memcpy(newbuf + newlen, job->databuf + sizeof(struct mitsu9550_plane) + planelen * 3, sizeof(struct mitsu9550_cmd)); + memcpy(newbuf + newlen, job->databuf + sizeof(struct mitsu9550_plane) + planelen/2 * 3, sizeof(struct mitsu9550_cmd)); newlen += sizeof(struct mitsu9550_cmd); /* Clean up, and move pointer to new buffer; */ @@ -1362,7 +1336,6 @@ top: /* Send over plane data */ while(ptr < (job->databuf + job->datalen)) { struct mitsu9550_plane *plane = (struct mitsu9550_plane *)ptr; - uint32_t planelen; if (plane->cmd[0] != 0x1b || plane->cmd[1] != 0x5a || plane->cmd[2] != 0x54) @@ -1457,7 +1430,7 @@ top: /* Don't forget the 9810's matte plane */ if (job->hdr1.matte) { struct mitsu9550_plane *plane = (struct mitsu9550_plane *)ptr; - uint32_t planelen = be16_to_cpu(plane->rows) * be16_to_cpu(plane->cols); + planelen = be16_to_cpu(plane->rows) * be16_to_cpu(plane->cols); if (plane->cmd[3] == 0x10) planelen *= 2; @@ -1735,7 +1708,7 @@ static const char *mitsu9550_prefixes[] = { /* Exported */ struct dyesub_backend mitsu9550_backend = { .name = "Mitsubishi CP9xxx family", - .version = "0.41", + .version = "0.47", .uri_prefixes = mitsu9550_prefixes, .cmdline_usage = mitsu9550_cmdline, .cmdline_arg = mitsu9550_cmdline_arg, diff --git a/src/cups/backend_mitsud90.c b/src/cups/backend_mitsud90.c index 9655e55..2a5764c 100644 --- a/src/cups/backend_mitsud90.c +++ b/src/cups/backend_mitsud90.c @@ -559,15 +559,6 @@ static void mitsud90_cleanup_job(const void *vjob) free((void*)job); } -static void mitsud90_teardown(void *vctx) { - struct mitsud90_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int mitsud90_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct mitsud90_ctx *ctx = vctx; int i, remain; @@ -1232,7 +1223,6 @@ struct dyesub_backend mitsud90_backend = { .init = mitsud90_init, .attach = mitsud90_attach, .cleanup_job = mitsud90_cleanup_job, - .teardown = mitsud90_teardown, .read_parse = mitsud90_read_parse, .main_loop = mitsud90_main_loop, .query_markers = mitsud90_query_markers, diff --git a/src/cups/backend_mitsup95d.c b/src/cups/backend_mitsup95d.c index c4e0054..284cc01 100644 --- a/src/cups/backend_mitsup95d.c +++ b/src/cups/backend_mitsup95d.c @@ -169,15 +169,6 @@ static void mitsup95d_cleanup_job(const void *vjob) free((void*)job); } -static void mitsup95d_teardown(void *vctx) { - struct mitsup95d_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int mitsup95d_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct mitsup95d_ctx *ctx = vctx; uint8_t buf[2]; /* Enough to read in any header */ @@ -584,6 +575,13 @@ static int mitsup95d_query_markers(void *vctx, struct marker **markers, int *cou } } + /* Lot state */ + if (ctx->marker.levelnow) + STATE("-media-empty\n"); + else + STATE("+media-empty\n"); + + *markers = &ctx->marker; *count = 1; @@ -601,13 +599,12 @@ static const char *mitsup95d_prefixes[] = { /* Exported */ struct dyesub_backend mitsup95d_backend = { .name = "Mitsubishi P93D/P95D", - .version = "0.11", + .version = "0.12", .uri_prefixes = mitsup95d_prefixes, .cmdline_arg = mitsup95d_cmdline_arg, .cmdline_usage = mitsup95d_cmdline, .init = mitsup95d_init, .attach = mitsup95d_attach, - .teardown = mitsup95d_teardown, .cleanup_job = mitsup95d_cleanup_job, .read_parse = mitsup95d_read_parse, .main_loop = mitsup95d_main_loop, diff --git a/src/cups/backend_shinkos1245.c b/src/cups/backend_shinkos1245.c index cd0d34c..99fc690 100644 --- a/src/cups/backend_shinkos1245.c +++ b/src/cups/backend_shinkos1245.c @@ -1,7 +1,7 @@ /* * Shinko/Sinfonia CHC-S1245 CUPS backend -- libusb-1.0 version * - * (c) 2015-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2015-2019 Solomon Peachy <pizza@shaftnet.org> * * Low-level documentation was provided by Sinfonia, Inc. Thank you! * @@ -41,46 +41,7 @@ #define BACKEND shinkos1245_backend #include "backend_common.h" - -/* Structure of printjob header. All fields are LITTLE ENDIAN */ -struct s1245_printjob_hdr { - uint32_t len1; /* Fixed at 0x10 */ - uint32_t model; /* Equal to the printer model (eg '1245' or '2145' decimal) */ - uint32_t unk2; /* Null */ - uint32_t unk3; /* Fixed at 0x01 */ - - uint32_t len2; /* Fixed at 0x64 */ - uint32_t unk5; /* Null */ - uint32_t media; /* Fixed at 0x10 */ - uint32_t unk6; /* Null */ - - uint32_t method; /* Print Method */ - uint32_t mode; /* Print Mode */ - uint32_t unk7; /* Null */ - int32_t mattedepth; /* 0x7fffffff for glossy, 0x00 +- 25 for matte */ - - uint32_t dust; /* Dust control */ - uint32_t columns; - uint32_t rows; - uint32_t copies; - - uint32_t unk10; /* Null */ - uint32_t unk11; /* Null */ - uint32_t unk12; /* Null */ - uint32_t unk13; /* 0xceffffff */ - - uint32_t unk14; /* Null */ - uint32_t unk15; /* 0xceffffff */ - uint32_t dpi; /* Fixed at '300' (decimal) */ - uint32_t unk16; /* 0xceffffff */ - - uint32_t unk17; /* Null */ - uint32_t unk18; /* 0xceffffff */ - uint32_t unk19; /* Null */ - uint32_t unk20; /* Null */ - - uint32_t unk21; /* Null */ -} __attribute__((packed)); +#include "backend_sinfonia.h" /* Printer data structures */ struct shinkos1245_cmd_hdr { @@ -166,113 +127,6 @@ struct shinkos1245_resp_status { uint8_t curve_status; } __attribute__((packed)); -enum { - CMD_CODE_OK = 1, - CMD_CODE_BAD = 2, -}; - -enum { - STATUS_PRINTING = 1, - STATUS_IDLE = 2, -}; - -enum { - STATE_STATUS1_STANDBY = 1, - STATE_STATUS1_ERROR = 2, - STATE_STATUS1_WAIT = 3, -}; - -#define STATE_STANDBY_STATUS2 0x0 - -enum { - WAIT_STATUS2_INIT = 0, - WAIT_STATUS2_RIBBON = 1, - WAIT_STATUS2_THERMAL = 2, - WAIT_STATUS2_OPERATING = 3, - WAIT_STATUS2_BUSY = 4, -}; - - -#define ERROR_STATUS2_CTRL_CIRCUIT (0x80000000) -#define ERROR_STATUS2_MECHANISM_CTRL (0x40000000) -#define ERROR_STATUS2_SENSOR (0x00002000) -#define ERROR_STATUS2_COVER_OPEN (0x00001000) -#define ERROR_STATUS2_TEMP_SENSOR (0x00000200) -#define ERROR_STATUS2_PAPER_JAM (0x00000100) -#define ERROR_STATUS2_PAPER_EMPTY (0x00000040) -#define ERROR_STATUS2_RIBBON_ERR (0x00000010) - -enum { - CTRL_CIR_ERROR_EEPROM1 = 0x01, - CTRL_CIR_ERROR_EEPROM2 = 0x02, - CTRL_CIR_ERROR_DSP = 0x04, - CTRL_CIR_ERROR_CRC_MAIN = 0x06, - CTRL_CIR_ERROR_DL_MAIN = 0x07, - CTRL_CIR_ERROR_CRC_DSP = 0x08, - CTRL_CIR_ERROR_DL_DSP = 0x09, - CTRL_CIR_ERROR_ASIC = 0x0a, - CTRL_CIR_ERROR_DRAM = 0x0b, - CTRL_CIR_ERROR_DSPCOMM = 0x29, -}; - -enum { - MECH_ERROR_HEAD_UP = 0x01, - MECH_ERROR_HEAD_DOWN = 0x02, - MECH_ERROR_MAIN_PINCH_UP = 0x03, - MECH_ERROR_MAIN_PINCH_DOWN = 0x04, - MECH_ERROR_SUB_PINCH_UP = 0x05, - MECH_ERROR_SUB_PINCH_DOWN = 0x06, - MECH_ERROR_FEEDIN_PINCH_UP = 0x07, - MECH_ERROR_FEEDIN_PINCH_DOWN = 0x08, - MECH_ERROR_FEEDOUT_PINCH_UP = 0x09, - MECH_ERROR_FEEDOUT_PINCH_DOWN = 0x0a, - MECH_ERROR_CUTTER_LR = 0x0b, - MECH_ERROR_CUTTER_RL = 0x0c, -}; - -enum { - SENSOR_ERROR_CUTTER = 0x05, - SENSOR_ERROR_HEAD_DOWN = 0x09, - SENSOR_ERROR_HEAD_UP = 0x0a, - SENSOR_ERROR_MAIN_PINCH_DOWN = 0x0b, - SENSOR_ERROR_MAIN_PINCH_UP = 0x0c, - SENSOR_ERROR_FEED_PINCH_DOWN = 0x0d, - SENSOR_ERROR_FEED_PINCH_UP = 0x0e, - SENSOR_ERROR_EXIT_PINCH_DOWN = 0x0f, - SENSOR_ERROR_EXIT_PINCH_UP = 0x10, - SENSOR_ERROR_LEFT_CUTTER = 0x11, - SENSOR_ERROR_RIGHT_CUTTER = 0x12, - SENSOR_ERROR_CENTER_CUTTER = 0x13, - SENSOR_ERROR_UPPER_CUTTER = 0x14, - SENSOR_ERROR_PAPER_FEED_COVER = 0x15, -}; - -enum { - TEMP_SENSOR_ERROR_HEAD_HIGH = 0x01, - TEMP_SENSOR_ERROR_HEAD_LOW = 0x02, - TEMP_SENSOR_ERROR_ENV_HIGH = 0x03, - TEMP_SENSOR_ERROR_ENV_LOW = 0x04, -}; - -enum { - COVER_OPEN_ERROR_UPPER = 0x01, - COVER_OPEN_ERROR_LOWER = 0x02, -}; - -enum { - PAPER_EMPTY_ERROR = 0x00, -}; - -enum { - RIBBON_ERROR = 0x00, -}; - -enum { - CURVE_TABLE_STATUS_INITIAL = 0x00, - CURVE_TABLE_STATUS_USERSET = 0x01, - CURVE_TABLE_STATUS_CURRENT = 0x02, -}; - /* Query media info */ struct shinkos1245_cmd_getmedia { struct shinkos1245_cmd_hdr hdr; @@ -280,28 +134,15 @@ struct shinkos1245_cmd_getmedia { uint8_t pad[10]; } __attribute__((packed)); -struct shinkos1245_mediadesc { - uint8_t code; /* Fixed at 0x10 */ - uint16_t columns; /* BE */ - uint16_t rows; /* BE */ - uint8_t type; /* MEDIA_TYPE_* */ - uint8_t print_type; /* aka "print method" in the spool file */ - uint8_t reserved[3]; -} __attribute__((packed)); - #define NUM_MEDIAS 5 /* Maximum per message */ struct shinkos1245_resp_media { uint8_t code; uint8_t reserved[6]; uint8_t count; /* 1-5? */ - struct shinkos1245_mediadesc data[NUM_MEDIAS]; + struct sinfonia_mediainfo_item data[NUM_MEDIAS]; } __attribute__((packed)); -enum { - MEDIA_TYPE_UNKNOWN = 0x00, - MEDIA_TYPE_PAPER = 0x01, -}; enum { PRINT_TYPE_STANDARD = 0x00, @@ -359,7 +200,6 @@ enum { PARAM_TABLE_FINE = 2, }; -#define TONE_CURVE_SIZE 1536 #define TONE_CURVE_DATA_BLOCK_SIZE 64 /* Query Model information */ @@ -400,15 +240,9 @@ struct shinkos1245_resp_matte { } __attribute__((packed)); #define MATTE_MODE_MATTE 0x00 +#define MAX_MEDIA_ITEMS 15 /* Private data structure */ -struct shinkos1245_printjob { - uint8_t *databuf; - int datalen; - - int copies; -}; - struct shinkos1245_ctx { struct libusb_device_handle *dev; uint8_t endp_up; @@ -417,9 +251,7 @@ struct shinkos1245_ctx { uint8_t jobid; - struct s1245_printjob_hdr hdr; - - struct shinkos1245_mediadesc medias[15]; + struct sinfonia_mediainfo_item medias[MAX_MEDIA_ITEMS]; int num_medias; int media_8x12; @@ -493,6 +325,9 @@ static int shinkos1245_get_status(struct shinkos1245_ctx *ctx, return -99; } + /* Byteswap important stuff */ + resp->state.status2 = be32_to_cpu(resp->state.status2); + return 0; } @@ -527,7 +362,7 @@ static int shinkos1245_get_media(struct shinkos1245_ctx *ctx) ctx->medias[ctx->num_medias].columns = be16_to_cpu(resp.data[j].columns); ctx->medias[ctx->num_medias].rows = be16_to_cpu(resp.data[j].rows); ctx->medias[ctx->num_medias].type = resp.data[j].type; - ctx->medias[ctx->num_medias].print_type = resp.data[j].print_type; + ctx->medias[ctx->num_medias].method = resp.data[j].method; ctx->num_medias++; if (ctx->medias[i].rows >= 3636) @@ -697,153 +532,6 @@ static int shinkos1245_get_matte(struct shinkos1245_ctx *ctx, return 0; } - -/* Structure dumps */ -static char *shinkos1245_status_str(struct shinkos1245_resp_status *resp) -{ - switch(resp->state.status1) { - case STATE_STATUS1_STANDBY: - return "Standby (Ready)"; - case STATE_STATUS1_WAIT: - switch (resp->state.status2) { - case WAIT_STATUS2_INIT: - return "Wait (Initializing)"; - case WAIT_STATUS2_RIBBON: - return "Wait (Ribbon Winding)"; - case WAIT_STATUS2_THERMAL: - return "Wait (Thermal Protection)"; - case WAIT_STATUS2_OPERATING: - return "Wait (Operating)"; - case WAIT_STATUS2_BUSY: - return "Wait (Busy)"; - default: - return "Wait (Unknown)"; - } - case STATE_STATUS1_ERROR: - switch (resp->state.status2) { - case ERROR_STATUS2_CTRL_CIRCUIT: - switch (resp->state.error) { - case CTRL_CIR_ERROR_EEPROM1: - return "Error (EEPROM1)"; - case CTRL_CIR_ERROR_EEPROM2: - return "Error (EEPROM2)"; - case CTRL_CIR_ERROR_DSP: - return "Error (DSP)"; - case CTRL_CIR_ERROR_CRC_MAIN: - return "Error (Main CRC)"; - case CTRL_CIR_ERROR_DL_MAIN: - return "Error (Main Download)"; - case CTRL_CIR_ERROR_CRC_DSP: - return "Error (DSP CRC)"; - case CTRL_CIR_ERROR_DL_DSP: - return "Error (DSP Download)"; - case CTRL_CIR_ERROR_ASIC: - return "Error (ASIC)"; - case CTRL_CIR_ERROR_DRAM: - return "Error (DRAM)"; - case CTRL_CIR_ERROR_DSPCOMM: - return "Error (DSP Communincation)"; - default: - return "Error (Unknown Circuit)"; - } - case ERROR_STATUS2_MECHANISM_CTRL: - switch (resp->state.error) { - case MECH_ERROR_HEAD_UP: - return "Error (Head Up Mechanism)"; - case MECH_ERROR_HEAD_DOWN: - return "Error (Head Down Mechanism)"; - case MECH_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Mechanism)"; - case MECH_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Mechanism)"; - case MECH_ERROR_SUB_PINCH_UP: - return "Error (Sub Pinch Up Mechanism)"; - case MECH_ERROR_SUB_PINCH_DOWN: - return "Error (Sub Pinch Down Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_UP: - return "Error (Feed-in Pinch Up Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_DOWN: - return "Error (Feed-in Pinch Down Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_UP: - return "Error (Feed-out Pinch Up Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_DOWN: - return "Error (Feed-out Pinch Down Mechanism)"; - case MECH_ERROR_CUTTER_LR: - return "Error (Left->Right Cutter)"; - case MECH_ERROR_CUTTER_RL: - return "Error (Right->Left Cutter)"; - default: - return "Error (Unknown Mechanism)"; - } - case ERROR_STATUS2_SENSOR: - switch (resp->state.error) { - case SENSOR_ERROR_CUTTER: - return "Error (Cutter Sensor)"; - case SENSOR_ERROR_HEAD_DOWN: - return "Error (Head Down Sensor)"; - case SENSOR_ERROR_HEAD_UP: - return "Error (Head Up Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Sensor)"; - case SENSOR_ERROR_FEED_PINCH_DOWN: - return "Error (Feed Pinch Down Sensor)"; - case SENSOR_ERROR_FEED_PINCH_UP: - return "Error (Feed Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_DOWN: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_UP: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_LEFT_CUTTER: - return "Error (Left Cutter Sensor)"; - case SENSOR_ERROR_RIGHT_CUTTER: - return "Error (Right Cutter Sensor)"; - case SENSOR_ERROR_CENTER_CUTTER: - return "Error (Center Cutter Sensor)"; - case SENSOR_ERROR_UPPER_CUTTER: - return "Error (Upper Cutter Sensor)"; - case SENSOR_ERROR_PAPER_FEED_COVER: - return "Error (Paper Feed Cover)"; - default: - return "Error (Unknown Sensor)"; - } - case ERROR_STATUS2_COVER_OPEN: - switch (resp->state.error) { - case COVER_OPEN_ERROR_UPPER: - return "Error (Upper Cover Open)"; - case COVER_OPEN_ERROR_LOWER: - return "Error (Lower Cover Open)"; - default: - return "Error (Unknown Cover Open)"; - } - case ERROR_STATUS2_TEMP_SENSOR: - switch (resp->state.error) { - case TEMP_SENSOR_ERROR_HEAD_HIGH: - return "Error (Head Temperature High)"; - case TEMP_SENSOR_ERROR_HEAD_LOW: - return "Error (Head Temperature Low)"; - case TEMP_SENSOR_ERROR_ENV_HIGH: - return "Error (Environmental Temperature High)"; - case TEMP_SENSOR_ERROR_ENV_LOW: - return "Error (Environmental Temperature Low)"; - default: - return "Error (Unknown Temperature)"; - } - case ERROR_STATUS2_PAPER_JAM: - return "Error (Paper Jam)"; - case ERROR_STATUS2_PAPER_EMPTY: - return "Error (Paper Empty)"; - case ERROR_STATUS2_RIBBON_ERR: - return "Error (Ribbon)"; - default: - return "Error (Unknown)"; - } - default: - return "Unknown!"; - } -} - static char* shinkos1245_tonecurves(int type, int table) { switch (type) { @@ -897,10 +585,8 @@ static void shinkos1245_dump_status(struct shinkos1245_ctx *ctx, INFO("Printer Status: %s\n", detail); /* Byteswap */ - sts->state.status2 = be32_to_cpu(sts->state.status2); - INFO("Printer State: %s # %02x %08x %02x\n", - shinkos1245_status_str(sts), + sinfonia_1x45_status_str(sts->state.status1, sts->state.status2, sts->state.error), sts->state.status1, sts->state.status2, sts->state.error); INFO("Counters:\n"); INFO("\tLifetime : %u\n", be32_to_cpu(sts->counters.lifetime)); @@ -944,7 +630,7 @@ static void shinkos1245_dump_status(struct shinkos1245_ctx *ctx, INFO("Tone Curve Status: %s\n", detail); } -static void shinkos1245_dump_media(struct shinkos1245_mediadesc *medias, +static void shinkos1245_dump_media(struct sinfonia_mediainfo_item *medias, int media_8x12, int count) { @@ -954,11 +640,12 @@ static void shinkos1245_dump_media(struct shinkos1245_mediadesc *medias, INFO("Supported print sizes: %d\n", count); for (i = 0 ; i < count ; i++) { - INFO("\t %02x: %04u*%04u (%02x/%02u)\n", - medias[i].print_type, + INFO("\t %02d: %04u*%04u (%02x/%02u)\n", + i, medias[i].columns, medias[i].rows, - medias[i].type, medias[i].print_type); + medias[i].type, + medias[i].method); } } @@ -1091,21 +778,11 @@ static int set_tonecurve(struct shinkos1245_ctx *ctx, int type, int table, char } ptr = data; - /* Open file and read it in */ - { - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = tc_fd; - goto done; - } - - ret = read(tc_fd, data, TONE_CURVE_SIZE); - if (ret < 0) { - close(tc_fd); - goto done; - } - close(tc_fd); + /* Read in file */ + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) { + ERROR("Failed to read Tone Curve file\n"); + goto done; } /* Issue a tone_write_start */ @@ -1321,31 +998,11 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, int return CUPS_BACKEND_OK; } -static void shinkos1245_cleanup_job(const void *vjob) -{ - const struct shinkos1245_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void shinkos1245_teardown(void *vctx) { - struct shinkos1245_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int shinkos1245_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct shinkos1245_ctx *ctx = vctx; int ret; - uint8_t tmpbuf[4]; - struct shinkos1245_printjob *job = NULL; + struct sinfonia_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1356,88 +1013,18 @@ static int shinkos1245_read_parse(void *vctx, const void **vjob, int data_fd, in return CUPS_BACKEND_RETRY_CURRENT; } memset(job, 0, sizeof(*job)); - job->copies = copies; - /* Read in then validate header */ - ret = read(data_fd, &ctx->hdr, sizeof(ctx->hdr)); - if (ret < 0) { - shinkos1245_cleanup_job(job); + /* Common read/parse code */ + ret = sinfonia_read_parse(data_fd, 1245, job); + if (ret) { + free(job); return ret; } - if (ret != sizeof(ctx->hdr)) { - shinkos1245_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - - if (le32_to_cpu(ctx->hdr.len1) != 0x10 || - le32_to_cpu(ctx->hdr.len2) != 0x64 || - le32_to_cpu(ctx->hdr.dpi) != 300) { - ERROR("Unrecognized header data format!\n"); - shinkos1245_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - - ctx->hdr.model = le32_to_cpu(ctx->hdr.model); - if(ctx->hdr.model != 1245) { - ERROR("Unrecognized printer (%u)!\n", ctx->hdr.model); - shinkos1245_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - - /* Finish byteswapping */ - ctx->hdr.media = le32_to_cpu(ctx->hdr.media); - ctx->hdr.method = le32_to_cpu(ctx->hdr.method); - ctx->hdr.mode = le32_to_cpu(ctx->hdr.mode); - ctx->hdr.mattedepth = le32_to_cpu(ctx->hdr.mattedepth); - ctx->hdr.dust = le32_to_cpu(ctx->hdr.dust); - ctx->hdr.columns = le32_to_cpu(ctx->hdr.columns); - ctx->hdr.rows = le32_to_cpu(ctx->hdr.rows); - ctx->hdr.copies = le32_to_cpu(ctx->hdr.copies); - - /* Allocate space */ - job->datalen = ctx->hdr.rows * ctx->hdr.columns * 3; - job->databuf = malloc(job->datalen); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - shinkos1245_cleanup_job(job); - return CUPS_BACKEND_RETRY_CURRENT; - } - - { - int remain = job->datalen; - uint8_t *ptr = job->databuf; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%d)\n", - ret, remain, job->datalen); - perror("ERROR: Read failed"); - shinkos1245_cleanup_job(job); - return ret; - } - ptr += ret; - remain -= ret; - } while (remain); - } - - /* Make sure footer is sane too */ - ret = read(data_fd, tmpbuf, 4); - if (ret != 4) { - ERROR("Read failed (%d/%d/%d)\n", - ret, 4, 4); - perror("ERROR: Read failed"); - shinkos1245_cleanup_job(job); - return ret; - } - if (tmpbuf[0] != 0x04 || - tmpbuf[1] != 0x03 || - tmpbuf[2] != 0x02 || - tmpbuf[3] != 0x01) { - ERROR("Unrecognized footer data format!\n"); - shinkos1245_cleanup_job(job); - return CUPS_BACKEND_FAILED; - } + if (job->jp.copies > 1) + job->copies = job->jp.copies; + else + job->copies = copies; *vjob = job; return CUPS_BACKEND_OK; @@ -1447,8 +1034,9 @@ static int shinkos1245_main_loop(void *vctx, const void *vjob) { struct shinkos1245_ctx *ctx = vctx; int i, num, last_state = -1, state = S_IDLE; struct shinkos1245_resp_status status1, status2; + int copies; - const struct shinkos1245_printjob *job = vjob; + const struct sinfonia_printjob *job = vjob; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1459,10 +1047,10 @@ static int shinkos1245_main_loop(void *vctx, const void *vjob) { /* Make sure print size is supported */ for (i = 0 ; i < ctx->num_medias ; i++) { - if (ctx->hdr.media == ctx->medias[i].code && - ctx->hdr.method == ctx->medias[i].print_type && - ctx->hdr.rows == ctx->medias[i].rows && - ctx->hdr.columns == ctx->medias[i].columns) + if (job->jp.media == ctx->medias[i].code && + job->jp.method == ctx->medias[i].method && + job->jp.rows == ctx->medias[i].rows && + job->jp.columns == ctx->medias[i].columns) break; } if (i == ctx->num_medias) { @@ -1508,14 +1096,10 @@ top: break; } - if (status1.print_status == STATUS_IDLE) { - state = S_PRINTER_READY_CMD; - break; - } #if 0 // XXX is this necessary if (status1.state.status1 == STATE_STATUS1_WAIT) { INFO("Printer busy: %s\n", - shinkos1245_status_str(&status1)); + sinfonia_1x45_status_str(status1.state.status1, status1.state.status2, status1.state.error)); break; } #endif @@ -1542,15 +1126,15 @@ top: struct shinkos1245_cmd_print cmd; /* Set matte intensity */ - if (ctx->hdr.mattedepth != 0x7fffffff) { + if (job->jp.mattedepth != 0x7fffffff) { int current = -1; i = shinkos1245_get_matte(ctx, ¤t); if (i < 0) - goto printer_error; - if (current != ctx->hdr.mattedepth) { - i = shinkos1245_set_matte(ctx, ctx->hdr.mattedepth); + goto printer_error2; + if (current != job->jp.mattedepth) { + i = shinkos1245_set_matte(ctx, job->jp.mattedepth); if (i < 0) - goto printer_error; + goto printer_error2; if (i > 0) { INFO("Can't set matte intensity when printing in progress...\n"); state = S_IDLE; @@ -1567,17 +1151,18 @@ top: cmd.cmd[1] = 0x00; cmd.id = ctx->jobid; - cmd.count = cpu_to_be16(uint16_to_packed_bcd(copies)); - cmd.columns = cpu_to_be16(ctx->hdr.columns); - cmd.rows = cpu_to_be16(ctx->hdr.rows); - cmd.media = ctx->hdr.media; - cmd.mode = (ctx->hdr.mode & 0x3f) || ((ctx->hdr.dust & 0x3) << 6); - cmd.combo = ctx->hdr.method; + cmd.count = uint16_to_packed_bcd(copies); + cmd.columns = cpu_to_be16(job->jp.columns); + cmd.rows = cpu_to_be16(job->jp.rows); + cmd.media = job->jp.media; + cmd.mode = (job->jp.oc_mode & 0x3f) || ((job->jp.dust & 0x3) << 6); + cmd.combo = job->jp.method; /* Issue print command */ i = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd), &status1, sizeof(status1), &num); + status1.state.status2 = be32_to_cpu(status1.state.status2); if (i < 0) goto printer_error; @@ -1628,13 +1213,10 @@ top: return CUPS_BACKEND_OK; printer_error: - /* Byteswap */ - status1.state.status2 = be32_to_cpu(status1.state.status2); - ERROR("Printer Error: %s # %02x %08x %02x\n", - shinkos1245_status_str(&status1), + sinfonia_1x45_status_str(status1.state.status1, status1.state.status2, status1.state.error), status1.state.status1, status1.state.status2, status1.state.error); - +printer_error2: return CUPS_BACKEND_FAILED; } @@ -1698,14 +1280,13 @@ static const char *shinkos1245_prefixes[] = { struct dyesub_backend shinkos1245_backend = { .name = "Shinko/Sinfonia CHC-S1245/E1", - .version = "0.26", + .version = "0.31" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = shinkos1245_prefixes, .cmdline_usage = shinkos1245_cmdline, .cmdline_arg = shinkos1245_cmdline_arg, .init = shinkos1245_init, .attach = shinkos1245_attach, - .teardown = shinkos1245_teardown, - .cleanup_job = shinkos1245_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = shinkos1245_read_parse, .main_loop = shinkos1245_main_loop, .query_serno = shinkos1245_query_serno, diff --git a/src/cups/backend_shinkos2145.c b/src/cups/backend_shinkos2145.c index 749b59a..bc0df33 100644 --- a/src/cups/backend_shinkos2145.c +++ b/src/cups/backend_shinkos2145.c @@ -1,7 +1,7 @@ -/* + /* * Shinko/Sinfonia CHC-S2145 CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * Development of this backend was sponsored by: * @@ -43,6 +43,7 @@ #define BACKEND shinkos2145_backend #include "backend_common.h" +#include "backend_sinfonia.h" enum { S_IDLE = 0, @@ -51,156 +52,25 @@ enum { S_FINISHED, }; -/* Structure of printjob header. All fields are LITTLE ENDIAN */ -struct s2145_printjob_hdr { - uint32_t len1; /* Fixed at 0x10 */ - uint32_t model; /* Equal to the printer model (eg '2145' or '1245' decimal) */ - uint32_t unk2; - uint32_t unk3; /* Fixed at 0x01 */ - - uint32_t len2; /* Fixed at 0x64 */ - uint32_t unk5; - uint32_t media; - uint32_t unk6; - - uint32_t method; - uint32_t mode; - uint32_t unk7; - uint32_t unk8; - - uint32_t unk9; - uint32_t columns; - uint32_t rows; - uint32_t copies; - - uint32_t unk10; - uint32_t unk11; - uint32_t unk12; - uint32_t unk13; - - uint32_t unk14; - uint32_t unk15; - uint32_t dpi; /* Fixed at '300' (decimal) */ - uint32_t unk16; - - uint32_t unk17; - uint32_t unk18; - uint32_t unk19; - uint32_t unk20; - - uint32_t unk21; -} __attribute__((packed)); - /* Structs for printer */ -struct s2145_cmd_hdr { - uint16_t cmd; - uint16_t len; /* Not including this header */ -} __attribute__((packed)); - -#define S2145_CMD_STATUS 0x0001 -#define S2145_CMD_MEDIAINFO 0x0002 -#define S2145_CMD_MODELNAME 0x0003 -#define S2145_CMD_ERRORLOG 0x0004 -#define S2145_CMD_PRINTJOB 0x4001 -#define S2145_CMD_CANCELJOB 0x4002 -#define S2145_CMD_FLASHLED 0x4003 -#define S2145_CMD_RESET 0x4004 -#define S2145_CMD_READTONE 0x4005 -#define S2145_CMD_BUTTON 0x4006 -#define S2145_CMD_GETUNIQUE 0x8003 -#define S2145_CMD_FWINFO 0xC003 -#define S2145_CMD_UPDATE 0xC004 -#define S2145_CMD_SETUNIQUE 0xC007 - -static char *cmd_names(uint16_t v) { - switch (le16_to_cpu(v)) { - case S2145_CMD_STATUS: - return "Get Status"; - case S2145_CMD_MEDIAINFO: - return "Get Media Info"; - case S2145_CMD_MODELNAME: - return "Get Model Name"; - case S2145_CMD_ERRORLOG: - return "Get Error Log"; - case S2145_CMD_PRINTJOB: - return "Print"; - case S2145_CMD_CANCELJOB: - return "Cancel Print"; - case S2145_CMD_FLASHLED: - return "Flash LEDs"; - case S2145_CMD_RESET: - return "Reset"; - case S2145_CMD_READTONE: - return "Read Tone Curve"; - case S2145_CMD_BUTTON: - return "Button Enable"; - case S2145_CMD_GETUNIQUE: - return "Get Unique String"; - case S2145_CMD_FWINFO: - return "Get Firmware Info"; - case S2145_CMD_UPDATE: - return "Update"; - case S2145_CMD_SETUNIQUE: - return "Set Unique String"; - default: - return "Unknown Command"; - } -} - -struct s2145_print_cmd { - struct s2145_cmd_hdr hdr; - uint8_t id; - uint16_t count; - uint16_t columns; - uint16_t rows; - uint8_t media; - uint8_t mode; - uint8_t method; -} __attribute__((packed)); - -#define PRINT_MEDIA_4x6 0x00 -#define PRINT_MEDIA_5x3_5 0x01 -#define PRINT_MEDIA_5x7 0x03 -#define PRINT_MEDIA_6x9 0x05 -#define PRINT_MEDIA_6x8 0x06 -#define PRINT_MEDIA_2x6 0x07 - -static char *print_sizes (uint8_t v) { - switch (v) { - case PRINT_MEDIA_4x6: - return "4x6"; - case PRINT_MEDIA_5x3_5: - return "5x3.5"; - case PRINT_MEDIA_5x7: - return "5x7"; - case PRINT_MEDIA_6x9: - return "6x9"; - case PRINT_MEDIA_6x8: - return "6x8"; - case PRINT_MEDIA_2x6: - return "2x6"; - default: - return "Unknown"; - } -} - static int print_counts (uint8_t v) { switch (v) { - case PRINT_MEDIA_4x6: + case CODE_4x6: return 700; - case PRINT_MEDIA_5x3_5: + case CODE_3_5x5: return 800; - case PRINT_MEDIA_5x7: + case CODE_5x7: return 400; - case PRINT_MEDIA_6x9: + case CODE_6x9: return 310; - case PRINT_MEDIA_6x8: + case CODE_6x8: return 350; default: return 700; } } +#if 0 #define PRINT_MODE_DEFAULT 0x01 #define PRINT_MODE_STD_GLOSSY 0x02 #define PRINT_MODE_FINE_GLOSSY 0x03 @@ -209,8 +79,7 @@ static int print_counts (uint8_t v) { #define PRINT_MODE_STD_EGLOSSY 0x06 #define PRINT_MODE_FINE_EGLOSSY 0x07 -#if 0 -static char *print_modes(uint8_t v) { +static char *s2145_print_modes(uint8_t v) { switch (v) { case PRINT_MODE_DEFAULT: return "Default"; @@ -232,30 +101,8 @@ static char *print_modes(uint8_t v) { } #endif -#define PRINT_METHOD_STD 0x00 -#define PRINT_METHOD_4x6_2UP 0x02 -#define PRINT_METHOD_2x6_2UP 0x04 - -static char *print_methods (uint8_t v) { - switch (v) { - case PRINT_METHOD_STD: - return "Standard"; - case PRINT_METHOD_4x6_2UP: - return "4x6 2up"; - case PRINT_METHOD_2x6_2UP: - return "2x6 2up"; - default: - return "Unknown"; - } -} - -struct s2145_cancel_cmd { - struct s2145_cmd_hdr hdr; - uint8_t id; -} __attribute__((packed)); - struct s2145_reset_cmd { - struct s2145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t target; } __attribute__((packed)); @@ -263,23 +110,18 @@ struct s2145_reset_cmd { #define RESET_USER_CURVE 0x04 struct s2145_readtone_cmd { - struct s2145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t curveid; } __attribute__((packed)); struct s2145_button_cmd { - struct s2145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t enabled; } __attribute__((packed)); #define BUTTON_ENABLED 0x01 #define BUTTON_DISABLED 0x00 -struct s2145_fwinfo_cmd { - struct s2145_cmd_hdr hdr; - uint8_t target; -} __attribute__((packed)); - #define FWINFO_TARGET_MAIN_BOOT 0x01 #define FWINFO_TARGET_MAIN_APP 0x02 #define FWINFO_TARGET_DSP_BOOT 0x03 @@ -310,61 +152,19 @@ static char *fwinfo_targets (uint8_t v) { } struct s2145_update_cmd { - struct s2145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t target; uint32_t reserved; uint32_t size; } __attribute__((packed)); -#define UPDATE_TARGET_USER 0x03 -#define UPDATE_TARGET_CURRENT 0x04 - -static char *update_targets (uint8_t v) { - switch (v) { - case UPDATE_TARGET_USER: - return "User"; - case UPDATE_TARGET_CURRENT: - return "Current"; - default: - return "Unknown"; - } -} - -#define UPDATE_SIZE 0x600 -/* Update is three channels, Y, M, C; - each is 256 entries of 11-bit data padded to 16-bits. - Printer expects LE data. We use BE data on disk. -*/ - struct s2145_setunique_cmd { - struct s2145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t len; uint8_t data[23]; /* Not necessarily all used. */ } __attribute__((packed)); -struct s2145_status_hdr { - uint8_t result; - uint8_t error; - uint8_t printer_major; - uint8_t printer_minor; - uint8_t reserved[3]; - uint8_t status; - uint16_t payload_len; -} __attribute__((packed)); - -#define RESULT_SUCCESS 0x01 -#define RESULT_FAIL 0x02 - -#define ERROR_NONE 0x00 -#define ERROR_INVALID_PARAM 0x01 -#define ERROR_MAIN_APP_INACTIVE 0x02 -#define ERROR_COMMS_TIMEOUT 0x03 -#define ERROR_MAINT_NEEDED 0x04 -#define ERROR_BAD_COMMAND 0x05 -#define ERROR_PRINTER 0x11 -#define ERROR_BUFFER_FULL 0x21 - -static char *error_codes(uint8_t major, uint8_t minor) +static const char *error_codes(uint8_t major, uint8_t minor) { switch(major) { case 0x01: /* "Controller Error" */ @@ -562,105 +362,8 @@ static char *error_codes(uint8_t major, uint8_t minor) } } -static char *error_str(uint8_t v) { - switch (v) { - case ERROR_NONE: - return "None"; - case ERROR_INVALID_PARAM: - return "Invalid Command Parameter"; - case ERROR_MAIN_APP_INACTIVE: - return "Main App Inactive"; - case ERROR_COMMS_TIMEOUT: - return "Main Communication Timeout"; - case ERROR_MAINT_NEEDED: - return "Maintenance Needed"; - case ERROR_BAD_COMMAND: - return "Inappropriate Command"; - case ERROR_PRINTER: - return "Printer Error"; - case ERROR_BUFFER_FULL: - return "Buffer Full"; - default: - return "Unknown"; - } -} - -#define STATUS_READY 0x00 -#define STATUS_INIT_CPU 0x31 -#define STATUS_INIT_RIBBON 0x32 -#define STATUS_INIT_PAPER 0x33 -#define STATUS_THERMAL_PROTECT 0x34 -#define STATUS_USING_PANEL 0x35 -#define STATUS_SELF_DIAG 0x36 -#define STATUS_DOWNLOADING 0x37 - -#define STATUS_FEEDING_PAPER 0x61 -#define STATUS_PRE_HEAT 0x62 -#define STATUS_PRINT_Y 0x63 -#define STATUS_BACK_FEED_Y 0x64 -#define STATUS_PRINT_M 0x65 -#define STATUS_BACK_FEED_M 0x66 -#define STATUS_PRINT_C 0x67 -#define STATUS_BACK_FEED_C 0x68 -#define STATUS_PRINT_OP 0x69 -#define STATUS_PAPER_CUT 0x6A -#define STATUS_PAPER_EJECT 0x6B -#define STATUS_BACK_FEED_E 0x6C -#define STATUS_FINISHED 0x6D - -static char *status_str(uint8_t v) { - switch (v) { - case STATUS_READY: - return "Ready"; - case STATUS_INIT_CPU: - return "Initializing CPU"; - case STATUS_INIT_RIBBON: - return "Initializing Ribbon"; - case STATUS_INIT_PAPER: - return "Loading Paper"; - case STATUS_THERMAL_PROTECT: - return "Thermal Protection"; - case STATUS_USING_PANEL: - return "Using Operation Panel"; - case STATUS_SELF_DIAG: - return "Processing Self Diagnosis"; - case STATUS_DOWNLOADING: - return "Processing Download"; - case STATUS_FEEDING_PAPER: - return "Feeding Paper"; - case STATUS_PRE_HEAT: - return "Pre-Heating"; - case STATUS_PRINT_Y: - return "Printing Yellow"; - case STATUS_BACK_FEED_Y: - return "Back-Feeding - Yellow Complete"; - case STATUS_PRINT_M: - return "Printing Magenta"; - case STATUS_BACK_FEED_M: - return "Back-Feeding - Magenta Complete"; - case STATUS_PRINT_C: - return "Printing Cyan"; - case STATUS_BACK_FEED_C: - return "Back-Feeding - Cyan Complete"; - case STATUS_PRINT_OP: - return "Laminating"; - case STATUS_PAPER_CUT: - return "Cutting Paper"; - case STATUS_PAPER_EJECT: - return "Ejecting Paper"; - case STATUS_BACK_FEED_E: - return "Back-Feeding - Ejected"; - case STATUS_FINISHED: - return "Print Finished"; - case ERROR_PRINTER: - return "Printer Error"; - default: - return "Unknown"; - } -} - struct s2145_status_resp { - struct s2145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint32_t count_lifetime; uint32_t count_maint; uint32_t count_paper; @@ -680,240 +383,104 @@ struct s2145_status_resp { uint8_t tonecurve_status; } __attribute__((packed)); -#define BANK_STATUS_FREE 0x00 -#define BANK_STATUS_XFER 0x01 -#define BANK_STATUS_FULL 0x02 - -static char *bank_statuses(uint8_t v) -{ - switch (v) { - case BANK_STATUS_FREE: - return "Free"; - case BANK_STATUS_XFER: - return "Xfer"; - case BANK_STATUS_FULL: - return "Full"; - default: - return "Unknown"; - } -} - -#define TONECURVE_INIT 0x00 -#define TONECURVE_USER 0x01 -#define TONECURVE_CURRENT 0x02 - -static char *tonecurve_statuses (uint8_t v) -{ - switch(v) { - case 0: - return "Initial"; - case 1: - return "UserSet"; - case 2: - return "Current"; - default: - return "Unknown"; - } -} - struct s2145_readtone_resp { - struct s2145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint16_t total_size; } __attribute__((packed)); -struct s2145_mediainfo_item { - uint8_t code; - uint16_t columns; - uint16_t rows; - uint8_t media_type; - uint8_t print_type; /* The same as the "print method" */ - uint8_t reserved[3]; -} __attribute__((packed)); - -#define MEDIA_TYPE_UNKNOWN 0x00 -#define MEDIA_TYPE_PAPER 0x01 - -static char *media_types(uint8_t v) { - switch (v) { - case MEDIA_TYPE_UNKNOWN: - return "Unknown"; - case MEDIA_TYPE_PAPER: - return "Paper"; - default: - return "Unknown"; - } -} - struct s2145_mediainfo_resp { - struct s2145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t count; - struct s2145_mediainfo_item items[10]; /* Not all necessarily used */ + struct sinfonia_mediainfo_item items[10]; /* Not all necessarily used */ } __attribute__((packed)); struct s2145_modelname_resp { - struct s2145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t vendor[4]; uint8_t product[4]; uint8_t modelname[40]; } __attribute__((packed)); -struct s2145_error_item { - uint8_t major; - uint8_t minor; - uint32_t print_counter; -} __attribute__((packed)); - -struct s2145_errorlog_resp { - struct s2145_status_hdr hdr; - uint8_t count; - struct s2145_error_item items[10]; /* Not all necessarily used */ -} __attribute__((packed)); - -struct s2145_fwinfo_resp { - struct s2145_status_hdr hdr; - uint8_t name[8]; - uint8_t type[16]; - uint8_t date[10]; - uint8_t major; - uint8_t minor; - uint16_t checksum; -} __attribute__((packed)); - struct s2145_getunique_resp { - struct s2145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t data[24]; /* Not necessarily all used. */ } __attribute__((packed)); /* Private data structure */ -struct shinkos2145_printjob { - struct s2145_printjob_hdr hdr; - - uint8_t *databuf; - int datalen; - int copies; -}; - struct shinkos2145_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; + struct sinfonia_usbdev dev; uint8_t jobid; - int type; - struct s2145_mediainfo_resp media; struct marker marker; int media_code; }; -#define READBACK_LEN 128 /* Needs to be larger than largest response hdr */ -#define CMDBUF_LEN sizeof(struct s2145_print_cmd) - -static uint8_t rdbuf[READBACK_LEN]; - -static int s2145_do_cmd(struct shinkos2145_ctx *ctx, - uint8_t *cmd, int cmdlen, - int minlen, int *num) -{ - int ret; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; - - libusb_device_handle *dev = ctx->dev; - uint8_t endp_up = ctx->endp_up; - uint8_t endp_down = ctx->endp_down; - - if ((ret = send_data(dev, endp_down, - cmd, cmdlen))) - return (ret < 0) ? ret : -99; - - ret = read_data(dev, endp_up, - rdbuf, READBACK_LEN, num); - - if (ret < 0) - return ret; - if (*num < minlen) { - ERROR("Short read! (%d/%d))\n", *num, minlen); - return -99; - } - - if (resp->result != RESULT_SUCCESS) { - INFO("Printer Status: %02x (%s)\n", resp->status, - status_str(resp->status)); - INFO(" Result: 0x%02x Error: 0x%02x (0x%02x/0x%02x = %s)\n", - resp->result, resp->error, resp->printer_major, - resp->printer_minor, error_codes(resp->printer_major, resp->printer_minor)); - return -99; - } - - return ret; -} - static int get_status(struct shinkos2145_ctx *ctx) { - struct s2145_cmd_hdr cmd; - struct s2145_status_resp *resp = (struct s2145_status_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s2145_status_resp resp; int ret, num = 0; - cmd.cmd = cpu_to_le16(S2145_CMD_STATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } - INFO("Printer Status: 0x%02x (%s)\n", resp->hdr.status, - status_str(resp->hdr.status)); - if (resp->hdr.status == ERROR_PRINTER) { - if(resp->hdr.error == ERROR_NONE) - resp->hdr.error = resp->hdr.status; + INFO("Printer Status: 0x%02x (%s)\n", resp.hdr.status, + sinfonia_status_str(resp.hdr.status)); + if (resp.hdr.status == ERROR_PRINTER) { + if(resp.hdr.error == ERROR_NONE) + resp.hdr.error = resp.hdr.status; INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", - resp->hdr.error, - error_str(resp->hdr.error), - resp->hdr.printer_major, - resp->hdr.printer_minor, error_codes(resp->hdr.printer_major, resp->hdr.printer_minor)); + resp.hdr.error, + sinfonia_error_str(resp.hdr.error), + resp.hdr.printer_major, + resp.hdr.printer_minor, error_codes(resp.hdr.printer_major, resp.hdr.printer_minor)); } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_status_resp) - sizeof(struct s2145_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s2145_status_resp) - sizeof(struct sinfonia_status_hdr))) return 0; INFO(" Print Counts:\n"); - INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp->count_paper)); - INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp->count_lifetime)); - INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp->count_maint)); - INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp->count_head)); - INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp->count_cutter)); - INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp->count_ribbon_left)); + INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp.count_paper)); + INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp.count_lifetime)); + INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp.count_maint)); + INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp.count_head)); + INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp.count_cutter)); + INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp.count_ribbon_left)); INFO("Bank 1: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank1_status, bank_statuses(resp->bank1_status), - resp->bank1_printid, - le16_to_cpu(resp->bank1_finished), - le16_to_cpu(resp->bank1_specified), - le16_to_cpu(resp->bank1_remaining)); + resp.bank1_status, sinfonia_bank_statuses(resp.bank1_status), + resp.bank1_printid, + le16_to_cpu(resp.bank1_finished), + le16_to_cpu(resp.bank1_specified), + le16_to_cpu(resp.bank1_remaining)); INFO("Bank 2: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank2_status, bank_statuses(resp->bank1_status), - resp->bank2_printid, - le16_to_cpu(resp->bank2_finished), - le16_to_cpu(resp->bank2_specified), - le16_to_cpu(resp->bank2_remaining)); + resp.bank2_status, sinfonia_bank_statuses(resp.bank1_status), + resp.bank2_printid, + le16_to_cpu(resp.bank2_finished), + le16_to_cpu(resp.bank2_specified), + le16_to_cpu(resp.bank2_remaining)); - INFO("Tonecurve Status: 0x%02x (%s)\n", resp->tonecurve_status, tonecurve_statuses(resp->tonecurve_status)); + INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, sinfonia_tonecurve_statuses(resp.tonecurve_status)); return 0; } static int get_fwinfo(struct shinkos2145_ctx *ctx) { - struct s2145_fwinfo_cmd cmd; - struct s2145_fwinfo_resp *resp = (struct s2145_fwinfo_resp *)rdbuf; + struct sinfonia_fwinfo_cmd cmd; + struct sinfonia_fwinfo_resp resp; int num = 0; int i; - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_FWINFO); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_FWINFO); cmd.hdr.len = cpu_to_le16(1); INFO("FW Information:\n"); @@ -922,106 +489,74 @@ static int get_fwinfo(struct shinkos2145_ctx *ctx) int ret; cmd.target = i; - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); continue; } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_fwinfo_resp) - sizeof(struct s2145_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_fwinfo_resp) - sizeof(struct sinfonia_status_hdr))) continue; INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i), - resp->major, resp->minor); + resp.major, resp.minor); #if 0 - INFO(" name: '%s'\n", resp->name); - INFO(" type: '%s'\n", resp->type); - INFO(" date: '%s'\n", resp->date); - INFO(" version: %02x.%02x (CRC %04x)\n", resp->major, resp->minor, - le16_to_cpu(resp->checksum)); + INFO(" name: '%s'\n", resp.name); + INFO(" type: '%s'\n", resp.type); + INFO(" date: '%s'\n", resp.date); + INFO(" version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor, + le16_to_cpu(resp.checksum)); #endif } return 0; } -static int get_errorlog(struct shinkos2145_ctx *ctx) -{ - struct s2145_cmd_hdr cmd; - struct s2145_errorlog_resp *resp = (struct s2145_errorlog_resp *) rdbuf; - int ret, num = 0; - int i; - - cmd.cmd = cpu_to_le16(S2145_CMD_ERRORLOG); - cmd.len = cpu_to_le16(0); - - if ((ret = s2145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); - return ret; - } - - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_errorlog_resp) - sizeof(struct s2145_status_hdr))) - return -2; - - INFO("Stored Error Events: %u entries:\n", resp->count); - for (i = 0 ; i < resp->count ; i++) { - INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i, - le32_to_cpu(resp->items[i].print_counter), - resp->items[i].major, resp->items[i].minor, - error_codes(resp->items[i].major, resp->items[i].minor)); - } - return 0; -} - static void dump_mediainfo(struct s2145_mediainfo_resp *resp) { int i; INFO("Supported Media Information: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { - INFO(" %02d: C 0x%02x (%s), %04ux%04u, M 0x%02x (%s), P 0x%02x (%s)\n", i, - resp->items[i].code, print_sizes(resp->items[i].code), - le16_to_cpu(resp->items[i].columns), - le16_to_cpu(resp->items[i].rows), - resp->items[i].media_type, media_types(resp->items[i].media_type), - resp->items[i].print_type, print_methods(resp->items[i].print_type)); + INFO(" %02d: C 0x%02x (%s), %04ux%04u, P 0x%02x (%s)\n", i, + resp->items[i].code, + sinfonia_print_codes(resp->items[i].code, 0), + resp->items[i].columns, + resp->items[i].rows, + resp->items[i].method, + sinfonia_print_methods(resp->items[i].method)); } } static int get_user_string(struct shinkos2145_ctx *ctx) { - struct s2145_cmd_hdr cmd; - struct s2145_getunique_resp *resp = (struct s2145_getunique_resp*) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s2145_getunique_resp resp; int ret, num = 0; - cmd.cmd = cpu_to_le16(S2145_CMD_GETUNIQUE); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETUNIQUE); cmd.len = cpu_to_le16(0); - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp) - 1, + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } /* Null-terminate */ - resp->hdr.payload_len = le16_to_cpu(resp->hdr.payload_len); - if (resp->hdr.payload_len > 23) - resp->hdr.payload_len = 23; - resp->data[resp->hdr.payload_len] = 0; - INFO("Unique String: '%s'\n", resp->data); + resp.hdr.payload_len = le16_to_cpu(resp.hdr.payload_len); + if (resp.hdr.payload_len > 23) + resp.hdr.payload_len = 23; + resp.data[resp.hdr.payload_len] = 0; + INFO("Unique String: '%s'\n", resp.data); return 0; } static int set_user_string(struct shinkos2145_ctx *ctx, char *str) { struct s2145_setunique_cmd cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; + struct sinfonia_status_hdr resp; int ret, num = 0; if (str) { @@ -1034,59 +569,13 @@ static int set_user_string(struct shinkos2145_ctx *ctx, char *str) cmd.len = 0; } - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_SETUNIQUE); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_SETUNIQUE); cmd.hdr.len = cpu_to_le16(cmd.len + 1); - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, cmd.len + 1 + sizeof(cmd.hdr), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - return 0; -} - -static int cancel_job(struct shinkos2145_ctx *ctx, char *str) -{ - struct s2145_cancel_cmd cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; - int ret, num = 0; - - if (!str) - return -1; - - cmd.id = atoi(str); - - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_CANCELJOB); - cmd.hdr.len = cpu_to_le16(1); - - if ((ret = s2145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - return 0; -} - -static int flash_led(struct shinkos2145_ctx *ctx) -{ - struct s2145_cmd_hdr cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; - int ret, num = 0; - - cmd.cmd = cpu_to_le16(S2145_CMD_FLASHLED); - cmd.len = cpu_to_le16(0); - - if ((ret = s2145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } @@ -1096,19 +585,19 @@ static int flash_led(struct shinkos2145_ctx *ctx) static int reset_curve(struct shinkos2145_ctx *ctx, int target) { struct s2145_reset_cmd cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; + struct sinfonia_status_hdr resp; + int ret, num = 0; cmd.target = target; - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_RESET); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_RESET); cmd.hdr.len = cpu_to_le16(1); - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } @@ -1118,19 +607,18 @@ static int reset_curve(struct shinkos2145_ctx *ctx, int target) static int button_set(struct shinkos2145_ctx *ctx, int enable) { struct s2145_button_cmd cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; + struct sinfonia_status_hdr resp; int ret, num = 0; - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_BUTTON); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_BUTTON); cmd.hdr.len = cpu_to_le16(1); cmd.enabled = enable; - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&cmd, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } @@ -1140,43 +628,42 @@ static int button_set(struct shinkos2145_ctx *ctx, int enable) static int get_tonecurve(struct shinkos2145_ctx *ctx, int type, char *fname) { struct s2145_readtone_cmd cmd; - struct s2145_readtone_resp *resp = (struct s2145_readtone_resp *) rdbuf; + struct s2145_readtone_resp resp; int ret, num = 0; uint8_t *data; - uint16_t curves[UPDATE_SIZE] = { 0 } ; + uint16_t curves[TONE_CURVE_SIZE] = { 0 } ; int i,j; cmd.curveid = type; - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_READTONE); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_READTONE); cmd.hdr.len = cpu_to_le16(1); - INFO("Dump %s Tone Curve to '%s'\n", tonecurve_statuses(type), fname); + INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname); - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } - resp->total_size = le16_to_cpu(resp->total_size); + resp.total_size = le16_to_cpu(resp.total_size); - data = malloc(resp->total_size * 2); + data = malloc(resp.total_size * 2); if (!data) { ERROR("Memory allocation failure! (%d bytes)\n", - resp->total_size * 2); + resp.total_size * 2); return -1; } i = 0; - while (i < resp->total_size) { - ret = read_data(ctx->dev, ctx->endp_up, + while (i < resp.total_size) { + ret = read_data(ctx->dev.dev, ctx->dev.endp_up, data + i, - resp->total_size * 2 - i, + resp.total_size * 2 - i, &num); if (ret < 0) goto done; @@ -1184,7 +671,7 @@ static int get_tonecurve(struct shinkos2145_ctx *ctx, int type, char *fname) } i = j = 0; - while (i < resp->total_size) { + while (i < resp.total_size) { memcpy(curves + j, data + i+2, data[i+1]); j += data[i+1] / 2; i += data[i+1] + 2; @@ -1198,11 +685,11 @@ static int get_tonecurve(struct shinkos2145_ctx *ctx, int type, char *fname) goto done; } - for (i = 0 ; i < UPDATE_SIZE; i++) { + for (i = 0 ; i < TONE_CURVE_SIZE; i++) { /* Byteswap appropriately */ curves[i] = cpu_to_be16(le16_to_cpu(curves[i])); } - ret = write(tc_fd, curves, UPDATE_SIZE * sizeof(uint16_t)); + ret = write(tc_fd, curves, TONE_CURVE_SIZE * sizeof(uint16_t)); if (ret < 0) ERROR("Can't write curve file\n"); else @@ -1220,59 +707,53 @@ done: static int set_tonecurve(struct shinkos2145_ctx *ctx, int target, char *fname) { struct s2145_update_cmd cmd; - struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf; + struct sinfonia_status_hdr resp; int ret, num = 0; - INFO("Set %s Tone Curve from '%s'\n", update_targets(target), fname); + INFO("Set %s Tone Curve from '%s'\n", sinfonia_update_targets(target), fname); - uint16_t *data = malloc(UPDATE_SIZE * sizeof(uint16_t)); + uint16_t *data = malloc(TONE_CURVE_SIZE * sizeof(uint16_t)); if (!data) { ERROR("Memory allocation failure! (%d bytes)\n", - UPDATE_SIZE); + TONE_CURVE_SIZE); return -1; } /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE * sizeof(uint16_t)) != (UPDATE_SIZE * sizeof(uint16_t))) { - ret = -2; + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) { + ERROR("Failed to read Tone Curve file\n"); goto done; } - close(tc_fd); + /* Byteswap data to local CPU.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { + for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) { data[ret] = be16_to_cpu(data[ret]); } /* Set up command */ cmd.target = target; cmd.reserved = 0; - cmd.size = cpu_to_le32(UPDATE_SIZE * sizeof(uint16_t)); + cmd.size = cpu_to_le32(TONE_CURVE_SIZE * sizeof(uint16_t)); - cmd.hdr.cmd = cpu_to_le16(S2145_CMD_UPDATE); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_UPDATE); cmd.hdr.len = cpu_to_le16(sizeof(struct s2145_update_cmd)-sizeof(cmd.hdr)); /* Byteswap data to format printer is expecting.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { + for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) { data[ret] = cpu_to_le16(data[ret]); } - if ((ret = s2145_do_cmd(ctx, + if ((ret = sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); goto done; } /* Sent transfer */ - if ((ret = send_data(ctx->dev, ctx->endp_down, - (uint8_t *) data, UPDATE_SIZE * sizeof(uint16_t)))) { + if ((ret = send_data(ctx->dev.dev, ctx->dev.endp_down, + (uint8_t *) data, TONE_CURVE_SIZE * sizeof(uint16_t)))) { goto done; } @@ -1288,7 +769,6 @@ static void shinkos2145_cmdline(void) DEBUG("\t\t[ -c filename ] # Get user/NV tone curve\n"); DEBUG("\t\t[ -C filename ] # Set user/NV tone curve\n"); DEBUG("\t\t[ -e ] # Query error log\n"); - DEBUG("\t\t[ -f ] # Use fast return mode\n"); DEBUG("\t\t[ -F ] # Flash Printer LED\n"); DEBUG("\t\t[ -i ] # Query printer info\n"); DEBUG("\t\t[ -l filename ] # Get current tone curve\n"); @@ -1328,10 +808,10 @@ int shinkos2145_cmdline_arg(void *vctx, int argc, char **argv) j = set_tonecurve(ctx, TONECURVE_USER, optarg); break; case 'e': - j = get_errorlog(ctx); + j = sinfonia_geterrorlog(&ctx->dev); break; case 'F': - j = flash_led(ctx); + j = sinfonia_flashled(&ctx->dev); break; case 'i': j = get_fwinfo(ctx); @@ -1361,7 +841,7 @@ int shinkos2145_cmdline_arg(void *vctx, int argc, char **argv) j = set_user_string(ctx, optarg); break; case 'X': - j = cancel_job(ctx, optarg); + j = sinfonia_canceljob(&ctx->dev, atoi(optarg)); break; default: break; /* Ignore completely */ @@ -1391,12 +871,12 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int uint8_t endp_up, uint8_t endp_down, uint8_t jobid) { struct shinkos2145_ctx *ctx = vctx; - int i; - ctx->dev = dev; - ctx->endp_up = endp_up; - ctx->endp_down = endp_down; - ctx->type = type; + ctx->dev.dev = dev; + ctx->dev.endp_up = endp_up; + ctx->dev.endp_down = endp_down; + ctx->dev.type = type; + ctx->dev.error_codes = &error_codes; /* Ensure jobid is sane */ ctx->jobid = (jobid & 0x7f); @@ -1406,21 +886,25 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int int media_prints = 65536; if (test_mode < TEST_MODE_NOATTACH) { /* Query Media */ - struct s2145_cmd_hdr cmd; - struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; int num = 0; + int i; - cmd.cmd = cpu_to_le16(S2145_CMD_MEDIAINFO); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_MEDIAINFO); cmd.len = cpu_to_le16(0); - if (s2145_do_cmd(ctx, + if (sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), + (uint8_t*)&ctx->media, sizeof(ctx->media), &num)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return CUPS_BACKEND_FAILED; } - memcpy(&ctx->media, resp, sizeof(ctx->media)); + + /* Byteswap media descriptor.. */ + for (i = 0 ; i < ctx->media.count ; i++) { + ctx->media.items[i].columns = le16_to_cpu(ctx->media.items[i].columns); + ctx->media.items[i].rows = le16_to_cpu(ctx->media.items[i].rows); + } /* Figure out the media type... */ for (i = 0 ; i < ctx->media.count ; i++) { @@ -1430,7 +914,7 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int } } } else { - int media_code = PRINT_MEDIA_6x9; + int media_code = CODE_6x9; if (getenv("MEDIA_CODE")) media_code = atoi(getenv("MEDIA_CODE")); @@ -1439,38 +923,17 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int } ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = print_sizes(ctx->media_code); + ctx->marker.name = sinfonia_print_codes(ctx->media_code, 0); ctx->marker.levelmax = media_prints; ctx->marker.levelnow = -2; return CUPS_BACKEND_OK; } -static void shinkos2145_cleanup_job(const void *vjob) -{ - const struct shinkos2145_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void shinkos2145_teardown(void *vctx) { - struct shinkos2145_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct shinkos2145_ctx *ctx = vctx; + struct sinfonia_printjob *job = NULL; int ret; - uint8_t tmpbuf[4]; - - struct shinkos2145_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1481,70 +944,18 @@ static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, in return CUPS_BACKEND_RETRY_CURRENT; } memset(job, 0, sizeof(*job)); - job->copies = copies; // XXX hdr.copies - - /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - if (ret == 0) - return CUPS_BACKEND_CANCEL; - ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); - perror("ERROR: Read failed"); - return ret; - } - - if (le32_to_cpu(job->hdr.len1) != 0x10 || - le32_to_cpu(job->hdr.len2) != 0x64 || - le32_to_cpu(job->hdr.dpi) != 300) { - ERROR("Unrecognized header data format!\n"); - return CUPS_BACKEND_CANCEL; - } - - if (le32_to_cpu(job->hdr.model) != 2145) { - ERROR("Unrecognized printer (%u)!\n", le32_to_cpu(job->hdr.model)); - return CUPS_BACKEND_CANCEL; - } - - job->datalen = le32_to_cpu(job->hdr.rows) * le32_to_cpu(job->hdr.columns) * 3; - job->databuf = malloc(job->datalen); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - return CUPS_BACKEND_RETRY_CURRENT; - } - - { - int remain = job->datalen; - uint8_t *ptr = job->databuf; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%d)\n", - ret, remain, job->datalen); - perror("ERROR: Read failed"); - return ret; - } - ptr += ret; - remain -= ret; - } while (remain); - } - - /* Make sure footer is sane too */ - ret = read(data_fd, tmpbuf, 4); - if (ret != 4) { - ERROR("Read failed (%d/%d/%d)\n", - ret, 4, 4); - perror("ERROR: Read failed"); + /* Common read/parse code */ + ret = sinfonia_read_parse(data_fd, 2145, job); + if (ret) { + free(job); return ret; } - if (tmpbuf[0] != 0x04 || - tmpbuf[1] != 0x03 || - tmpbuf[2] != 0x02 || - tmpbuf[3] != 0x01) { - ERROR("Unrecognized footer data format!\n"); - return CUPS_BACKEND_FAILED; - } + + if (job->jp.copies > 1) + job->copies = job->jp.copies; + else + job->copies = copies; *vjob = job; @@ -1555,23 +966,19 @@ static int shinkos2145_main_loop(void *vctx, const void *vjob) { struct shinkos2145_ctx *ctx = vctx; int ret, num; - uint8_t cmdbuf[CMDBUF_LEN]; - uint8_t rdbuf2[READBACK_LEN]; int i, last_state = -1, state = S_IDLE; - struct s2145_cmd_hdr *cmd = (struct s2145_cmd_hdr *) cmdbuf;; - struct s2145_print_cmd *print = (struct s2145_print_cmd *) cmdbuf; - struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; - - struct shinkos2145_printjob *job = (struct shinkos2145_printjob*) vjob; + struct sinfonia_printjob *job = (struct sinfonia_printjob*) vjob; + struct sinfonia_cmd_hdr cmd; + struct s2145_status_resp sts, sts2; /* Validate print sizes */ for (i = 0; i < ctx->media.count ; i++) { /* Look for matching media */ - if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(job->hdr.columns)) && - le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(job->hdr.rows)) && - ctx->media.items[i].print_type == le32_to_cpu(job->hdr.method)) + if (ctx->media.items[i].columns == job->jp.columns && + ctx->media.items[i].rows == job->jp.rows && + ctx->media.items[i].method == job->jp.method) break; } if (i == ctx->media.count) { @@ -1588,32 +995,30 @@ top: } /* Send Status Query */ - memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S2145_CMD_STATUS); - cmd->len = cpu_to_le16(0); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); - if ((ret = s2145_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(struct s2145_status_hdr), + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&sts, sizeof(sts), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd)); return CUPS_BACKEND_FAILED; } - if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) { - memcpy(rdbuf2, rdbuf, READBACK_LEN); + if (memcmp(&sts, &sts2, sizeof(sts))) { + memcpy(&sts2, &sts, sizeof(sts)); INFO("Printer Status: 0x%02x (%s)\n", - sts->hdr.status, status_str(sts->hdr.status)); + sts.hdr.status, sinfonia_status_str(sts.hdr.status)); - if (ctx->marker.levelnow != (int)sts->count_ribbon_left) { - ctx->marker.levelnow = sts->count_ribbon_left; + if (ctx->marker.levelnow != (int)sts.count_ribbon_left) { + ctx->marker.levelnow = sts.count_ribbon_left; dump_markers(&ctx->marker, 1, 0); } - if (sts->hdr.result != RESULT_SUCCESS) + if (sts.hdr.result != RESULT_SUCCESS) goto printer_error; - if (sts->hdr.error == ERROR_PRINTER) + if (sts.hdr.error == ERROR_PRINTER) goto printer_error; } else if (state == last_state) { sleep(1); @@ -1629,8 +1034,8 @@ top: /* make sure we're not colliding with an existing jobid */ - while (ctx->jobid == sts->bank1_printid || - ctx->jobid == sts->bank2_printid) { + while (ctx->jobid == sts.bank1_printid || + ctx->jobid == sts.bank2_printid) { ctx->jobid++; ctx->jobid &= 0x7f; if (!ctx->jobid) @@ -1638,47 +1043,48 @@ top: } /* If either bank is free, continue */ - if (sts->bank1_status == BANK_STATUS_FREE || - sts->bank2_status == BANK_STATUS_FREE) + if (sts.bank1_status == BANK_STATUS_FREE || + sts.bank2_status == BANK_STATUS_FREE) state = S_PRINTER_READY_CMD; break; - case S_PRINTER_READY_CMD: + case S_PRINTER_READY_CMD: { + struct sinfonia_printcmd10_hdr print; + INFO("Sending print job (internal id %u)\n", ctx->jobid); - memset(cmdbuf, 0, CMDBUF_LEN); - print->hdr.cmd = cpu_to_le16(S2145_CMD_PRINTJOB); - print->hdr.len = cpu_to_le16(sizeof (*print) - sizeof(*cmd)); - - print->id = ctx->jobid; - print->count = cpu_to_le16(job->copies); - print->columns = cpu_to_le16(le32_to_cpu(job->hdr.columns)); - print->rows = cpu_to_le16(le32_to_cpu(job->hdr.rows)); - print->media = le32_to_cpu(job->hdr.media); - print->mode = le32_to_cpu(job->hdr.mode); - print->method = le32_to_cpu(job->hdr.method); - - if ((ret = s2145_do_cmd(ctx, - cmdbuf, sizeof(*print), - sizeof(struct s2145_status_hdr), + memset(&print, 0, sizeof(print)); + print.hdr.cmd = cpu_to_le16(SINFONIA_CMD_PRINTJOB); + print.hdr.len = cpu_to_le16(sizeof(print) - sizeof(print.hdr)); + + print.jobid = ctx->jobid; + print.copies = cpu_to_le16(job->copies); + print.columns = cpu_to_le16(job->jp.columns); + print.rows = cpu_to_le16(job->jp.rows); + print.media = job->jp.media; + print.oc_mode = job->jp.oc_mode; + print.method = job->jp.method; + + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&print, sizeof(print), + (uint8_t*)&sts, sizeof(sts), &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd)); return ret; } - if (sts->hdr.result != RESULT_SUCCESS) { - if (sts->hdr.error == ERROR_BUFFER_FULL) { + if (sts.hdr.result != RESULT_SUCCESS) { + if (sts.hdr.error == ERROR_BUFFER_FULL) { INFO("Printer Buffers full, retrying\n"); break; - } else if ((sts->hdr.status & 0xf0) == 0x30 || sts->hdr.status == 0x21) { - INFO("Printer busy (%s), retrying\n", status_str(sts->hdr.status)); + } else if ((sts.hdr.status & 0xf0) == 0x30 || sts.hdr.status == 0x21) { + INFO("Printer busy (%s), retrying\n", sinfonia_status_str(sts.hdr.status)); break; - } else if (sts->hdr.status != ERROR_NONE) + } else if (sts.hdr.status != ERROR_NONE) goto printer_error; } INFO("Sending image data to printer\n"); - if ((ret = send_data(ctx->dev, ctx->endp_down, + if ((ret = send_data(ctx->dev.dev, ctx->dev.endp_down, job->databuf, job->datalen))) return CUPS_BACKEND_FAILED; @@ -1686,13 +1092,14 @@ top: sleep(1); state = S_PRINTER_SENT_DATA; break; + } case S_PRINTER_SENT_DATA: if (fast_return) { INFO("Fast return mode enabled.\n"); state = S_FINISHED; - } else if (sts->hdr.status == STATUS_READY || - sts->hdr.status == STATUS_FINISHED || - sts->hdr.status == ERROR_PRINTER) { + } else if (sts.hdr.status == STATUS_READY || + sts.hdr.status == STATUS_FINISHED || + sts.hdr.status == ERROR_PRINTER) { state = S_FINISHED; } break; @@ -1703,14 +1110,14 @@ top: if (state != S_FINISHED) goto top; - if (sts->hdr.status == ERROR_PRINTER) { - if(sts->hdr.error == ERROR_NONE) - sts->hdr.error = sts->hdr.status; + if (sts.hdr.status == ERROR_PRINTER) { + if(sts.hdr.error == ERROR_NONE) + sts.hdr.error = sts.hdr.status; INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", - sts->hdr.error, - error_str(sts->hdr.error), - sts->hdr.printer_major, - sts->hdr.printer_minor, error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + sts.hdr.error, + sinfonia_error_str(sts.hdr.error), + sts.hdr.printer_major, + sts.hdr.printer_minor, error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); } INFO("Print complete\n"); @@ -1719,45 +1126,41 @@ top: printer_error: ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n", - sts->hdr.error, - error_str(sts->hdr.error), - sts->hdr.status, - status_str(sts->hdr.status), - sts->hdr.printer_major, sts->hdr.printer_minor, - error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + sts.hdr.error, + sinfonia_error_str(sts.hdr.error), + sts.hdr.status, + sinfonia_status_str(sts.hdr.status), + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); return CUPS_BACKEND_FAILED; } static int shinkos2145_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len) { - struct s2145_cmd_hdr cmd; - struct s2145_getunique_resp *resp = (struct s2145_getunique_resp*) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s2145_getunique_resp resp; int ret, num = 0; - struct shinkos2145_ctx ctx = { + struct sinfonia_usbdev sdev = { .dev = dev, .endp_up = endp_up, .endp_down = endp_down, }; - cmd.cmd = cpu_to_le16(S2145_CMD_GETUNIQUE); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETUNIQUE); cmd.len = cpu_to_le16(0); - if ((ret = s2145_do_cmd(&ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp) - 1, - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&sdev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return ret; } - /* Null-terminate */ - resp->hdr.payload_len = le16_to_cpu(resp->hdr.payload_len); - if (resp->hdr.payload_len > 23) - resp->hdr.payload_len = 23; - resp->data[resp->hdr.payload_len] = 0; - strncpy(buf, (char*)resp->data, buf_len); - buf[buf_len-1] = 0; /* ensure it's null terminated */ + /* Copy and Null-terminate */ + num = (buf_len > (int)sizeof(resp.data)) ? (int)sizeof(resp.data) : (buf_len - 1); + memcpy(buf, resp.data, num); + buf[num] = 0; return CUPS_BACKEND_OK; } @@ -1765,23 +1168,22 @@ static int shinkos2145_query_serno(struct libusb_device_handle *dev, uint8_t end static int shinkos2145_query_markers(void *vctx, struct marker **markers, int *count) { struct shinkos2145_ctx *ctx = vctx; - struct s2145_cmd_hdr cmd; - struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s2145_status_resp sts; int num; /* Query Status */ - cmd.cmd = cpu_to_le16(S2145_CMD_STATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if (s2145_do_cmd(ctx, + if (sinfonia_docmd(&ctx->dev, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*sts), + (uint8_t*)&sts, sizeof(sts), &num)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return CUPS_BACKEND_FAILED; } - ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts->count_ribbon_left); + ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts.count_ribbon_left); *markers = &ctx->marker; *count = 1; @@ -1804,14 +1206,13 @@ static const char *shinkos2145_prefixes[] = { struct dyesub_backend shinkos2145_backend = { .name = "Shinko/Sinfonia CHC-S2145/S2", - .version = "0.55", + .version = "0.61" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = shinkos2145_prefixes, .cmdline_usage = shinkos2145_cmdline, .cmdline_arg = shinkos2145_cmdline_arg, .init = shinkos2145_init, .attach = shinkos2145_attach, - .teardown = shinkos2145_teardown, - .cleanup_job = shinkos2145_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = shinkos2145_read_parse, .main_loop = shinkos2145_main_loop, .query_serno = shinkos2145_query_serno, diff --git a/src/cups/backend_shinkos6145.c b/src/cups/backend_shinkos6145.c index e795831..bbe5912 100644 --- a/src/cups/backend_shinkos6145.c +++ b/src/cups/backend_shinkos6145.c @@ -1,7 +1,7 @@ /* * Shinko/Sinfonia CHC-S6145 CUPS backend -- libusb-1.0 version * - * (c) 2015-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2015-2019 Solomon Peachy <pizza@shaftnet.org> * * Low-level documentation was provided by Sinfonia. Thank you! * @@ -79,6 +79,7 @@ #define BACKEND shinkos6145_backend #include "backend_common.h" +#include "backend_sinfonia.h" /* Image processing library function prototypes */ typedef int (*ImageProcessingFN)(unsigned char *, unsigned short *, void *); @@ -94,46 +95,6 @@ enum { S_FINISHED, }; -/* Structure of printjob header. All fields are LITTLE ENDIAN */ -struct s6145_printjob_hdr { - uint32_t len1; /* Fixed at 0x10 */ - uint32_t model; /* Equal to the printer model (eg '6245' or '1245' decimal) */ - uint32_t media_w; /* 0x02 for 5", 0x03 for 6" */ - uint32_t unk3; /* Fixed at 0x01 */ - - uint32_t len2; /* Fixed at 0x64 */ - uint32_t unk5; - uint32_t media; /* 0x08 5x5, 0x03 5x7, 0x07 2x6, 0x00 4x6, 0x06 6x6/6x6+6x2/4x6*2/6x8 */ - uint32_t unk6; - - uint32_t method; /* 0x00 normal, 0x02 4x6*2, 0x04 2x6*2, 0x05 6x6+2x6 */ - uint32_t qual; /* 0x00 default, 0x01 std */ - uint32_t oc_mode; /* 0x00 default, 0x01 off, 0x02 glossy, 0x03 matte */ - uint32_t unk8; - - uint32_t unk9; - uint32_t columns; - uint32_t rows; - uint32_t copies; - - uint32_t unk10; - uint32_t unk11; - uint32_t unk12; - uint32_t unk13; - - uint32_t unk14; - uint32_t unk15; - uint32_t dpi; /* Fixed at '300' (decimal) */ - uint32_t unk16; - - uint32_t unk17; - uint32_t unk18; - uint32_t unk19; - uint32_t unk20; - - uint32_t ext_flags; /* 0x00 in the official headers. 0x01 to mark inout data as YMC planar */ -} __attribute__((packed)); - /* "Image Correction Parameter" File */ // 128 bytes total, apparently an array of 32-bit values struct tankParamTable { @@ -261,79 +222,8 @@ struct shinkos6145_correctionparam { } __attribute__((packed)); /* 16384 bytes */ /* Structs for printer */ -struct s6145_cmd_hdr { - uint16_t cmd; - uint16_t len; /* Not including this header */ -} __attribute__((packed)); - -#define S6145_CMD_GETSTATUS 0x0001 -#define S6145_CMD_MEDIAINFO 0x0002 -#define S6145_CMD_ERRORLOG 0x0004 -#define S6145_CMD_GETPARAM 0x0005 -#define S6145_CMD_GETSERIAL 0x0006 -#define S6145_CMD_PRINTSTAT 0x0007 -#define S6145_CMD_EXTCOUNTER 0x0008 -#define S6145_CMD_MEMORYBANK 0x000A // Brava 21 only? - -#define S6145_CMD_PRINTJOB 0x4001 -#define S6145_CMD_CANCELJOB 0x4002 -#define S6145_CMD_FLASHLED 0x4003 -#define S6145_CMD_RESET 0x4004 -#define S6145_CMD_READTONE 0x4005 -#define S6145_CMD_SETPARAM 0x4007 - -#define S6145_CMD_GETCORR 0x400D -#define S6145_CMD_GETEEPROM 0x400E -#define S6145_CMD_SETEEPROM 0x400F - -#define S6145_CMD_FWINFO 0xC003 -#define S6145_CMD_UPDATE 0xC004 - -static char *cmd_names(uint16_t v) { - switch (le16_to_cpu(v)) { - case S6145_CMD_GETSTATUS: - return "Get Status"; - case S6145_CMD_MEDIAINFO: - return "Get Media Info"; - case S6145_CMD_ERRORLOG: - return "Get Error Log"; - case S6145_CMD_GETPARAM: - return "Get Parameter"; - case S6145_CMD_GETSERIAL: - return "Get Serial Number"; - case S6145_CMD_PRINTSTAT: - return "Get Print ID Status"; - case S6145_CMD_EXTCOUNTER: - return "Get Extended Counters"; - case S6145_CMD_PRINTJOB: - return "Print"; - case S6145_CMD_CANCELJOB: - return "Cancel Print"; - case S6145_CMD_FLASHLED: - return "Flash LEDs"; - case S6145_CMD_RESET: - return "Reset"; - case S6145_CMD_READTONE: - return "Read Tone Curve"; - case S6145_CMD_SETPARAM: - return "Set Parameter"; - case S6145_CMD_GETCORR: - return "Get Image Correction Parameter"; - case S6145_CMD_GETEEPROM: - return "Get EEPROM Backup Parameter"; - case S6145_CMD_SETEEPROM: - return "Set EEPROM Backup Parameter"; - case S6145_CMD_FWINFO: - return "Get Firmware Info"; - case S6145_CMD_UPDATE: - return "Update"; - default: - return "Unknown Command"; - } -} - struct s6145_print_cmd { - struct s6145_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t id; uint16_t count; uint16_t columns; @@ -346,77 +236,6 @@ struct s6145_print_cmd { uint8_t image_avg; } __attribute__((packed)); -#define PRINT_MODE_NO_OC 0x01 -#define PRINT_MODE_GLOSSY 0x02 -#define PRINT_MODE_MATTE 0x03 - -#if 0 -static char *print_modes(uint8_t v) { - switch (v) { - case PRINT_MODE_NO_OC: - return "No Overcoat"; - case PRINT_MODE_GLOSSY: - return "Glossy"; - case PRINT_MODE_MATTE: - return "Matte"; - default: - return "Unknown"; - } -} -#endif - -#define PRINT_METHOD_STD 0x00 -#define PRINT_METHOD_COMBO_2 0x02 -#define PRINT_METHOD_SPLIT 0x04 -#define PRINT_METHOD_DOUBLE 0x08 -#define PRINT_METHOD_NOTRIM 0x80 - -static char *print_methods (uint8_t v) { - switch (v & 0xf) { - case PRINT_METHOD_STD: - return "Standard"; - case PRINT_METHOD_COMBO_2: - return "2up"; - case PRINT_METHOD_SPLIT: - return "Split"; - case PRINT_METHOD_DOUBLE: - return "Double"; - default: - return "Unknown"; - } -} - -struct s6145_cancel_cmd { - struct s6145_cmd_hdr hdr; - uint8_t id; -} __attribute__((packed)); - -struct s6145_reset_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; - uint8_t curveid; -} __attribute__((packed)); - -#define RESET_PRINTER 0x03 -#define RESET_TONE_CURVE 0x04 - -#define TONE_CURVE_ID 0x01 - -struct s6145_readtone_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; - uint8_t curveid; -} __attribute__((packed)); - -#define READ_TONE_CURVE_USER 0x01 -#define READ_TONE_CURVE_CURR 0x02 - -struct s6145_setparam_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; - uint32_t param; -} __attribute__((packed)); - #define PARAM_OC_PRINT 0x20 #define PARAM_PAPER_PRESV 0x3d #define PARAM_DRIVER_MODE 0x3e @@ -445,103 +264,7 @@ struct s6145_setparam_cmd { #define PARAM_SLEEP_120MIN 0x00000004 #define PARAM_SLEEP_240MIN 0x00000005 -struct s6145_seteeprom_cmd { - struct s6145_cmd_hdr hdr; - uint8_t data[256]; /* Maxlen */ -} __attribute__((packed)); - -struct s6145_errorlog_cmd { - struct s6145_cmd_hdr hdr; - uint16_t index; /* 0 is latest */ -} __attribute__((packed)); - -struct s6145_getparam_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; -} __attribute__((packed)); - -struct s6145_getprintidstatus_cmd { - struct s6145_cmd_hdr hdr; - uint8_t id; -} __attribute__((packed)); - -struct s6145_fwinfo_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; -} __attribute__((packed)); - -#define FWINFO_TARGET_MAIN_BOOT 0x01 -#define FWINFO_TARGET_MAIN_APP 0x02 -#define FWINFO_TARGET_PRINT_TABLES 0x03 -#define FWINFO_TARGET_DSP 0x04 - -static char *fwinfo_targets (uint8_t v) { - switch (v) { - case FWINFO_TARGET_MAIN_BOOT: - return "Main Boot "; - case FWINFO_TARGET_MAIN_APP: - return "Main App "; - case FWINFO_TARGET_DSP: - return "DSP "; - case FWINFO_TARGET_PRINT_TABLES: - return "Print Tables"; - default: - return "Unknown "; - } -} - -struct s6145_update_cmd { - struct s6145_cmd_hdr hdr; - uint8_t target; - uint8_t curve_id; - uint8_t reset; // ?? - uint8_t reserved[3]; - uint32_t size; -} __attribute__((packed)); - -#define UPDATE_TARGET_USER 0x03 -#define UPDATE_TARGET_CURRENT 0x04 - -static char *update_targets (uint8_t v) { - switch (v) { - case UPDATE_TARGET_USER: - return "User"; - case UPDATE_TARGET_CURRENT: - return "Current"; - default: - return "Unknown"; - } -} - -#define UPDATE_SIZE 0x600 -/* Update is three channels, Y, M, C; - each is 256 entries of 11-bit data padded to 16-bits. - Printer expects LE data. We use BE data on disk. -*/ - -struct s6145_status_hdr { - uint8_t result; - uint8_t error; - uint8_t printer_major; - uint8_t printer_minor; - uint8_t reserved[3]; - uint8_t status; - uint16_t payload_len; -} __attribute__((packed)); - -#define RESULT_SUCCESS 0x01 -#define RESULT_FAIL 0x02 - -#define ERROR_NONE 0x00 -#define ERROR_INVALID_PARAM 0x01 -#define ERROR_MAIN_APP_INACTIVE 0x02 -#define ERROR_COMMS_TIMEOUT 0x03 -#define ERROR_MAINT_NEEDED 0x04 -#define ERROR_BAD_COMMAND 0x05 -#define ERROR_PRINTER 0x11 -#define ERROR_BUFFER_FULL 0x21 - -static char *error_codes(uint8_t major, uint8_t minor) +static const char *error_codes(uint8_t major, uint8_t minor) { switch(major) { case 0x01: /* "Controller Error" */ @@ -734,102 +457,8 @@ static char *error_codes(uint8_t major, uint8_t minor) } } -static char *error_str(uint8_t v) { - switch (v) { - case ERROR_NONE: - return "None"; - case ERROR_INVALID_PARAM: - return "Invalid Command Parameter"; - case ERROR_MAIN_APP_INACTIVE: - return "Main App Inactive"; - case ERROR_COMMS_TIMEOUT: - return "Main Communication Timeout"; - case ERROR_MAINT_NEEDED: - return "Maintenance Needed"; - case ERROR_BAD_COMMAND: - return "Inappropriate Command"; - case ERROR_PRINTER: - return "Printer Error"; - case ERROR_BUFFER_FULL: - return "Buffer Full"; - default: - return "Unknown"; - } -} - -#define STATUS_READY 0x00 -#define STATUS_INIT_CPU 0x31 -#define STATUS_INIT_RIBBON 0x32 -#define STATUS_INIT_PAPER 0x33 -#define STATUS_THERMAL_PROTECT 0x34 -#define STATUS_USING_PANEL 0x35 -#define STATUS_SELF_DIAG 0x36 -#define STATUS_DOWNLOADING 0x37 - -#define STATUS_FEEDING_PAPER 0x61 -#define STATUS_PRE_HEAT 0x62 -#define STATUS_PRINT_Y 0x63 -#define STATUS_BACK_FEED_Y 0x64 -#define STATUS_PRINT_M 0x65 -#define STATUS_BACK_FEED_M 0x66 -#define STATUS_PRINT_C 0x67 -#define STATUS_BACK_FEED_C 0x68 -#define STATUS_PRINT_OP 0x69 -#define STATUS_PAPER_CUT 0x6A -#define STATUS_PAPER_EJECT 0x6B -#define STATUS_BACK_FEED_E 0x6C - -static char *status_str(uint8_t v) { - switch (v) { - case STATUS_READY: - return "Ready"; - case STATUS_INIT_CPU: - return "Initializing CPU"; - case STATUS_INIT_RIBBON: - return "Initializing Ribbon"; - case STATUS_INIT_PAPER: - return "Loading Paper"; - case STATUS_THERMAL_PROTECT: - return "Thermal Protection"; - case STATUS_USING_PANEL: - return "Using Operation Panel"; - case STATUS_SELF_DIAG: - return "Processing Self Diagnosis"; - case STATUS_DOWNLOADING: - return "Processing Download"; - case STATUS_FEEDING_PAPER: - return "Feeding Paper"; - case STATUS_PRE_HEAT: - return "Pre-Heating"; - case STATUS_PRINT_Y: - return "Printing Yellow"; - case STATUS_BACK_FEED_Y: - return "Back-Feeding - Yellow Complete"; - case STATUS_PRINT_M: - return "Printing Magenta"; - case STATUS_BACK_FEED_M: - return "Back-Feeding - Magenta Complete"; - case STATUS_PRINT_C: - return "Printing Cyan"; - case STATUS_BACK_FEED_C: - return "Back-Feeding - Cyan Complete"; - case STATUS_PRINT_OP: - return "Laminating"; - case STATUS_PAPER_CUT: - return "Cutting Paper"; - case STATUS_PAPER_EJECT: - return "Ejecting Paper"; - case STATUS_BACK_FEED_E: - return "Back-Feeding - Ejected"; - case ERROR_PRINTER: - return "Printer Error"; - default: - return "Unknown"; - } -} - struct s6145_status_resp { - struct s6145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint32_t count_lifetime; uint32_t count_maint; uint32_t count_paper; @@ -855,111 +484,11 @@ struct s6145_status_resp { uint8_t reserved3[6]; } __attribute__((packed)); -#define BANK_STATUS_FREE 0x00 -#define BANK_STATUS_XFER 0x01 -#define BANK_STATUS_FULL 0x02 -#define BANK_STATUS_PRINTING 0x12 - -static char *bank_statuses(uint8_t v) -{ - switch (v) { - case BANK_STATUS_FREE: - return "Free"; - case BANK_STATUS_XFER: - return "Xfer"; - case BANK_STATUS_FULL: - return "Full"; - case BANK_STATUS_PRINTING: - return "Printing"; - default: - return "Unknown"; - } -} - -#define TONECURVE_INIT 0x00 -#define TONECURVE_USER 0x01 -#define TONECURVE_CURRENT 0x02 - -static char *tonecurve_statuses (uint8_t v) -{ - switch(v) { - case 0: - return "Initial"; - case 1: - return "UserSet"; - case 2: - return "Current"; - default: - return "Unknown"; - } -} - struct s6145_geteeprom_resp { - struct s6145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t data[256]; } __attribute__((packed)); -struct s6145_readtone_resp { - struct s6145_status_hdr hdr; - uint16_t total_size; -} __attribute__((packed)); - -struct s6145_mediainfo_item { - uint8_t media_code; - uint16_t columns; - uint16_t rows; - uint8_t reserved; - uint8_t print_method; /* PRINT_METHOD_* */ - uint8_t reserved2[3]; -} __attribute__((packed)); - -#define MEDIA_4x6 0x00 -#define MEDIA_3_5x5 0x01 -#define MEDIA_5x7 0x03 -#define MEDIA_6x9 0x05 -#define MEDIA_6x8 0x06 -#define MEDIA_2x6 0x07 -#define MEDIA_6x6 0x08 -#define MEDIA_89x60mm 0x10 -#define MEDIA_89x59mm 0x11 -#define MEDIA_89x58mm 0x12 -#define MEDIA_89x57mm 0x13 -#define MEDIA_89x56mm 0x14 -#define MEDIA_89x55mm 0x15 - -static char *print_sizes (uint8_t v) { - switch (v) { - case MEDIA_4x6: - return "4x6"; - case MEDIA_3_5x5: - return "3.5x5"; - case MEDIA_5x7: - return "5x7"; - case MEDIA_6x9: - return "6x9"; - case MEDIA_6x8: - return "6x8"; - case MEDIA_2x6: - return "2x6"; - case MEDIA_6x6: - return "6x6"; - case MEDIA_89x60mm: - return "89x60mm"; - case MEDIA_89x59mm: - return "89x59mm"; - case MEDIA_89x58mm: - return "89x58mm"; - case MEDIA_89x57mm: - return "89x57mm"; - case MEDIA_89x56mm: - return "89x56mm"; - case MEDIA_89x55mm: - return "89x55mm"; - default: - return "Unknown"; - } -} - #define RIBBON_NONE 0x00 #define RIBBON_4x6 0x01 #define RIBBON_3_5x5 0x02 @@ -1000,76 +529,22 @@ static const char *print_ribbons (uint8_t v) { return "6x8"; case RIBBON_6x9: return "6x9"; - // XXX 89x??? rubbons. + // XXX 89x??? ribbons. default: return "Unknown"; } } struct s6145_mediainfo_resp { - struct s6145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t ribbon; uint8_t reserved; uint8_t count; - struct s6145_mediainfo_item items[10]; /* Not all necessarily used */ -} __attribute__((packed)); - -struct s6145_error_item { - uint8_t major; - uint8_t minor; - uint32_t print_counter; -} __attribute__((packed)); - -struct s6145_errorlog_resp { - struct s6145_status_hdr hdr; - uint8_t count; - struct s6145_error_item items[10]; /* Not all necessarily used */ -} __attribute__((packed)); - -struct s6145_getparam_resp { - struct s6145_status_hdr hdr; - uint32_t param; -} __attribute__((packed)); - -struct s6145_getserial_resp { - struct s6145_status_hdr hdr; - uint8_t data[8]; -} __attribute__((packed)); - -struct s6145_getprintidstatus_resp { - struct s6145_status_hdr hdr; - uint8_t id; - uint16_t remaining; - uint16_t finished; - uint16_t specified; - uint16_t status; -} __attribute__((packed)); - -#define STATUS_WAITING 0x0000 -#define STATUS_PRINTING 0x0100 -#define STATUS_COMPLETED 0x0200 -#define STATUS_ERROR 0xFFFF - -struct s6145_getextcounter_resp { - struct s6145_status_hdr hdr; - uint32_t lifetime_distance; /* Inches */ - uint32_t maint_distance; - uint32_t head_distance; - uint8_t reserved[32]; -} __attribute__((packed)); - -struct s6145_fwinfo_resp { - struct s6145_status_hdr hdr; - uint8_t name[8]; - uint8_t type[16]; - uint8_t date[10]; - uint8_t major; - uint8_t minor; - uint16_t checksum; + struct sinfonia_mediainfo_item items[10]; /* Not all necessarily used */ } __attribute__((packed)); struct s6145_imagecorr_resp { - struct s6145_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint16_t total_size; } __attribute__((packed)); @@ -1080,20 +555,8 @@ struct s6145_imagecorr_data { } __attribute__((packed)); /* Private data structure */ -struct shinkos6145_printjob { - uint8_t *databuf; - size_t datalen; - - struct s6145_printjob_hdr hdr; - - int copies; -}; - struct shinkos6145_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; + struct sinfonia_usbdev dev; uint8_t jobid; @@ -1116,152 +579,106 @@ struct shinkos6145_ctx { static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx); static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx); -static int get_param(struct shinkos6145_ctx *ctx, int target, uint32_t *param); - -#define READBACK_LEN 512 /* Needs to be larger than largest response hdr */ -#define CMDBUF_LEN sizeof(struct s6145_print_cmd) - -uint8_t rdbuf[READBACK_LEN]; - -static int s6145_do_cmd(struct shinkos6145_ctx *ctx, - uint8_t *cmd, int cmdlen, - int minlen, int *num) -{ - int ret; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - - libusb_device_handle *dev = ctx->dev; - uint8_t endp_up = ctx->endp_up; - uint8_t endp_down = ctx->endp_down; - - if ((ret = send_data(dev, endp_down, - cmd, cmdlen))) - return (ret < 0) ? ret : -99; - - ret = read_data(dev, endp_up, - rdbuf, READBACK_LEN, num); - - if (ret < 0) - return ret; - if (*num < minlen) { - ERROR("Short read! (%d/%d))\n", *num, minlen); - return -99; - } - - if (resp->result != RESULT_SUCCESS) { - INFO("Printer Status: %02x (%s)\n", resp->status, - status_str(resp->status)); - INFO(" Result: 0x%02x Error: 0x%02x (0x%02x/0x%02x = %s)\n", - resp->result, resp->error, resp->printer_major, - resp->printer_minor, error_codes(resp->printer_major, resp->printer_minor)); - return -99; - } - - return ret; -} static int get_status(struct shinkos6145_ctx *ctx) { - struct s6145_cmd_hdr cmd; - struct s6145_status_resp *resp = (struct s6145_status_resp *) rdbuf; - struct s6145_getextcounter_resp *resp2 = (struct s6145_getextcounter_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s6145_status_resp resp; + struct sinfonia_getextcounter_resp resp2; int ret, num = 0; uint32_t val; - cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), &num)) < 0) { return ret; } - INFO("Printer Status: 0x%02x (%s)\n", resp->hdr.status, - status_str(resp->hdr.status)); - if (resp->hdr.status == ERROR_PRINTER) { - if(resp->hdr.error == ERROR_NONE) - resp->hdr.error = resp->hdr.status; + INFO("Printer Status: 0x%02x (%s)\n", resp.hdr.status, + sinfonia_status_str(resp.hdr.status)); + if (resp.hdr.status == ERROR_PRINTER) { + if(resp.hdr.error == ERROR_NONE) + resp.hdr.error = resp.hdr.status; INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", - resp->hdr.error, - error_str(resp->hdr.error), - resp->hdr.printer_major, - resp->hdr.printer_minor, error_codes(resp->hdr.printer_major, resp->hdr.printer_minor)); + resp.hdr.error, + sinfonia_error_str(resp.hdr.error), + resp.hdr.printer_major, + resp.hdr.printer_minor, error_codes(resp.hdr.printer_major, resp.hdr.printer_minor)); } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6145_status_resp) - sizeof(struct s6145_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6145_status_resp) - sizeof(struct sinfonia_status_hdr))) return -1; INFO(" Print Counts:\n"); - INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp->count_paper)); - INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp->count_lifetime)); - INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp->count_maint)); - INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp->count_head)); - INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp->count_cutter)); - INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp->count_ribbon_left)); + INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp.count_paper)); + INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp.count_lifetime)); + INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp.count_maint)); + INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp.count_head)); + INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp.count_cutter)); + INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp.count_ribbon_left)); INFO("Bank 1: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank1_status, bank_statuses(resp->bank1_status), - resp->bank1_printid, - le16_to_cpu(resp->bank1_finished), - le16_to_cpu(resp->bank1_specified), - le16_to_cpu(resp->bank1_remaining)); + resp.bank1_status, sinfonia_bank_statuses(resp.bank1_status), + resp.bank1_printid, + le16_to_cpu(resp.bank1_finished), + le16_to_cpu(resp.bank1_specified), + le16_to_cpu(resp.bank1_remaining)); INFO("Bank 2: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank2_status, bank_statuses(resp->bank1_status), - resp->bank2_printid, - le16_to_cpu(resp->bank2_finished), - le16_to_cpu(resp->bank2_specified), - le16_to_cpu(resp->bank2_remaining)); + resp.bank2_status, sinfonia_bank_statuses(resp.bank1_status), + resp.bank2_printid, + le16_to_cpu(resp.bank2_finished), + le16_to_cpu(resp.bank2_specified), + le16_to_cpu(resp.bank2_remaining)); - INFO("Tonecurve Status: 0x%02x (%s)\n", resp->tonecurve_status, tonecurve_statuses(resp->tonecurve_status)); + INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, sinfonia_tonecurve_statuses(resp.tonecurve_status)); /* Query Extended counters */ - cmd.cmd = cpu_to_le16(S6145_CMD_EXTCOUNTER); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_EXTCOUNTER); cmd.len = cpu_to_le16(0); - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp2), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp2, sizeof(resp2), + &num)) < 0) { return ret; } - if (le16_to_cpu(resp2->hdr.payload_len) != (sizeof(struct s6145_getextcounter_resp) - sizeof(struct s6145_status_hdr))) + if (le16_to_cpu(resp2.hdr.payload_len) != (sizeof(struct sinfonia_getextcounter_resp) - sizeof(struct sinfonia_status_hdr))) return -1; - INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2->lifetime_distance)); - INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2->maint_distance)); - INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2->head_distance)); + INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2.lifetime_distance)); + INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2.maint_distance)); + INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2.head_distance)); /* Query various params */ - if (ctx->type == P_SHINKO_S6145D) { - if ((ret = get_param(ctx, PARAM_REGION_CODE, &val))) { + if (ctx->dev.type == P_SHINKO_S6145D) { + if ((ret = sinfonia_getparam(&ctx->dev, PARAM_REGION_CODE, &val))) { ERROR("Failed to execute command\n"); return ret; } INFO("Region Code: %#x\n", val); } - if ((ret = get_param(ctx, PARAM_PAPER_PRESV, &val))) { + if ((ret = sinfonia_getparam(&ctx->dev, PARAM_PAPER_PRESV, &val))) { ERROR("Failed to execute command\n"); return ret; } INFO("Paper Preserve mode: %s\n", (val ? "On" : "Off")); - if ((ret = get_param(ctx, PARAM_DRIVER_MODE, &val))) { + if ((ret = sinfonia_getparam(&ctx->dev, PARAM_DRIVER_MODE, &val))) { ERROR("Failed to execute command\n"); return ret; } INFO("Driver mode: %s\n", (val ? "On" : "Off")); - if ((ret = get_param(ctx, PARAM_PAPER_MODE, &val))) { + if ((ret = sinfonia_getparam(&ctx->dev, PARAM_PAPER_MODE, &val))) { ERROR("Failed to execute command\n"); return ret; } INFO("Paper load mode: %s\n", (val ? "Cut" : "No Cut")); - if ((ret = get_param(ctx, PARAM_SLEEP_TIME, &val))) { + if ((ret = sinfonia_getparam(&ctx->dev, PARAM_SLEEP_TIME, &val))) { ERROR("Failed to execute command\n"); return ret; } @@ -1285,77 +702,6 @@ static int get_status(struct shinkos6145_ctx *ctx) return 0; } -static int get_fwinfo(struct shinkos6145_ctx *ctx) -{ - struct s6145_fwinfo_cmd cmd; - struct s6145_fwinfo_resp *resp = (struct s6145_fwinfo_resp *)rdbuf; - int num = 0; - int i; - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_FWINFO); - cmd.hdr.len = cpu_to_le16(1); - - INFO("FW Information:\n"); - - for (i = FWINFO_TARGET_MAIN_BOOT ; i <= FWINFO_TARGET_PRINT_TABLES ; i++) { - int ret; - cmd.target = i; - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); - continue; - } - - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6145_fwinfo_resp) - sizeof(struct s6145_status_hdr))) - continue; - - INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i), - resp->major, resp->minor); -#if 0 - INFO(" name: '%s'\n", resp->name); - INFO(" type: '%s'\n", resp->type); - INFO(" date: '%s'\n", resp->date); - INFO(" version: %02x.%02x (CRC %04x)\n", resp->major, resp->minor, - le16_to_cpu(resp->checksum)); -#endif - } - return 0; -} - -static int get_errorlog(struct shinkos6145_ctx *ctx) -{ - struct s6145_cmd_hdr cmd; - struct s6145_errorlog_resp *resp = (struct s6145_errorlog_resp *) rdbuf; - int ret, num = 0; - int i; - - cmd.cmd = cpu_to_le16(S6145_CMD_ERRORLOG); - cmd.len = cpu_to_le16(0); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); - return ret; - } - - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6145_errorlog_resp) - sizeof(struct s6145_status_hdr))) - return -2; - - INFO("Stored Error Events: %u entries:\n", resp->count); - for (i = 0 ; i < resp->count ; i++) { - INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i, - le32_to_cpu(resp->items[i].print_counter), - resp->items[i].major, resp->items[i].minor, - error_codes(resp->items[i].major, resp->items[i].minor)); - } - return 0; -} - static void dump_mediainfo(struct s6145_mediainfo_resp *resp) { int i; @@ -1364,126 +710,13 @@ static void dump_mediainfo(struct s6145_mediainfo_resp *resp) INFO("Supported Print Sizes: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { INFO(" %02d: C 0x%02x (%s), %04ux%04u, P 0x%02x (%s)\n", i, - resp->items[i].media_code, print_sizes(resp->items[i].media_code), - le16_to_cpu(resp->items[i].columns), - le16_to_cpu(resp->items[i].rows), - resp->items[i].print_method, print_methods(resp->items[i].print_method)); - } -} - -static int cancel_job(struct shinkos6145_ctx *ctx, char *str) -{ - struct s6145_cancel_cmd cmd; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - int ret, num = 0; - - if (!str) - return -1; - - cmd.id = atoi(str); - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_CANCELJOB); - cmd.hdr.len = cpu_to_le16(1); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; + resp->items[i].code, + sinfonia_print_codes(resp->items[i].code, 0), + resp->items[i].columns, + resp->items[i].rows, + resp->items[i].method, + sinfonia_print_methods(resp->items[i].method)); } - - return 0; -} - -static int flash_led(struct shinkos6145_ctx *ctx) -{ - struct s6145_cmd_hdr cmd; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - int ret, num = 0; - - cmd.cmd = cpu_to_le16(S6145_CMD_FLASHLED); - cmd.len = cpu_to_le16(0); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); - return ret; - } - - return 0; -} - - -static int set_param(struct shinkos6145_ctx *ctx, int target, uint32_t param) -{ - struct s6145_setparam_cmd cmd; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - int ret, num = 0; - - /* Set up command */ - cmd.target = target; - cmd.param = cpu_to_le32(param); - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_SETPARAM); - cmd.hdr.len = cpu_to_le16(sizeof(struct s6145_setparam_cmd)-sizeof(cmd.hdr)); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); - } - - return ret; -} - -static int get_param(struct shinkos6145_ctx *ctx, int target, uint32_t *param) -{ - struct s6145_getparam_cmd cmd; - struct s6145_getparam_resp *resp = (struct s6145_getparam_resp *) rdbuf; - int ret, num = 0; - - /* Set up command */ - cmd.target = target; - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_GETPARAM); - cmd.hdr.len = cpu_to_le16(sizeof(struct s6145_getparam_cmd)-sizeof(cmd.hdr)); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); - } - *param = le32_to_cpu(resp->param); - - return ret; -} - - -static int reset_curve(struct shinkos6145_ctx *ctx, int target) -{ - struct s6145_reset_cmd cmd; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - int ret, num = 0; - - cmd.target = target; - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_RESET); - cmd.hdr.len = cpu_to_le16(1); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - return 0; } static int shinkos6145_dump_corrdata(struct shinkos6145_ctx *ctx, char *fname) @@ -1504,7 +737,7 @@ static int shinkos6145_dump_corrdata(struct shinkos6145_ctx *ctx, char *fname) return fd; } - write(fd, ctx->corrdata, sizeof(struct shinkos6145_correctionparam)); + ret = write(fd, ctx->corrdata, sizeof(struct shinkos6145_correctionparam)); close(fd); } @@ -1534,7 +767,7 @@ static int shinkos6145_dump_eeprom(struct shinkos6145_ctx *ctx, char *fname) return fd; } - write(fd, ctx->eeprom, ctx->eepromlen); + ret = write(fd, ctx->eeprom, ctx->eepromlen); close(fd); } @@ -1546,152 +779,14 @@ static int shinkos6145_dump_eeprom(struct shinkos6145_ctx *ctx, char *fname) return ret; } -static int get_tonecurve(struct shinkos6145_ctx *ctx, int type, char *fname) -{ - struct s6145_readtone_cmd cmd; - struct s6145_readtone_resp *resp = (struct s6145_readtone_resp *) rdbuf; - int ret, num = 0; - - uint8_t *data; - uint16_t curves[UPDATE_SIZE] = { 0 }; - - int i,j; - - cmd.target = type; - cmd.curveid = TONE_CURVE_ID; - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_READTONE); - cmd.hdr.len = cpu_to_le16(1); - - INFO("Dump %s Tone Curve to '%s'\n", tonecurve_statuses(type), fname); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - resp->total_size = le16_to_cpu(resp->total_size); - - data = malloc(resp->total_size * 2); - if (!data) { - ERROR("Memory Allocation Failure!\n"); - return -1; - } - - i = 0; - while (i < resp->total_size) { - ret = read_data(ctx->dev, ctx->endp_up, - data + i, - resp->total_size * 2 - i, - &num); - if (ret < 0) - goto done; - i += num; - } - - i = j = 0; - while (i < resp->total_size) { - memcpy(curves + j, data + i+2, data[i+1]); - j += data[i+1] / 2; - i += data[i+1] + 2; - } - - /* Open file and write it out */ - { - int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); - if (tc_fd < 0) { - ret = -1; - goto done; - } - - for (i = 0 ; i < UPDATE_SIZE; i++) { - /* Byteswap appropriately */ - curves[i] = cpu_to_be16(le16_to_cpu(curves[i])); - } - write(tc_fd, curves, UPDATE_SIZE * sizeof(uint16_t)); - close(tc_fd); - } - -done: - free(data); - return ret; -} - -static int set_tonecurve(struct shinkos6145_ctx *ctx, int target, char *fname) -{ - struct s6145_update_cmd cmd; - struct s6145_status_hdr *resp = (struct s6145_status_hdr *) rdbuf; - int ret, num = 0; - - INFO("Set %s Tone Curve from '%s'\n", update_targets(target), fname); - - uint16_t *data = malloc(UPDATE_SIZE * sizeof(uint16_t)); - if (!data) { - ERROR("Memory Allocation Failure!\n"); - return -1; - } - - /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE * sizeof(uint16_t)) != (UPDATE_SIZE * sizeof(uint16_t))) { - ret = -2; - goto done; - } - close(tc_fd); - /* Byteswap data to local CPU.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { - data[ret] = be16_to_cpu(data[ret]); - } - - /* Set up command */ - cmd.target = target; - cmd.reserved[0] = cmd.reserved[1] = cmd.reserved[2] = 0; - cmd.reset = 0; - cmd.size = cpu_to_le32(UPDATE_SIZE * sizeof(uint16_t)); - - cmd.hdr.cmd = cpu_to_le16(S6145_CMD_UPDATE); - cmd.hdr.len = cpu_to_le16(sizeof(struct s6145_update_cmd)-sizeof(cmd.hdr)); - - /* Byteswap data to format printer is expecting.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { - data[ret] = cpu_to_le16(data[ret]); - } - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - goto done; - } - - /* Sent transfer */ - if ((ret = send_data(ctx->dev, ctx->endp_down, - (uint8_t *) data, UPDATE_SIZE * sizeof(uint16_t)))) { - goto done; - } - -done: - free(data); - - return ret; -} - static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx) { - struct s6145_cmd_hdr cmd; - struct s6145_imagecorr_resp *resp = (struct s6145_imagecorr_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s6145_imagecorr_resp resp; size_t total = 0; int ret, num; - cmd.cmd = cpu_to_le16(S6145_CMD_GETCORR); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETCORR); cmd.len = 0; if (ctx->corrdata) { @@ -1699,15 +794,14 @@ static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx) ctx->corrdata = NULL; } - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { goto done; } - ctx->corrdatalen = le16_to_cpu(resp->total_size); + ctx->corrdatalen = le16_to_cpu(resp.total_size); INFO("Fetching %zu bytes of image correction data\n", ctx->corrdatalen); ctx->corrdata = malloc(sizeof(struct shinkos6145_correctionparam)); @@ -1722,7 +816,7 @@ static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx) while (total < ctx->corrdatalen) { struct s6145_imagecorr_data data; - ret = read_data(ctx->dev, ctx->endp_up, (uint8_t *) &data, + ret = read_data(ctx->dev.dev, ctx->dev.endp_up, (uint8_t *) &data, sizeof(data), &num); if (ret < 0) @@ -1743,11 +837,11 @@ done: static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx) { - struct s6145_cmd_hdr cmd; - struct s6145_geteeprom_resp *resp = (struct s6145_geteeprom_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s6145_geteeprom_resp resp; int ret, num; - cmd.cmd = cpu_to_le16(S6145_CMD_GETEEPROM); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETEEPROM); cmd.len = 0; if (ctx->eeprom) { @@ -1755,22 +849,21 @@ static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx) ctx->eeprom = NULL; } - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { goto done; } - ctx->eepromlen = le16_to_cpu(resp->hdr.payload_len); + ctx->eepromlen = le16_to_cpu(resp.hdr.payload_len); ctx->eeprom = malloc(ctx->eepromlen); if (!ctx->eeprom) { ERROR("Memory allocation failure\n"); ret = -ENOMEM; goto done; } - memcpy(ctx->eeprom, resp->data, ctx->eepromlen); + memcpy(ctx->eeprom, resp.data, ctx->eepromlen); done: return ret; @@ -1803,26 +896,26 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv) if (!ctx) return -1; - while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mr:Q:q:R:sX:")) >= 0) { + while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mr:Q:q:rR:sX:")) >= 0) { switch(i) { GETOPT_PROCESS_GLOBAL case 'c': - j = get_tonecurve(ctx, TONECURVE_USER, optarg); + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_USER, optarg); break; case 'C': - j = set_tonecurve(ctx, TONECURVE_USER, optarg); + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_USER, optarg); break; case 'e': - j = get_errorlog(ctx); + j = sinfonia_geterrorlog(&ctx->dev); break; case 'F': - j = flash_led(ctx); + j = sinfonia_flashled(&ctx->dev); break; case 'i': - j = get_fwinfo(ctx); + j = sinfonia_getfwinfo(&ctx->dev); break; case 'k': { - uint32_t i = atoi(optarg); + i = atoi(optarg); if (i <= 5) i = 0; else if (i <= 15) @@ -1838,14 +931,14 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv) else i = 5; - j = set_param(ctx, PARAM_SLEEP_TIME, i); + j = sinfonia_setparam(&ctx->dev, PARAM_SLEEP_TIME, i); break; } case 'l': - j = get_tonecurve(ctx, TONECURVE_CURRENT, optarg); + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); break; case 'L': - j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg); + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); break; case 'm': dump_mediainfo(&ctx->media); @@ -1857,16 +950,16 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv) j = shinkos6145_dump_corrdata(ctx, optarg); break; case 'r': - j = reset_curve(ctx, RESET_TONE_CURVE); + j = sinfonia_resetcurve(&ctx->dev, RESET_TONE_CURVE, TONE_CURVE_ID); break; case 'R': - j = reset_curve(ctx, RESET_PRINTER); + j = sinfonia_resetcurve(&ctx->dev, RESET_PRINTER, 0); break; case 's': j = get_status(ctx); break; case 'X': - j = cancel_job(ctx, optarg); + j = sinfonia_canceljob(&ctx->dev, atoi(optarg)); break; default: break; /* Ignore completely */ @@ -1897,10 +990,11 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, int { struct shinkos6145_ctx *ctx = vctx; - ctx->dev = dev; - ctx->endp_up = endp_up; - ctx->endp_down = endp_down; - ctx->type = type; + ctx->dev.dev = dev; + ctx->dev.endp_up = endp_up; + ctx->dev.endp_down = endp_down; + ctx->dev.type = type; + ctx->dev.error_codes = &error_codes; /* Attempt to open the library */ #if defined(WITH_DYNAMIC) @@ -1926,22 +1020,31 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, int #endif /* Ensure jobid is sane */ - ctx->jobid = (jobid & 0x7f) + 1; + ctx->jobid = (jobid & 0x7f); + if (!ctx->jobid) + ctx->jobid++; if (test_mode < TEST_MODE_NOATTACH) { /* Query Media */ - struct s6145_mediainfo_resp *resp = (struct s6145_mediainfo_resp *) rdbuf; - struct s6145_cmd_hdr cmd; + struct sinfonia_cmd_hdr cmd; int num; - if (s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_MEDIAINFO); + cmd.len = cpu_to_le16(0); + + if (sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&ctx->media, sizeof(ctx->media), + &num)) { return CUPS_BACKEND_FAILED; } - memcpy(&ctx->media, resp, sizeof(*resp)); + + /* Byteswap media descriptor.. */ + int i; + for (i = 0 ; i < ctx->media.count ; i++) { + ctx->media.items[i].columns = le16_to_cpu(ctx->media.items[i].columns); + ctx->media.items[i].rows = le16_to_cpu(ctx->media.items[i].rows); + } } else { int media_code = RIBBON_6x8; if (getenv("MEDIA_CODE")) @@ -1958,16 +1061,6 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, int return CUPS_BACKEND_OK; } -static void shinkos6145_cleanup_job(const void *vjob) -{ - const struct shinkos6145_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - static void shinkos6145_teardown(void *vctx) { struct shinkos6145_ctx *ctx = vctx; @@ -1987,7 +1080,7 @@ static void shinkos6145_teardown(void *vctx) { } static void lib6145_calc_avg(struct shinkos6145_ctx *ctx, - const struct shinkos6145_printjob *job, + const struct sinfonia_printjob *job, uint16_t rows, uint16_t cols) { uint32_t plane, i, planelen; @@ -2080,131 +1173,58 @@ static void lib6145_process_image(uint8_t *src, uint16_t *dest, static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct shinkos6145_ctx *ctx = vctx; + struct sinfonia_printjob *job = NULL; int ret; - uint8_t tmpbuf[4]; + int model; uint8_t input_ymc; - struct shinkos6145_printjob *job = NULL; - if (!ctx) return CUPS_BACKEND_FAILED; + if (ctx->dev.type == P_SHINKO_S6145 || + ctx->dev.type == P_SHINKO_S6145D) + model = 6145; + else + model = 2245; + job = malloc(sizeof(*job)); if (!job) { ERROR("Memory allocation failure!\n"); return CUPS_BACKEND_RETRY_CURRENT; } memset(job, 0, sizeof(*job)); - job->copies = copies; // XXX hdr.copies? - - /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - shinkos6145_cleanup_job(job); - if (ret == 0) - return CUPS_BACKEND_CANCEL; - ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); - perror("ERROR: Read failed"); - return ret; - } -#define SWAP_HDR(__x) job->hdr.__x = le32_to_cpu(job->hdr.__x) - - SWAP_HDR(len1); - SWAP_HDR(model); - SWAP_HDR(media_w); - SWAP_HDR(len2); - SWAP_HDR(media); - SWAP_HDR(method); - SWAP_HDR(qual); - SWAP_HDR(oc_mode); - SWAP_HDR(columns); - SWAP_HDR(rows); - SWAP_HDR(copies); - SWAP_HDR(dpi); - SWAP_HDR(ext_flags); - -#undef SWAP_HDR - - if (job->hdr.len1 != 0x10 || - job->hdr.len2 != 0x64 || - job->hdr.dpi != 300) { - ERROR("Unrecognized header data format!\n"); - shinkos6145_cleanup_job(job); - return CUPS_BACKEND_CANCEL; + /* Common read/parse code */ + if (ctx->dev.type == P_KODAK_6900) { + ret = sinfonia_raw28_read_parse(data_fd, job); + } else { + ret = sinfonia_read_parse(data_fd, model, job); } - - if (job->hdr.model != 6145) { - ERROR("Unrecognized printer (%u)!\n", job->hdr.model); - shinkos6145_cleanup_job(job); - return CUPS_BACKEND_CANCEL; + if (ret) { + free(job); + return ret; } - if (!job->hdr.rows || !job->hdr.columns) { - ERROR("Bad print job header!\n"); - shinkos6145_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } + if (job->jp.copies > 1) + job->copies = job->jp.copies; + else + job->copies = copies; /* Extended spool format to re-purpose an unused header field. When bit 0 is set, this tells the backend that the data is already in planar YMC format (vs packed RGB) so we don't need to do the conversion ourselves. Saves some processing overhead */ - input_ymc = job->hdr.ext_flags & 0x01; - - job->datalen = job->hdr.rows * job->hdr.columns * 3; - job->databuf = malloc(job->datalen); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - shinkos6145_cleanup_job(job); - return CUPS_BACKEND_RETRY_CURRENT; - } - - { - int remain = job->datalen; - uint8_t *ptr = job->databuf; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%zu)\n", - ret, remain, job->datalen); - perror("ERROR: Read failed"); - shinkos6145_cleanup_job(job); - return ret; - } - ptr += ret; - remain -= ret; - } while (remain); - } - - /* Make sure footer is sane too */ - ret = read(data_fd, tmpbuf, 4); - if (ret != 4) { - ERROR("Read failed (%d/%d/%d)\n", - ret, 4, 4); - perror("ERROR: Read failed"); - shinkos6145_cleanup_job(job); - return ret; - } - if (tmpbuf[0] != 0x04 || - tmpbuf[1] != 0x03 || - tmpbuf[2] != 0x02 || - tmpbuf[3] != 0x01) { - ERROR("Unrecognized footer data format!\n"); - shinkos6145_cleanup_job(job); - return CUPS_BACKEND_FAILED; - } + input_ymc = job->jp.ext_flags & 0x01; /* Convert packed RGB to planar YMC if necessary */ if (!input_ymc) { INFO("Converting Packed RGB to Planar YMC\n"); - int planelen = job->hdr.columns * job->hdr.rows; + int planelen = job->jp.columns * job->jp.rows; uint8_t *databuf3 = malloc(job->datalen); int i; if (!databuf3) { ERROR("Memory allocation failure!\n"); - shinkos6145_cleanup_job(job); + sinfonia_cleanup_job(job); return CUPS_BACKEND_RETRY_CURRENT; } for (i = 0 ; i < planelen ; i++) { @@ -2234,49 +1254,29 @@ static int shinkos6145_main_loop(void *vctx, const void *vjob) { struct shinkos6145_ctx *ctx = vctx; int ret, num; - uint8_t cmdbuf[CMDBUF_LEN]; - uint8_t rdbuf2[READBACK_LEN]; int i, last_state = -1, state = S_IDLE; - struct s6145_cmd_hdr *cmd = (struct s6145_cmd_hdr *) cmdbuf; - struct s6145_print_cmd *print = (struct s6145_print_cmd *) cmdbuf; - struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf; - struct s6145_mediainfo_resp *media = (struct s6145_mediainfo_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s6145_status_resp sts, sts2; uint32_t cur_mode; - struct shinkos6145_printjob *job = (struct shinkos6145_printjob*) vjob; /* XXX stupid, we can't do this. */ + struct sinfonia_printjob *job = (struct sinfonia_printjob*) vjob; /* XXX stupid, we can't do this. */ if (!job) return CUPS_BACKEND_FAILED; - /* Send Media Query */ - memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S6145_CMD_MEDIAINFO); - cmd->len = cpu_to_le16(0); - - if ((ret = s6145_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(*media), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd)); - return CUPS_BACKEND_FAILED; - } - - if (le16_to_cpu(media->hdr.payload_len) != (sizeof(struct s6145_mediainfo_resp) - sizeof(struct s6145_status_hdr))) - return CUPS_BACKEND_FAILED; - /* Validate print sizes */ - for (i = 0; i < media->count ; i++) { + for (i = 0; i < ctx->media.count ; i++) { /* Look for matching media */ - if (le16_to_cpu(media->items[i].columns) == job->hdr.columns && - le16_to_cpu(media->items[i].rows) == job->hdr.rows && - media->items[i].print_method == job->hdr.method && - media->items[i].media_code == job->hdr.media) + if (ctx->media.items[i].columns == job->jp.columns && + ctx->media.items[i].rows == job->jp.rows && + ctx->media.items[i].method == job->jp.method && + ctx->media.items[i].code == job->jp.media) break; } - if (i == media->count) { + if (i == ctx->media.count) { ERROR("Incorrect media loaded for print!\n"); return CUPS_BACKEND_HOLD; } @@ -2284,7 +1284,7 @@ static int shinkos6145_main_loop(void *vctx, const void *vjob) { // XXX check copies against remaining media? /* Query printer mode */ - ret = get_param(ctx, PARAM_OC_PRINT, &cur_mode); + ret = sinfonia_getparam(&ctx->dev, PARAM_OC_PRINT, &cur_mode); if (ret) { ERROR("Failed to execute command\n"); return ret; @@ -2297,32 +1297,30 @@ top: } /* Send Status Query */ - memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S6145_CMD_GETSTATUS); - cmd->len = cpu_to_le16(0); - - if ((ret = s6145_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(struct s6145_status_hdr), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd)); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); + + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&sts, sizeof(sts), + &num)) < 0) { return CUPS_BACKEND_FAILED; } - if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) { - memcpy(rdbuf2, rdbuf, READBACK_LEN); + if (memcmp(&sts, &sts2, sizeof(sts))) { + memcpy(&sts2, &sts, sizeof(sts)); INFO("Printer Status: 0x%02x (%s)\n", - sts->hdr.status, status_str(sts->hdr.status)); + sts.hdr.status, sinfonia_status_str(sts.hdr.status)); - if (ctx->marker.levelnow != (int)sts->count_ribbon_left) { - ctx->marker.levelnow = sts->count_ribbon_left; + if (ctx->marker.levelnow != (int)sts.count_ribbon_left) { + ctx->marker.levelnow = sts.count_ribbon_left; dump_markers(&ctx->marker, 1, 0); } - if (sts->hdr.result != RESULT_SUCCESS) + if (sts.hdr.result != RESULT_SUCCESS) goto printer_error; - if (sts->hdr.status == ERROR_PRINTER) + if (sts.hdr.status == ERROR_PRINTER) goto printer_error; } else if (state == last_state) { sleep(1); @@ -2336,15 +1334,15 @@ top: case S_IDLE: INFO("Waiting for printer idle\n"); /* If either bank is free, continue */ - if (sts->bank1_status == BANK_STATUS_FREE || - sts->bank2_status == BANK_STATUS_FREE) + if (sts.bank1_status == BANK_STATUS_FREE || + sts.bank2_status == BANK_STATUS_FREE) state = S_PRINTER_READY_CMD; break; case S_PRINTER_READY_CMD: { /* Set matte/etc */ - uint32_t oc_mode = job->hdr.oc_mode; + uint32_t oc_mode = job->jp.oc_mode; uint32_t updated = 0; if (!oc_mode) /* if nothing set, default to glossy */ @@ -2354,13 +1352,13 @@ top: /* If cur_mode is not the same as desired oc_mode, change it -- but we have to wait until the printer is COMPLETELY idle */ - if (sts->bank1_status != BANK_STATUS_FREE || - sts->bank2_status != BANK_STATUS_FREE) { + if (sts.bank1_status != BANK_STATUS_FREE || + sts.bank2_status != BANK_STATUS_FREE) { INFO("Need to switch overcoat mode, waiting for printer idle\n"); sleep(1); goto top; } - ret = set_param(ctx, PARAM_OC_PRINT, oc_mode); + ret = sinfonia_setparam(&ctx->dev, PARAM_OC_PRINT, oc_mode); if (ret) { ERROR("Failed to execute command\n"); return ret; @@ -2385,19 +1383,19 @@ top: /* Set up library transform... */ uint32_t newlen = le16_to_cpu(ctx->corrdata->headDots) * - job->hdr.rows * sizeof(uint16_t) * 4; + job->jp.rows * sizeof(uint16_t) * 4; uint16_t *databuf2 = malloc(newlen); /* Set the size in the correctiondata */ - ctx->corrdata->width = cpu_to_le16(job->hdr.columns); - ctx->corrdata->height = cpu_to_le16(job->hdr.rows); + ctx->corrdata->width = cpu_to_le16(job->jp.columns); + ctx->corrdata->height = cpu_to_le16(job->jp.rows); /* Perform the actual library transform */ if (ctx->dl_handle) { INFO("Calling image processing library...\n"); - if (ctx->ImageAvrCalc(job->databuf, job->hdr.columns, job->hdr.rows, ctx->image_avg)) { + if (ctx->ImageAvrCalc(job->databuf, job->jp.columns, job->jp.rows, ctx->image_avg)) { free(databuf2); ERROR("Library returned error!\n"); return CUPS_BACKEND_FAILED; @@ -2407,7 +1405,7 @@ top: WARNING("Utilizing fallback internal image processing code\n"); WARNING(" *** Output quality will be poor! *** \n"); - lib6145_calc_avg(ctx, job, job->hdr.columns, job->hdr.rows); + lib6145_calc_avg(ctx, job, job->jp.columns, job->jp.rows); lib6145_process_image(job->databuf, databuf2, ctx->corrdata, oc_mode); } @@ -2415,49 +1413,50 @@ top: job->databuf = (uint8_t*) databuf2; job->datalen = newlen; + struct s6145_print_cmd print; + INFO("Sending print job (internal id %u)\n", ctx->jobid); - memset(cmdbuf, 0, CMDBUF_LEN); - print->hdr.cmd = cpu_to_le16(S6145_CMD_PRINTJOB); - print->hdr.len = cpu_to_le16(sizeof (*print) - sizeof(*cmd)); + memset(&print, 0, sizeof(print)); + print.hdr.cmd = cpu_to_le16(SINFONIA_CMD_PRINTJOB); + print.hdr.len = cpu_to_le16(sizeof (print) - sizeof(cmd)); - print->id = ctx->jobid; - print->count = cpu_to_le16(job->copies); - print->columns = cpu_to_le16(job->hdr.columns); - print->rows = cpu_to_le16(job->hdr.rows); - print->image_avg = ctx->image_avg[2]; /* Cyan level */ - print->method = cpu_to_le32(job->hdr.method); - print->combo_wait = 0; + print.id = ctx->jobid; + print.count = cpu_to_le16(job->copies); + print.columns = cpu_to_le16(job->jp.columns); + print.rows = cpu_to_le16(job->jp.rows); + print.image_avg = ctx->image_avg[2]; /* Cyan level */ + print.method = cpu_to_le32(job->jp.method); + print.combo_wait = 0; /* Brava21 header has a few quirks */ - if(ctx->type == P_SHINKO_S6145D) { - print->media = job->hdr.media; - print->unk_1 = 0x01; + if(ctx->dev.type == P_SHINKO_S6145D) { + print.media = job->jp.media; + print.unk_1 = 0x01; } - if ((ret = s6145_do_cmd(ctx, - cmdbuf, sizeof(*print), - sizeof(struct s6145_status_hdr), - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&print, sizeof(print), + (uint8_t*)&sts, sizeof(sts), + &num)) < 0) { return ret; } - if (sts->hdr.result != RESULT_SUCCESS) { - if (sts->hdr.error == ERROR_BUFFER_FULL) { + if (sts.hdr.result != RESULT_SUCCESS) { + if (sts.hdr.error == ERROR_BUFFER_FULL) { INFO("Printer Buffers full, retrying\n"); break; - } else if ((sts->hdr.status & 0xf0) == 0x30 || sts->hdr.status == 0x21) { - INFO("Printer busy (%s), retrying\n", status_str(sts->hdr.status)); + } else if ((sts.hdr.status & 0xf0) == 0x30 || sts.hdr.status == 0x21) { + INFO("Printer busy (%s), retrying\n", sinfonia_status_str(sts.hdr.status)); break; - } else if (sts->hdr.status != ERROR_NONE) + } else if (sts.hdr.status != ERROR_NONE) goto printer_error; } INFO("Sending image data to printer\n"); // XXX we shouldn't send the lamination layer over if // it's not needed. hdr->oc_mode == PRINT_MODE_NO_OC - if ((ret = send_data(ctx->dev, ctx->endp_down, + if ((ret = send_data(ctx->dev.dev, ctx->dev.endp_down, job->databuf, job->datalen))) return CUPS_BACKEND_FAILED; @@ -2470,7 +1469,7 @@ top: if (fast_return) { INFO("Fast return mode enabled.\n"); state = S_FINISHED; - } else if (sts->hdr.status == STATUS_READY) { + } else if (sts.hdr.status == STATUS_READY) { state = S_FINISHED; } break; @@ -2487,45 +1486,41 @@ top: printer_error: ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n", - sts->hdr.error, - error_str(sts->hdr.error), - sts->hdr.status, - status_str(sts->hdr.status), - sts->hdr.printer_major, sts->hdr.printer_minor, - error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + sts.hdr.error, + sinfonia_error_str(sts.hdr.error), + sts.hdr.status, + sinfonia_status_str(sts.hdr.status), + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); return CUPS_BACKEND_FAILED; } static int shinkos6145_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len) { - struct s6145_cmd_hdr cmd; - struct s6145_getserial_resp *resp = (struct s6145_getserial_resp*) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct sinfonia_getserial_resp resp; int ret, num = 0; - struct shinkos6145_ctx ctx = { + struct sinfonia_usbdev sdev = { .dev = dev, .endp_up = endp_up, .endp_down = endp_down, }; - cmd.cmd = cpu_to_le16(S6145_CMD_GETSERIAL); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSERIAL); cmd.len = cpu_to_le16(0); - if ((ret = s6145_do_cmd(&ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp) - 1, - &num)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&sdev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return ret; } - /* Null-terminate */ - resp->hdr.payload_len = le16_to_cpu(resp->hdr.payload_len); - if (resp->hdr.payload_len > 23) - resp->hdr.payload_len = 23; - resp->data[resp->hdr.payload_len] = 0; - strncpy(buf, (char*)resp->data, buf_len); - buf[buf_len-1] = 0; /* ensure it's null terminated */ + /* Copy and Null-terminate */ + num = (buf_len > (int)sizeof(resp.data)) ? (int)sizeof(resp.data) : (buf_len - 1); + memcpy(buf, resp.data, num); + buf[num] = 0; return CUPS_BACKEND_OK; } @@ -2533,23 +1528,22 @@ static int shinkos6145_query_serno(struct libusb_device_handle *dev, uint8_t end static int shinkos6145_query_markers(void *vctx, struct marker **markers, int *count) { struct shinkos6145_ctx *ctx = vctx; - struct s6145_cmd_hdr cmd; - struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf; + struct sinfonia_cmd_hdr cmd; + struct s6145_status_resp sts; int num; /* Query Status */ - cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if (s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*sts), - &num)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if (sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&sts, sizeof(sts), + &num)) { return CUPS_BACKEND_FAILED; } - ctx->marker.levelnow = le32_to_cpu(sts->count_ribbon_left); + ctx->marker.levelnow = le32_to_cpu(sts.count_ribbon_left); *markers = &ctx->marker; *count = 1; @@ -2561,9 +1555,15 @@ static int shinkos6145_query_markers(void *vctx, struct marker **markers, int *c #define USB_VID_SHINKO 0x10CE #define USB_PID_SHINKO_S6145 0x0019 #define USB_PID_SHINKO_S6145D 0x001E /* Aka CIAAT Brava 21 */ +#define USB_PID_SHINKO_S2245 0x0039 +#define USB_VID_KODAK 0x040a +//#define USB_PID_KODAK_6900 0xXXXX /* Aka S2245-6A */ +#define USB_VID_HITI 0x0D16 +#define USB_PID_HITI_M610 0x0010 static const char *shinkos6145_prefixes[] = { "sinfonia-chcs6145", "ciaat-brava-21", + "sinfonia-chcs2245", "hiti-m610", // "kodak-6900", // extras "shinko-chcs6145", // backwards-compatiblity @@ -2572,15 +1572,15 @@ static const char *shinkos6145_prefixes[] = { }; struct dyesub_backend shinkos6145_backend = { - .name = "Shinko/Sinfonia CHC-S6145/CS2", - .version = "0.30", + .name = "Shinko/Sinfonia CHC-S6145/CS2/S2245/S3", + .version = "0.40" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = shinkos6145_prefixes, .cmdline_usage = shinkos6145_cmdline, .cmdline_arg = shinkos6145_cmdline_arg, .init = shinkos6145_init, .attach = shinkos6145_attach, .teardown = shinkos6145_teardown, - .cleanup_job = shinkos6145_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = shinkos6145_read_parse, .main_loop = shinkos6145_main_loop, .query_serno = shinkos6145_query_serno, @@ -2588,6 +1588,9 @@ struct dyesub_backend shinkos6145_backend = { .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S6145, P_SHINKO_S6145, NULL, "sinfonia-chcs6145"}, { USB_VID_SHINKO, USB_PID_SHINKO_S6145D, P_SHINKO_S6145D, NULL, "ciaat-brava-21"}, + { USB_VID_SHINKO, USB_PID_SHINKO_S2245, P_SHINKO_S2245, NULL, "sinfonia-chcs2245"}, +// { USB_VID_KODAK, USB_PID_KODAK_6900, P_SHINKO_S2245, NULL, "sinfonia-chcs6145"}, + { USB_VID_HITI, USB_PID_HITI_M610, P_SHINKO_S2245, NULL, "hiti-m610"}, { 0, 0, 0, NULL, NULL} } }; diff --git a/src/cups/backend_shinkos6245.c b/src/cups/backend_shinkos6245.c index 5d75e0d..0fd1af0 100644 --- a/src/cups/backend_shinkos6245.c +++ b/src/cups/backend_shinkos6245.c @@ -1,7 +1,7 @@ /* * Shinko/Sinfonia CHC-S6245 CUPS backend -- libusb-1.0 version * - * (c) 2015-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2015-2019 Solomon Peachy <pizza@shaftnet.org> * * Low-level documentation was provided by Sinfonia, Inc. Thank you! * @@ -42,7 +42,7 @@ #define BACKEND shinkos6245_backend #include "backend_common.h" - +#include "backend_sinfonia.h" enum { S_IDLE = 0, @@ -51,198 +51,21 @@ enum { S_FINISHED, }; -/* Structure of printjob header. All fields are LITTLE ENDIAN */ -struct s6245_printjob_hdr { - uint32_t len1; /* Fixed at 0x10 */ - uint32_t model; /* Equal to the printer model (eg '6245' or '1245' decimal) */ - uint32_t unk2; - uint32_t unk3; /* Fixed at 0x01 */ - - uint32_t len2; /* Fixed at 0x64 */ - uint32_t unk5; - uint32_t media; // 8x4->8x12 - uint32_t unk6; - - uint32_t unk7; - uint32_t unk7a; - uint32_t oc_mode; /* 6145/6245 only, Matte/Glossy/None */ - uint32_t unk8; - - uint32_t unk9; - uint32_t columns; - uint32_t rows; - uint32_t copies; - - uint32_t unk10; - uint32_t unk11; - uint32_t unk12; - uint32_t unk13; - - uint32_t unk14; - uint32_t unk15; - uint32_t dpi; /* Fixed at '300' (decimal) */ - uint32_t unk16; - - uint32_t unk17; - uint32_t unk18; - uint32_t unk19; - uint32_t unk20; - - uint32_t unk21; -} __attribute__((packed)); - /* Structs for printer */ -struct s6245_cmd_hdr { - uint16_t cmd; - uint16_t len; /* Not including this header */ -} __attribute__((packed)); - -#define S6245_CMD_GETSTATUS 0x0001 -#define S6245_CMD_MEDIAINFO 0x0002 -#define S6245_CMD_ERRORLOG 0x0004 -#define S6245_CMD_GETPARAM 0x0005 -#define S6245_CMD_GETSERIAL 0x0006 -#define S6245_CMD_PRINTSTAT 0x0007 -#define S6245_CMD_EXTCOUNTER 0x0008 - -#define S6245_CMD_PRINTJOB 0x4001 -#define S6245_CMD_CANCELJOB 0x4002 -#define S6245_CMD_FLASHLED 0x4003 -#define S6245_CMD_RESET 0x4004 -#define S6245_CMD_READTONE 0x4005 -#define S6245_CMD_SETPARAM 0x4007 - -#define S6245_CMD_GETEEPROM 0x400E -#define S6245_CMD_SETEEPROM 0x400F -#define S6245_CMD_SETTIME 0x4011 - -#define S6245_CMD_FWINFO 0xC003 -#define S6245_CMD_UPDATE 0xC004 - -static char *cmd_names(uint16_t v) { - switch (le16_to_cpu(v)) { - case S6245_CMD_GETSTATUS: - return "Get Status"; - case S6245_CMD_MEDIAINFO: - return "Get Media Info"; - case S6245_CMD_ERRORLOG: - return "Get Error Log"; - case S6245_CMD_GETPARAM: - return "Get Parameter"; - case S6245_CMD_GETSERIAL: - return "Get Serial Number"; - case S6245_CMD_PRINTSTAT: - return "Get Print ID Status"; - case S6245_CMD_EXTCOUNTER: - return "Get Extended Counters"; - case S6245_CMD_PRINTJOB: - return "Print"; - case S6245_CMD_CANCELJOB: - return "Cancel Print"; - case S6245_CMD_FLASHLED: - return "Flash LEDs"; - case S6245_CMD_RESET: - return "Reset"; - case S6245_CMD_READTONE: - return "Read Tone Curve"; - case S6245_CMD_SETPARAM: - return "Set Parameter"; - case S6245_CMD_GETEEPROM: - return "Get EEPROM Backup Parameter"; - case S6245_CMD_SETEEPROM: - return "Set EEPROM Backup Parameter"; - case S6245_CMD_SETTIME: - return "Time Setting"; - case S6245_CMD_FWINFO: - return "Get Firmware Info"; - case S6245_CMD_UPDATE: - return "Update"; - default: - return "Unknown Command"; - } -} - struct s6245_print_cmd { - struct s6245_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t id; uint16_t count; uint16_t columns; uint16_t rows; - uint8_t reserved[8]; // columns and rows repeated, then nulls + uint16_t columns2; /* These are necessary for EK8810 */ + uint16_t rows2; /* */ + uint8_t reserved[4]; uint8_t mode; uint8_t method; uint8_t reserved2; } __attribute__((packed)); -#define PRINT_MODE_NO_OC 0x01 -#define PRINT_MODE_GLOSSY 0x02 -#define PRINT_MODE_MATTE 0x03 - -#if 0 -static char *print_modes(uint8_t v) { - switch (v) { - case PRINT_MODE_NO_OC: - return "No Overcoat"; - case PRINT_MODE_GLOSSY: - return "Glossy"; - case PRINT_MODE_MATTE: - return "Matte"; - default: - return "Unknown"; - } -} -#endif - -#define PRINT_METHOD_STD 0x00 -#define PRINT_METHOD_COMBO_2 0x02 -#define PRINT_METHOD_COMBO_3 0x03 - -#define PRINT_METHOD_DISABLE_ERR 0x10 - -static char *print_methods (uint8_t v) { - switch (v & 0xf) { - case PRINT_METHOD_STD: - return "Standard"; - case PRINT_METHOD_COMBO_2: - return "2up"; - case PRINT_METHOD_COMBO_3: - return "3up"; - default: - return "Unknown"; - } -} - -struct s6245_cancel_cmd { - struct s6245_cmd_hdr hdr; - uint8_t id; -} __attribute__((packed)); - -struct s6245_reset_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; - uint8_t curveid; -} __attribute__((packed)); - -#define RESET_PRINTER 0x03 -#define RESET_TONE_CURVE 0x04 - -#define TONE_CURVE_ID 0x01 - -struct s6245_readtone_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; - uint8_t curveid; -} __attribute__((packed)); - -#define READ_TONE_CURVE_USER 0x01 -#define READ_TONE_CURVE_CURR 0x02 - -struct s6245_setparam_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; - uint32_t param; -} __attribute__((packed)); - #define PARAM_DRIVER_MODE 0x3e #define PARAM_PAPER_MODE 0x3f #define PARAM_SLEEP_TIME 0x54 @@ -260,13 +83,8 @@ struct s6245_setparam_cmd { #define PARAM_SLEEP_120MIN 0x00000004 #define PARAM_SLEEP_240MIN 0x00000005 -struct s6245_seteeprom_cmd { - struct s6245_cmd_hdr hdr; - uint8_t data[256]; /* Maxlen */ -} __attribute__((packed)); - struct s6245_settime_cmd { - struct s6245_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint8_t enable; /* 0 or 1 */ uint8_t second; uint8_t minute; @@ -277,98 +95,11 @@ struct s6245_settime_cmd { } __attribute__((packed)); struct s6245_errorlog_cmd { - struct s6245_cmd_hdr hdr; + struct sinfonia_cmd_hdr hdr; uint16_t index; /* 0 is latest */ } __attribute__((packed)); -struct s6245_getparam_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; -} __attribute__((packed)); - -struct s6245_getprintidstatus_cmd { - struct s6245_cmd_hdr hdr; - uint8_t id; -} __attribute__((packed)); - -struct s6245_fwinfo_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; -} __attribute__((packed)); - -#define FWINFO_TARGET_MAIN_BOOT 0x01 -#define FWINFO_TARGET_MAIN_APP 0x02 -#define FWINFO_TARGET_PRINT_TABLES 0x03 -#define FWINFO_TARGET_DSP 0x04 - -static char *fwinfo_targets (uint8_t v) { - switch (v) { - case FWINFO_TARGET_MAIN_BOOT: - return "Main Boot "; - case FWINFO_TARGET_MAIN_APP: - return "Main App "; - case FWINFO_TARGET_DSP: - return "DSP "; - case FWINFO_TARGET_PRINT_TABLES: - return "Print Tables"; - default: - return "Unknown "; - } -} - -struct s6245_update_cmd { - struct s6245_cmd_hdr hdr; - uint8_t target; - uint8_t curve_id; - uint8_t reset; // ?? - uint8_t reserved[3]; - uint32_t size; -} __attribute__((packed)); - -#define UPDATE_TARGET_USER 0x03 -#define UPDATE_TARGET_CURRENT 0x04 - -static char *update_targets (uint8_t v) { - switch (v) { - case UPDATE_TARGET_USER: - return "User"; - case UPDATE_TARGET_CURRENT: - return "Current"; - default: - return "Unknown"; - } -} - -#define UPDATE_SIZE 0x600 -/* Update is three channels, Y, M, C; - each is 256 entries of 11-bit data padded to 16-bits. - Printer expects LE data. We use BE data on disk. -*/ - -struct s6245_status_hdr { - uint8_t result; - uint8_t error; - uint8_t printer_major; - uint8_t printer_minor; - uint8_t reserved[2]; - uint8_t mode; - uint8_t status; - uint16_t payload_len; -} __attribute__((packed)); - -#define RESULT_SUCCESS 0x01 -#define RESULT_FAIL 0x02 - -#define ERROR_NONE 0x00 -#define ERROR_INVALID_PARAM 0x01 -#define ERROR_MAIN_APP_INACTIVE 0x02 -#define ERROR_COMMS_TIMEOUT 0x03 -#define ERROR_MAINT_NEEDED 0x04 -#define ERROR_BAD_COMMAND 0x05 -#define ERROR_PRINTER 0x11 -#define ERROR_BUFFER_FULL 0x21 - -static char *error_codes(uint8_t major, uint8_t minor) +static const char *error_codes(uint8_t major, uint8_t minor) { switch(major) { case 0x01: /* "Controller Error" */ @@ -583,102 +314,8 @@ static char *error_codes(uint8_t major, uint8_t minor) } } -static char *error_str(uint8_t v) { - switch (v) { - case ERROR_NONE: - return "None"; - case ERROR_INVALID_PARAM: - return "Invalid Command Parameter"; - case ERROR_MAIN_APP_INACTIVE: - return "Main App Inactive"; - case ERROR_COMMS_TIMEOUT: - return "Main Communication Timeout"; - case ERROR_MAINT_NEEDED: - return "Maintenance Needed"; - case ERROR_BAD_COMMAND: - return "Inappropriate Command"; - case ERROR_PRINTER: - return "Printer Error"; - case ERROR_BUFFER_FULL: - return "Buffer Full"; - default: - return "Unknown"; - } -} - -#define STATUS_READY 0x00 -#define STATUS_INIT_CPU 0x31 -#define STATUS_INIT_RIBBON 0x32 -#define STATUS_INIT_PAPER 0x33 -#define STATUS_THERMAL_PROTECT 0x34 -#define STATUS_USING_PANEL 0x35 -#define STATUS_SELF_DIAG 0x36 -#define STATUS_DOWNLOADING 0x37 - -#define STATUS_FEEDING_PAPER 0x61 -#define STATUS_PRE_HEAT 0x62 -#define STATUS_PRINT_Y 0x63 -#define STATUS_BACK_FEED_Y 0x64 -#define STATUS_PRINT_M 0x65 -#define STATUS_BACK_FEED_M 0x66 -#define STATUS_PRINT_C 0x67 -#define STATUS_BACK_FEED_C 0x68 -#define STATUS_PRINT_OP 0x69 -#define STATUS_PAPER_CUT 0x6A -#define STATUS_PAPER_EJECT 0x6B -#define STATUS_BACK_FEED_E 0x6C - -static char *status_str(uint8_t v) { - switch (v) { - case STATUS_READY: - return "Ready"; - case STATUS_INIT_CPU: - return "Initializing CPU"; - case STATUS_INIT_RIBBON: - return "Initializing Ribbon"; - case STATUS_INIT_PAPER: - return "Loading Paper"; - case STATUS_THERMAL_PROTECT: - return "Thermal Protection"; - case STATUS_USING_PANEL: - return "Using Operation Panel"; - case STATUS_SELF_DIAG: - return "Processing Self Diagnosis"; - case STATUS_DOWNLOADING: - return "Processing Download"; - case STATUS_FEEDING_PAPER: - return "Feeding Paper"; - case STATUS_PRE_HEAT: - return "Pre-Heating"; - case STATUS_PRINT_Y: - return "Printing Yellow"; - case STATUS_BACK_FEED_Y: - return "Back-Feeding - Yellow Complete"; - case STATUS_PRINT_M: - return "Printing Magenta"; - case STATUS_BACK_FEED_M: - return "Back-Feeding - Magenta Complete"; - case STATUS_PRINT_C: - return "Printing Cyan"; - case STATUS_BACK_FEED_C: - return "Back-Feeding - Cyan Complete"; - case STATUS_PRINT_OP: - return "Laminating"; - case STATUS_PAPER_CUT: - return "Cutting Paper"; - case STATUS_PAPER_EJECT: - return "Ejecting Paper"; - case STATUS_BACK_FEED_E: - return "Back-Feeding - Ejected"; - case ERROR_PRINTER: - return "Printer Error"; - default: - return "Unknown"; - } -} - struct s6245_status_resp { - struct s6245_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint32_t count_lifetime; uint32_t count_maint; uint32_t count_paper; @@ -704,117 +341,35 @@ struct s6245_status_resp { uint8_t reserved3[6]; } __attribute__((packed)); -#define BANK_STATUS_FREE 0x00 -#define BANK_STATUS_XFER 0x01 -#define BANK_STATUS_FULL 0x02 -#define BANK_STATUS_PRINTING 0x12 - -static char *bank_statuses(uint8_t v) -{ - switch (v) { - case BANK_STATUS_FREE: - return "Free"; - case BANK_STATUS_XFER: - return "Xfer"; - case BANK_STATUS_FULL: - return "Full"; - case BANK_STATUS_PRINTING: - return "Printing"; - default: - return "Unknown"; - } -} - -#define TONECURVE_INIT 0x00 -#define TONECURVE_USER 0x01 -#define TONECURVE_CURRENT 0x02 - -static char *tonecurve_statuses (uint8_t v) -{ - switch(v) { - case 0: - return "Initial"; - case 1: - return "UserSet"; - case 2: - return "Current"; - default: - return "Unknown"; - } -} - struct s6245_geteeprom_resp { - struct s6245_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t data[256]; } __attribute__((packed)); -struct s6245_readtone_resp { - struct s6245_status_hdr hdr; - uint16_t total_size; -} __attribute__((packed)); - -struct s6245_mediainfo_item { - uint8_t media_code; - uint16_t columns; - uint16_t rows; - uint8_t reserved; - uint8_t print_method; /* PRINT_METHOD_* */ - uint8_t reserved2[3]; -} __attribute__((packed)); - -#define MEDIA_8x10 0x10 -#define MEDIA_8x12 0x11 -#define MEDIA_8x4 0x20 -#define MEDIA_8x5 0x21 -#define MEDIA_8x6 0x22 -#define MEDIA_8x8 0x23 -#define MEDIA_8x4_2 0x30 -#define MEDIA_8x5_2 0x31 -#define MEDIA_8x6_2 0x32 -#define MEDIA_8x4_3 0x40 - -static const char *print_sizes (uint8_t v) { - switch (v) { - case MEDIA_8x10: - return "8x10"; - case MEDIA_8x12: - return "8x12"; - case MEDIA_8x4: - return "8x4"; - case MEDIA_8x5: - return "8x5"; - case MEDIA_8x6: - return "8x6"; - case MEDIA_8x8: - return "8x8"; - case MEDIA_8x4_2: - return "8x4*2"; - case MEDIA_8x5_2: - return "8x5*2"; - case MEDIA_8x6_2: - return "8x6*2"; - case MEDIA_8x4_3: - return "8x4*3"; - default: - return "Unknown"; - } -} - struct s6245_mediainfo_resp { - struct s6245_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint8_t ribbon_code; uint8_t reserved; uint8_t count; - struct s6245_mediainfo_item items[10]; /* Not all necessarily used */ + struct sinfonia_mediainfo_item items[10]; /* Not all necessarily used */ } __attribute__((packed)); +#define RIBBON_NONE 0x00 +#define RIBBON_8x10 0x11 +#define RIBBON_8x12 0x12 + +#define RIBBON_8x10K 0x03 /* XXX GUESS - EK8810 */ +#define RIBBON_8x12K 0x04 /* EK8810 */ + static const char *ribbon_sizes (uint8_t v) { switch (v) { - case 0x00: + case RIBBON_NONE: return "None"; - case 0x11: + case RIBBON_8x10: + case RIBBON_8x10K: return "8x10"; - case 0x12: + case RIBBON_8x12: + case RIBBON_8x12K: return "8x12"; default: return "Unknown"; @@ -823,17 +378,21 @@ static const char *ribbon_sizes (uint8_t v) { static int ribbon_counts (uint8_t v) { switch (v) { - case 0x11: + case RIBBON_8x10: return 120; - case 0x12: + case RIBBON_8x12: return 100; + case RIBBON_8x10K: + return 250; + case RIBBON_8x12K: + return 250; default: return 120; } } struct s6245_errorlog_resp { - struct s6245_status_hdr hdr; + struct sinfonia_status_hdr hdr; uint16_t error_count; uint8_t error_major; uint8_t error_minor; @@ -864,62 +423,9 @@ struct s6245_errorlog_resp { uint8_t reserved5[8]; } __attribute__((packed)); -struct s6245_getparam_resp { - struct s6245_status_hdr hdr; - uint32_t param; -} __attribute__((packed)); - -struct s6245_getserial_resp { - struct s6245_status_hdr hdr; - uint8_t data[8]; -} __attribute__((packed)); - -struct s6245_getprintidstatus_resp { - struct s6245_status_hdr hdr; - uint8_t id; - uint16_t remaining; - uint16_t finished; - uint16_t specified; - uint16_t status; -} __attribute__((packed)); - -#define STATUS_WAITING 0x0000 -#define STATUS_PRINTING 0x0100 -#define STATUS_COMPLETED 0x0200 -#define STATUS_ERROR 0xFFFF - -struct s6245_getextcounter_resp { - struct s6245_status_hdr hdr; - uint32_t lifetime_distance; /* Inches */ - uint32_t maint_distance; - uint32_t head_distance; - uint8_t reserved[32]; -} __attribute__((packed)); - -struct s6245_fwinfo_resp { - struct s6245_status_hdr hdr; - uint8_t name[8]; - uint8_t type[16]; - uint8_t date[10]; - uint8_t major; - uint8_t minor; - uint16_t checksum; -} __attribute__((packed)); - /* Private data structure */ -struct shinkos6245_printjob { - uint8_t *databuf; - int datalen; - int copies; - - struct s6245_printjob_hdr hdr; -}; - struct shinkos6245_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; + struct sinfonia_usbdev dev; uint8_t jobid; @@ -928,71 +434,37 @@ struct shinkos6245_ctx { struct s6245_mediainfo_resp media; }; -#define READBACK_LEN 512 /* Needs to be larger than largest response hdr */ #define CMDBUF_LEN sizeof(struct s6245_print_cmd) -static int s6245_do_cmd(struct shinkos6245_ctx *ctx, - uint8_t *cmd, int cmdlen, - int buflen, - int *num, struct s6245_status_hdr *resp) -{ - libusb_device_handle *dev = ctx->dev; - uint8_t endp_up = ctx->endp_up; - uint8_t endp_down = ctx->endp_down; - int ret; - - if ((ret = send_data(dev, endp_down, - cmd, cmdlen))) - return (ret < 0) ? ret : -99; - - ret = read_data(dev, endp_up, - (uint8_t *)resp, buflen, num); - - if (ret < 0) - return ret; - - if (resp->result != RESULT_SUCCESS) { - INFO("Printer Status: %02x (%s)\n", resp->status, - status_str(resp->status)); - INFO(" Result: 0x%02x Error: 0x%02x (0x%02x/0x%02x = %s)\n", - resp->result, resp->error, resp->printer_major, - resp->printer_minor, error_codes(resp->printer_major, resp->printer_minor)); - return -99; - } - - return ret; -} - static int get_status(struct shinkos6245_ctx *ctx) { - struct s6245_cmd_hdr cmd; + struct sinfonia_cmd_hdr cmd; struct s6245_status_resp resp; - struct s6245_getextcounter_resp resp2; + struct sinfonia_getextcounter_resp resp2; int ret, num = 0; - cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*) &resp, sizeof(resp), + &num)) < 0) { return ret; } INFO("Printer Status: 0x%02x (%s)\n", resp.hdr.status, - status_str(resp.hdr.status)); + sinfonia_status_str(resp.hdr.status)); if (resp.hdr.status == ERROR_PRINTER) { if(resp.hdr.error == ERROR_NONE) resp.hdr.error = resp.hdr.status; INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", resp.hdr.error, - error_str(resp.hdr.error), + sinfonia_error_str(resp.hdr.error), resp.hdr.printer_major, resp.hdr.printer_minor, error_codes(resp.hdr.printer_major, resp.hdr.printer_minor)); } - if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct sinfonia_status_hdr))) return 0; INFO(" Print Counts:\n"); @@ -1001,35 +473,40 @@ static int get_status(struct shinkos6245_ctx *ctx) INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp.count_maint)); INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp.count_head)); INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp.count_cutter)); - INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp.count_ribbon_left)); + INFO(" Ribbon Remaining:\t%8u%%\n", le32_to_cpu(resp.count_ribbon_left)); + INFO(" Prints Remaining:\t%8u\n", ribbon_counts(ctx->media.ribbon_code) - le32_to_cpu(resp.count_paper)); INFO("Bank 1: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp.bank1_status, bank_statuses(resp.bank1_status), + resp.bank1_status, sinfonia_bank_statuses(resp.bank1_status), resp.bank1_printid, le16_to_cpu(resp.bank1_finished), le16_to_cpu(resp.bank1_specified), le16_to_cpu(resp.bank1_remaining)); INFO("Bank 2: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp.bank2_status, bank_statuses(resp.bank1_status), + resp.bank2_status, sinfonia_bank_statuses(resp.bank1_status), resp.bank2_printid, le16_to_cpu(resp.bank2_finished), le16_to_cpu(resp.bank2_specified), le16_to_cpu(resp.bank2_remaining)); - INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, tonecurve_statuses(resp.tonecurve_status)); + INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, sinfonia_tonecurve_statuses(resp.tonecurve_status)); + /* Query Extended counters */ - cmd.cmd = cpu_to_le16(S6245_CMD_EXTCOUNTER); + if (ctx->dev.type == P_KODAK_8810) + return 0; /* Kodak 8810 returns 12 bytes of garbage. */ + + cmd.cmd = cpu_to_le16(SINFONIA_CMD_EXTCOUNTER); cmd.len = cpu_to_le16(0); - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp2), - &num, (void*)&resp2)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp2, sizeof(resp2), + &num)) < 0) { return ret; } - if (le16_to_cpu(resp2.hdr.payload_len) != (sizeof(struct s6245_getextcounter_resp) - sizeof(struct s6245_status_hdr))) + + if (le16_to_cpu(resp2.hdr.payload_len) < 12) return 0; INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2.lifetime_distance)); @@ -1039,46 +516,6 @@ static int get_status(struct shinkos6245_ctx *ctx) return 0; } -static int get_fwinfo(struct shinkos6245_ctx *ctx) -{ - struct s6245_fwinfo_cmd cmd; - struct s6245_fwinfo_resp resp; - int num = 0; - int i; - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_FWINFO); - cmd.hdr.len = cpu_to_le16(1); - - INFO("FW Information:\n"); - - for (i = FWINFO_TARGET_MAIN_BOOT ; i <= FWINFO_TARGET_PRINT_TABLES ; i++) { - int ret; - cmd.target = i; - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); - continue; - } - - if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_fwinfo_resp) - sizeof(struct s6245_status_hdr))) - continue; - - INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i), - resp.major, resp.minor); -#if 0 - INFO(" name: '%s'\n", resp.name); - INFO(" type: '%s'\n", resp.type); - INFO(" date: '%s'\n", resp.date); - INFO(" version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor, - le16_to_cpu(resp.checksum)); -#endif - } - return 0; -} - static int get_errorlog(struct shinkos6245_ctx *ctx) { struct s6245_errorlog_cmd cmd; @@ -1086,22 +523,21 @@ static int get_errorlog(struct shinkos6245_ctx *ctx) int num = 0; int i = 0; - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_ERRORLOG); + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_ERRORLOG); cmd.hdr.len = cpu_to_le16(2); do { int ret; cmd.index = i; - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); + if ((ret = sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return ret; } - if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct sinfonia_status_hdr))) return -2; INFO("Stored Error ID %d:\n", i); @@ -1126,240 +562,13 @@ static void dump_mediainfo(struct s6245_mediainfo_resp *resp) INFO("Supported Media Information: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { INFO(" %02d: C 0x%02x (%s), %04ux%04u, P 0x%02x (%s)\n", i, - resp->items[i].media_code, print_sizes(resp->items[i].media_code), - le16_to_cpu(resp->items[i].columns), - le16_to_cpu(resp->items[i].rows), - resp->items[i].print_method, print_methods(resp->items[i].print_method)); - } -} - -static int cancel_job(struct shinkos6245_ctx *ctx, char *str) -{ - struct s6245_cancel_cmd cmd; - struct s6245_status_hdr resp; - int ret, num = 0; - - if (!str) - return -1; - - cmd.id = atoi(str); - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_CANCELJOB); - cmd.hdr.len = cpu_to_le16(1); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - return 0; -} - -static int flash_led(struct shinkos6245_ctx *ctx) -{ - struct s6245_cmd_hdr cmd; - struct s6245_status_hdr resp; - int ret, num = 0; - - cmd.cmd = cpu_to_le16(S6245_CMD_FLASHLED); - cmd.len = cpu_to_le16(0); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); - return ret; - } - - return 0; -} - - -static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param) -{ - struct s6245_setparam_cmd cmd; - struct s6245_status_hdr resp; - int ret, num = 0; - - /* Set up command */ - cmd.target = target; - cmd.param = cpu_to_le32(param); - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_SETPARAM); - cmd.hdr.len = cpu_to_le16(sizeof(struct s6245_setparam_cmd)-sizeof(cmd.hdr)); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); - } - - return ret; -} - -static int reset_curve(struct shinkos6245_ctx *ctx, int target) -{ - struct s6245_reset_cmd cmd; - struct s6245_status_hdr resp; - int ret, num = 0; - - cmd.target = target; - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_RESET); - cmd.hdr.len = cpu_to_le16(1); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - return 0; -} - -static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname) -{ - struct s6245_readtone_cmd cmd; - struct s6245_readtone_resp resp; - int ret, num = 0; - - uint8_t *data; - uint16_t curves[UPDATE_SIZE] = { 0 }; - - int i,j; - - cmd.target = type; - cmd.curveid = TONE_CURVE_ID; - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_READTONE); - cmd.hdr.len = cpu_to_le16(1); - - INFO("Dump %s Tone Curve to '%s'\n", tonecurve_statuses(type), fname); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - return ret; - } - - resp.total_size = le16_to_cpu(resp.total_size); - - data = malloc(resp.total_size * 2); - if (!data) { - ERROR("Memory Allocation Failure!\n"); - return -1; - } - - i = 0; - while (i < resp.total_size) { - ret = read_data(ctx->dev, ctx->endp_up, - data + i, - resp.total_size * 2 - i, - &num); - if (ret < 0) - goto done; - i += num; - } - - i = j = 0; - while (i < resp.total_size) { - memcpy(curves + j, data + i+2, data[i+1]); - j += data[i+1] / 2; - i += data[i+1] + 2; - } - - /* Open file and write it out */ - { - int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); - if (tc_fd < 0) { - ret = -1; - goto done; - } - - for (i = 0 ; i < UPDATE_SIZE; i++) { - /* Byteswap appropriately */ - curves[i] = cpu_to_be16(le16_to_cpu(curves[i])); - } - write(tc_fd, curves, UPDATE_SIZE * sizeof(uint16_t)); - close(tc_fd); - } - -done: - free(data); - return ret; -} - -static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname) -{ - struct s6245_update_cmd cmd; - struct s6245_status_hdr resp; - int ret, num = 0; - - INFO("Set %s Tone Curve from '%s'\n", update_targets(target), fname); - - uint16_t *data = malloc(UPDATE_SIZE * sizeof(uint16_t)); - if (!data) { - ERROR("Memory Allocation Failure!\n"); - return -1; - } - - /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE * sizeof(uint16_t)) != (UPDATE_SIZE * sizeof(uint16_t))) { - ret = -2; - goto done; - } - close(tc_fd); - /* Byteswap data to local CPU.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { - data[ret] = be16_to_cpu(data[ret]); - } - - /* Set up command */ - cmd.target = target; - cmd.reserved[0] = cmd.reserved[1] = cmd.reserved[2] = 0; - cmd.reset = 0; - cmd.size = cpu_to_le32(UPDATE_SIZE * sizeof(uint16_t)); - - cmd.hdr.cmd = cpu_to_le16(S6245_CMD_UPDATE); - cmd.hdr.len = cpu_to_le16(sizeof(struct s6245_update_cmd)-sizeof(cmd.hdr)); - - /* Byteswap data to format printer is expecting.. */ - for (ret = 0; ret < UPDATE_SIZE ; ret++) { - data[ret] = cpu_to_le16(data[ret]); - } - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); - goto done; - } - - /* Sent transfer */ - if ((ret = send_data(ctx->dev, ctx->endp_down, - (uint8_t *) data, UPDATE_SIZE * sizeof(uint16_t)))) { - goto done; + resp->items[i].code, + sinfonia_print_codes(resp->items[i].code, 1), + resp->items[i].columns, + resp->items[i].rows, + resp->items[i].method, + sinfonia_print_methods(resp->items[i].method)); } - -done: - free(data); - - return ret; } static void shinkos6245_cmdline(void) @@ -1387,26 +596,30 @@ int shinkos6245_cmdline_arg(void *vctx, int argc, char **argv) if (!ctx) return -1; - while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mr:R:sX:")) >= 0) { + while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:eFik:l:L:mrR:sX:")) >= 0) { switch(i) { GETOPT_PROCESS_GLOBAL case 'c': - j = get_tonecurve(ctx, TONECURVE_USER, optarg); + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_USER, optarg); break; case 'C': - j = set_tonecurve(ctx, TONECURVE_USER, optarg); + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_USER, optarg); break; case 'e': - j = get_errorlog(ctx); + if (ctx->dev.type == P_KODAK_8810) { + j = sinfonia_geterrorlog(&ctx->dev); + } else { + j = get_errorlog(ctx); + } break; case 'F': - j = flash_led(ctx); + j = sinfonia_flashled(&ctx->dev); break; case 'i': - j = get_fwinfo(ctx); + j = sinfonia_getfwinfo(&ctx->dev); break; case 'k': { - uint32_t i = atoi(optarg); + i = atoi(optarg); if (i < 5) i = 0; else if (i < 15) @@ -1422,29 +635,29 @@ int shinkos6245_cmdline_arg(void *vctx, int argc, char **argv) else i = 5; - j = set_param(ctx, PARAM_SLEEP_TIME, i); + j = sinfonia_setparam(&ctx->dev, PARAM_SLEEP_TIME, i); break; } case 'l': - j = get_tonecurve(ctx, TONECURVE_CURRENT, optarg); + j = sinfonia_gettonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); break; case 'L': - j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg); + j = sinfonia_settonecurve(&ctx->dev, TONECURVE_CURRENT, optarg); break; case 'm': dump_mediainfo(&ctx->media); break; case 'r': - j = reset_curve(ctx, RESET_TONE_CURVE); + j = sinfonia_resetcurve(&ctx->dev, RESET_TONE_CURVE, TONE_CURVE_ID); break; case 'R': - j = reset_curve(ctx, RESET_PRINTER); + j = sinfonia_resetcurve(&ctx->dev, RESET_PRINTER, 0); break; case 's': j = get_status(ctx); break; case 'X': - j = cancel_job(ctx, optarg); + j = sinfonia_canceljob(&ctx->dev, atoi(optarg)); break; default: break; /* Ignore completely */ @@ -1475,10 +688,11 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, int int num; - ctx->dev = dev; - ctx->endp_up = endp_up; - ctx->endp_down = endp_down; - ctx->type = type; + ctx->dev.dev = dev; + ctx->dev.endp_up = endp_up; + ctx->dev.endp_down = endp_down; + ctx->dev.type = type; + ctx->dev.error_codes = &error_codes; /* Ensure jobid is sane */ ctx->jobid = jobid & 0x7f; @@ -1487,59 +701,44 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, int /* Query Media */ if (test_mode < TEST_MODE_NOATTACH) { - struct s6245_cmd_hdr cmd; - cmd.cmd = cpu_to_le16(S6245_CMD_MEDIAINFO); + struct sinfonia_cmd_hdr cmd; + cmd.cmd = cpu_to_le16(SINFONIA_CMD_MEDIAINFO); cmd.len = cpu_to_le16(0); - if (s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(ctx->media), - &num, (void*)&ctx->media)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if (sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&ctx->media, sizeof(ctx->media), + &num)) { return CUPS_BACKEND_FAILED; } + + /* Byteswap media descriptor.. */ + int i; + for (i = 0 ; i < ctx->media.count ; i++) { + ctx->media.items[i].columns = le16_to_cpu(ctx->media.items[i].columns); + ctx->media.items[i].rows = le16_to_cpu(ctx->media.items[i].rows); + } + } else { - int media_code = 0x12; + int media_code = RIBBON_8x12; if (getenv("MEDIA_CODE")) media_code = atoi(getenv("MEDIA_CODE")); - ctx->media.ribbon_code = media_code; } ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; ctx->marker.name = ribbon_sizes(ctx->media.ribbon_code); - ctx->marker.levelmax = ribbon_counts(ctx->media.ribbon_code); + ctx->marker.levelmax = 100; ctx->marker.levelnow = -2; return CUPS_BACKEND_OK; } -static void shinkos6245_cleanup_job(const void *vjob) -{ - const struct shinkos6245_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void shinkos6245_teardown(void *vctx) { - struct shinkos6245_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int shinkos6245_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct shinkos6245_ctx *ctx = vctx; + struct sinfonia_printjob *job = NULL; int ret; - uint8_t tmpbuf[4]; - - struct shinkos6245_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1550,75 +749,22 @@ static int shinkos6245_read_parse(void *vctx, const void **vjob, int data_fd, in return CUPS_BACKEND_RETRY_CURRENT; } memset(job, 0, sizeof(*job)); - job->copies = copies; // XXX hdr.copies - - /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - if (ret == 0) - return CUPS_BACKEND_CANCEL; - ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); - perror("ERROR: Read failed"); - return ret; - } - - if (le32_to_cpu(job->hdr.len1) != 0x10 || - le32_to_cpu(job->hdr.len2) != 0x64 || - le32_to_cpu(job->hdr.dpi) != 300) { - ERROR("Unrecognized header data format!\n"); - return CUPS_BACKEND_CANCEL; - } - - if (le32_to_cpu(job->hdr.model) != 6245) { - ERROR("Unrecognized printer (%u)!\n", le32_to_cpu(job->hdr.model)); - - return CUPS_BACKEND_CANCEL; - } - - if (job->databuf) { - free(job->databuf); - job->databuf = NULL; - } - - job->datalen = le32_to_cpu(job->hdr.rows) * le32_to_cpu(job->hdr.columns) * 3; - job->databuf = malloc(job->datalen); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - return CUPS_BACKEND_RETRY_CURRENT; - } - { - int remain = job->datalen; - uint8_t *ptr = job->databuf; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%d)\n", - ret, remain, job->datalen); - perror("ERROR: Read failed"); - return ret; - } - ptr += ret; - remain -= ret; - } while (remain); + /* Common read/parse code */ + if (ctx->dev.type == P_KODAK_8810) { + ret = sinfonia_raw18_read_parse(data_fd, job); + } else { + ret = sinfonia_read_parse(data_fd, 6245, job); } - - /* Make sure footer is sane too */ - ret = read(data_fd, tmpbuf, 4); - if (ret != 4) { - ERROR("Read failed (%d/%d/%d)\n", - ret, 4, 4); - perror("ERROR: Read failed"); + if (ret) { + free(job); return ret; } - if (tmpbuf[0] != 0x04 || - tmpbuf[1] != 0x03 || - tmpbuf[2] != 0x02 || - tmpbuf[3] != 0x01) { - ERROR("Unrecognized footer data format!\n"); - return CUPS_BACKEND_FAILED; - } + + if (job->jp.copies > 1) + job->copies = job->jp.copies; + else + job->copies = copies; *vjob = job; @@ -1631,16 +777,16 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) { int ret, num; uint8_t cmdbuf[CMDBUF_LEN]; - int i, last_state = -1, state = S_IDLE; + int last_state = -1, state = S_IDLE; uint8_t mcut; int copies; - struct s6245_cmd_hdr *cmd = (struct s6245_cmd_hdr *) cmdbuf;; + struct sinfonia_cmd_hdr *cmd = (struct sinfonia_cmd_hdr *) cmdbuf;; struct s6245_print_cmd *print = (struct s6245_print_cmd *) cmdbuf; struct s6245_status_resp sts, sts2; - struct s6245_status_hdr resp; + struct sinfonia_status_hdr resp; - struct shinkos6245_printjob *job = (struct shinkos6245_printjob*) vjob; + struct sinfonia_printjob *job = (struct sinfonia_printjob*) vjob; copies = job->copies; @@ -1651,13 +797,13 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) { copies = 120; /* Set up mcut */ - switch (le32_to_cpu(job->hdr.media)) { - case MEDIA_8x4_2: - case MEDIA_8x5_2: - case MEDIA_8x6_2: + switch (job->jp.media) { + case CODE_8x4_2: + case CODE_8x5_2: + case CODE_8x6_2: mcut = PRINT_METHOD_COMBO_2; break; - case MEDIA_8x4_3: + case CODE_8x4_3: mcut = PRINT_METHOD_COMBO_3; break; default: @@ -1665,44 +811,56 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) { } // XXX what about mcut |= PRINT_METHOD_DISABLE_ERR; +#if 0 + int i; /* Validate print sizes */ for (i = 0; i < ctx->media.count ; i++) { /* Look for matching media */ - if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(job->hdr.columns)) && - le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(job->hdr.rows))) + if (ctx->media.items[i].columns == job->jp.columns && + ctx->media.items[i].rows == job->jp.rows) break; } if (i == ctx->media.count) { ERROR("Incorrect media loaded for print!\n"); return CUPS_BACKEND_HOLD; } +#else + if (ctx->media.ribbon_code != RIBBON_8x12 && + ctx->media.ribbon_code != RIBBON_8x12K && + job->jp.rows > 3024) { + ERROR("Incorrect media loaded for print!\n"); + return CUPS_BACKEND_HOLD; + } + +#endif /* Send Set Time */ - { - struct s6245_settime_cmd *stime = (struct s6245_settime_cmd *)cmdbuf; + if (ctx->dev.type != P_KODAK_8810) { + struct s6245_settime_cmd *settime = (struct s6245_settime_cmd *)cmdbuf; time_t now = time(NULL); struct tm *cur = localtime(&now); memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S6245_CMD_SETTIME); + cmd->cmd = cpu_to_le16(SINFONIA_CMD_SETTIME); cmd->len = cpu_to_le16(0); - stime->enable = 1; - stime->second = cur->tm_sec; - stime->minute = cur->tm_min; - stime->hour = cur->tm_hour; - stime->day = cur->tm_mday; - stime->month = cur->tm_mon; - stime->year = cur->tm_year + 1900 - 2000; - - if ((ret = s6245_do_cmd(ctx, - cmdbuf, sizeof(*stime), - sizeof(struct s6245_status_hdr), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(stime->hdr.cmd)); + settime->enable = 1; + settime->second = cur->tm_sec; + settime->minute = cur->tm_min; + settime->hour = cur->tm_hour; + settime->day = cur->tm_mday; + settime->month = cur->tm_mon; + settime->year = cur->tm_year + 1900 - 2000; + + if ((ret = sinfonia_docmd(&ctx->dev, + cmdbuf, sizeof(*settime), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return CUPS_BACKEND_FAILED; } - if (resp.result != RESULT_SUCCESS) - goto printer_error; + if (resp.result != RESULT_SUCCESS) { + ERROR("Bad result %02x\n", resp.result); + goto fail; + } } // XXX check copies against remaining media! @@ -1715,14 +873,13 @@ top: /* Send Status Query */ memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S6245_CMD_GETSTATUS); + cmd->cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd->len = cpu_to_le16(0); - if ((ret = s6245_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(sts), - &num, (void*)&sts)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + cmdbuf, sizeof(*cmd), + (uint8_t*)&sts, sizeof(sts), + &num)) < 0) { return CUPS_BACKEND_FAILED; } @@ -1730,7 +887,7 @@ top: memcpy(&sts2, &sts, sizeof(sts)); INFO("Printer Status: 0x%02x (%s)\n", - sts.hdr.status, status_str(sts.hdr.status)); + sts.hdr.status, sinfonia_status_str(sts.hdr.status)); if (ctx->marker.levelnow != (int)sts.count_ribbon_left) { ctx->marker.levelnow = sts.count_ribbon_left; @@ -1775,21 +932,19 @@ top: INFO("Sending print job (internal id %u)\n", ctx->jobid); memset(cmdbuf, 0, CMDBUF_LEN); - print->hdr.cmd = cpu_to_le16(S6245_CMD_PRINTJOB); + print->hdr.cmd = cpu_to_le16(SINFONIA_CMD_PRINTJOB); print->hdr.len = cpu_to_le16(sizeof (*print) - sizeof(*cmd)); - print->id = ctx->jobid; print->count = cpu_to_le16(copies); - print->columns = cpu_to_le16(le32_to_cpu(job->hdr.columns)); - print->rows = cpu_to_le16(le32_to_cpu(job->hdr.rows)); - print->mode = le32_to_cpu(job->hdr.oc_mode); + print->columns = print->columns2 = cpu_to_le16(job->jp.columns); + print->rows = print->rows2 = cpu_to_le16(job->jp.rows); + print->mode = job->jp.oc_mode; print->method = mcut; - if ((ret = s6245_do_cmd(ctx, - cmdbuf, sizeof(*print), - sizeof(resp), - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd)); + if ((ret = sinfonia_docmd(&ctx->dev, + cmdbuf, sizeof(*print), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return ret; } @@ -1797,15 +952,15 @@ top: if (resp.error == ERROR_BUFFER_FULL) { INFO("Printer Buffers full, retrying\n"); break; - } else if ((resp.status & 0xf0) == 0x30 || sts.hdr.status == 0x21) { - INFO("Printer busy (%s), retrying\n", status_str(sts.hdr.status)); + } else if ((resp.status & 0xf0) == 0x30 || sts.hdr.status == ERROR_BUFFER_FULL) { + INFO("Printer busy (%s), retrying\n", sinfonia_status_str(sts.hdr.status)); break; } else if (resp.status != ERROR_NONE) goto printer_error; } INFO("Sending image data to printer\n"); - if ((ret = send_data(ctx->dev, ctx->endp_down, + if ((ret = send_data(ctx->dev.dev, ctx->dev.endp_down, job->databuf, job->datalen))) return CUPS_BACKEND_FAILED; @@ -1835,44 +990,41 @@ top: printer_error: ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n", sts.hdr.error, - error_str(sts.hdr.error), + sinfonia_error_str(sts.hdr.error), sts.hdr.status, - status_str(sts.hdr.status), + sinfonia_status_str(sts.hdr.status), sts.hdr.printer_major, sts.hdr.printer_minor, error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); +fail: return CUPS_BACKEND_FAILED; } static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len) { - struct s6245_cmd_hdr cmd; - struct s6245_getserial_resp resp; + struct sinfonia_cmd_hdr cmd; + struct sinfonia_getserial_resp resp; int ret, num = 0; - struct shinkos6245_ctx ctx = { + struct sinfonia_usbdev sdev = { .dev = dev, .endp_up = endp_up, .endp_down = endp_down, }; - cmd.cmd = cpu_to_le16(S6245_CMD_GETSERIAL); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSERIAL); cmd.len = cpu_to_le16(0); - if ((ret = s6245_do_cmd(&ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(resp) - 1, - &num, (void*)&resp)) < 0) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if ((ret = sinfonia_docmd(&sdev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { return ret; } - /* Null-terminate */ - resp.hdr.payload_len = le16_to_cpu(resp.hdr.payload_len); - if (resp.hdr.payload_len > 23) - resp.hdr.payload_len = 23; - resp.data[resp.hdr.payload_len] = 0; - strncpy(buf, (char*)resp.data, buf_len); - buf[buf_len-1] = 0; /* ensure it's null terminated */ + /* Copy and Null-terminate */ + num = (buf_len > (int)sizeof(resp.data)) ? (int)sizeof(resp.data) : (buf_len - 1); + memcpy(buf, resp.data, num); + buf[num] = 0; return CUPS_BACKEND_OK; } @@ -1880,19 +1032,18 @@ static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t end static int shinkos6245_query_markers(void *vctx, struct marker **markers, int *count) { struct shinkos6245_ctx *ctx = vctx; - struct s6245_cmd_hdr cmd; + struct sinfonia_cmd_hdr cmd; struct s6245_status_resp status; int num; /* Query Status */ - cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS); + cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSTATUS); cmd.len = cpu_to_le16(0); - if (s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(status), - &num, (void*)&status)) { - ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + if (sinfonia_docmd(&ctx->dev, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&status, sizeof(status), + &num)) { return CUPS_BACKEND_FAILED; } @@ -1909,9 +1060,11 @@ static int shinkos6245_query_markers(void *vctx, struct marker **markers, int *c #define USB_PID_SHINKO_S6245 0x001D #define USB_VID_HITI 0x0D16 #define USB_PID_HITI_P910L 0x000E +#define USB_VID_KODAK 0x040A +#define USB_PID_KODAK_8810 0x404D static const char *shinkos6245_prefixes[] = { - "sinfonia-chcs6245", "hiti-p910l", + "sinfonia-chcs6245", "hiti-p910l", "kodak-8810", // extras "shinko-chcs6245", // backwards compatibility @@ -1920,15 +1073,14 @@ static const char *shinkos6245_prefixes[] = { }; struct dyesub_backend shinkos6245_backend = { - .name = "Shinko/Sinfonia CHC-S6245", - .version = "0.14WIP", + .name = "Sinfonia CHC-S6245 / Kodak 8810", + .version = "0.22" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = shinkos6245_prefixes, .cmdline_usage = shinkos6245_cmdline, .cmdline_arg = shinkos6245_cmdline_arg, .init = shinkos6245_init, .attach = shinkos6245_attach, - .teardown = shinkos6245_teardown, - .cleanup_job = shinkos6245_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = shinkos6245_read_parse, .main_loop = shinkos6245_main_loop, .query_serno = shinkos6245_query_serno, @@ -1936,6 +1088,7 @@ struct dyesub_backend shinkos6245_backend = { .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S6245, P_SHINKO_S6245, NULL, "shinfonia-chcs6245"}, { USB_VID_HITI, USB_PID_HITI_P910L, P_SHINKO_S6245, NULL, "hiti-p910l"}, + { USB_VID_KODAK, USB_PID_KODAK_8810, P_KODAK_8810, NULL, "kodak-8810"}, { 0, 0, 0, NULL, NULL} } }; @@ -1959,4 +1112,20 @@ struct dyesub_backend shinkos6245_backend = { 04 03 02 01 [[ footer ]] + Kodak 8810 data format: (Note: EK8810 is actually a Sinfonia CHC-S1845-5A) + + Spool file is the print_cmd_hdr (22 bytes) followed by RGB-packed data. + + 01 40 0a 00 Fixed header + XX Job ID + CC CC Number of copies (1-???) + WW WW Number of columns + HH HH Number of rows + WW WW Number of columns + HH HH Number of rows + 00 00 00 00 Reserved/Unknown + LL Laminate, 0x02/0x03 (on/satin) + MM Print Method + 00 Reserved/Unknown + */ diff --git a/src/cups/backend_sinfonia.c b/src/cups/backend_sinfonia.c new file mode 100644 index 0000000..07d7716 --- /dev/null +++ b/src/cups/backend_sinfonia.c @@ -0,0 +1,1154 @@ + /* + * Shinko/Sinfonia Common Code + * + * (c) 2019 Solomon Peachy <pizza@shaftnet.org> + * + * The latest version of this program can be found at: + * + * http://git.shaftnet.org/cgit/selphy_print.git + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * [http://www.gnu.org/licenses/gpl-2.0.html] + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> + +#include "backend_common.h" +#include "backend_sinfonia.h" + +int sinfonia_read_parse(int data_fd, uint32_t model, + struct sinfonia_printjob *job) +{ + uint32_t hdr[29]; + int ret, i; + uint8_t tmpbuf[4]; + + /* Read in header */ + ret = read(data_fd, hdr, SINFONIA_HDR_LEN); + if (ret < 0 || ret != SINFONIA_HDR_LEN) { + if (ret == 0) + return CUPS_BACKEND_CANCEL; + ERROR("Read failed (%d/%d)\n", + ret, SINFONIA_HDR_LEN); + perror("ERROR: Read failed"); + return ret; + } + + /* Byteswap everything */ + for (i = 0 ; i < (SINFONIA_HDR_LEN / 4) ; i++) { + hdr[i] = le32_to_cpu(hdr[i]); + } + + /* Sanity-check headers */ + if (hdr[0] != SINFONIA_HDR1_LEN || + hdr[4] != SINFONIA_HDR2_LEN || + hdr[22] != SINFONIA_DPI) { + ERROR("Unrecognized header data format!\n"); + return CUPS_BACKEND_CANCEL; + } + if (hdr[1] != model) { + ERROR("job/printer mismatch (%u/%u)!\n", hdr[1], model); + return CUPS_BACKEND_CANCEL; + } + + if (!hdr[13] || !hdr[14]) { + ERROR("Bad job cols/rows!\n"); + return CUPS_BACKEND_CANCEL; + } + + /* Work out data length */ + job->datalen = hdr[13] * hdr[14] * 3; + job->databuf = malloc(job->datalen); + if (!job->databuf) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } + + /* Read in payload data */ + { + uint32_t remain = job->datalen; + uint8_t *ptr = job->databuf; + do { + ret = read(data_fd, ptr, remain); + if (ret < 0) { + ERROR("Read failed (%d/%u/%d)\n", + ret, remain, job->datalen); + perror("ERROR: Read failed"); + free(job->databuf); + job->databuf = NULL; + return ret; + } + ptr += ret; + remain -= ret; + } while (remain); + } + + /* Make sure footer is sane too */ + ret = read(data_fd, tmpbuf, 4); + if (ret != 4) { + ERROR("Read failed (%d/%d)\n", ret, 4); + perror("ERROR: Read failed"); + free(job->databuf); + job->databuf = NULL; + return ret; + } + if (tmpbuf[0] != 0x04 || + tmpbuf[1] != 0x03 || + tmpbuf[2] != 0x02 || + tmpbuf[3] != 0x01) { + ERROR("Unrecognized footer data format!\n"); + free (job->databuf); + job->databuf = NULL; + return CUPS_BACKEND_CANCEL; + } + + /* Fill out job params */ + job->jp.media = hdr[6]; + if (hdr[1] != 6245) + job->jp.method = hdr[8]; + if (hdr[1] == 2245 || hdr[1] == 6245) + job->jp.quality = hdr[9]; + if (hdr[1] == 1245 || hdr[1] == 2145) + job->jp.oc_mode = hdr[9]; + else + job->jp.oc_mode = hdr[10]; + if (hdr[1] == 1245) + job->jp.mattedepth = hdr[11]; + if (hdr[1] == 1245) + job->jp.dust = hdr[12]; + job->jp.columns = hdr[13]; + job->jp.rows = hdr[14]; + job->jp.copies = hdr[15]; + + if (hdr[1] == 2245 || hdr[1] == 6145) + job->jp.ext_flags = hdr[28]; + + return CUPS_BACKEND_OK; +} + +int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job) +{ + struct sinfonia_printcmd10_hdr hdr; + int ret; + + /* Read in header */ + ret = read(data_fd, &hdr, sizeof(hdr)); + if (ret < 0 || ret != sizeof(hdr)) { + if (ret == 0) + return CUPS_BACKEND_CANCEL; + ERROR("Read failed (%d/%d/%d)\n", + ret, 0, (int)sizeof(hdr)); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + /* Validate header */ + if (le16_to_cpu(hdr.hdr.cmd) != 0x4001 || + le16_to_cpu(hdr.hdr.len) != 10) { + ERROR("Unrecognized data format!\n"); + return CUPS_BACKEND_CANCEL; + } + job->jp.copies = le16_to_cpu(hdr.copies); + job->jp.rows = le16_to_cpu(hdr.rows); + job->jp.columns = le16_to_cpu(hdr.columns); + job->jp.media = hdr.media; + job->jp.oc_mode = hdr.oc_mode; + job->jp.method = hdr.method; + + /* Allocate buffer */ + job->datalen = job->jp.rows * job->jp.columns * 3; + job->databuf = malloc(job->datalen); + if (!job->databuf) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } + + { + int remain = job->datalen; + uint8_t *ptr = job->databuf; + do { + ret = read(data_fd, ptr, remain); + if (ret < 0) { + ERROR("Read failed (%d/%d/%d)\n", + ret, remain, job->datalen); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + ptr += ret; + remain -= ret; + } while (remain); + } + + return CUPS_BACKEND_OK; +} + +int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job) +{ + struct sinfonia_printcmd18_hdr hdr; + int ret; + + /* Read in header */ + ret = read(data_fd, &hdr, sizeof(hdr)); + if (ret < 0 || ret != sizeof(hdr)) { + if (ret == 0) + return CUPS_BACKEND_CANCEL; + ERROR("Read failed (%d/%d/%d)\n", + ret, 0, (int)sizeof(hdr)); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + /* Validate header */ + if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB || + le16_to_cpu(hdr.hdr.len) != 18) { + ERROR("Unrecognized data format!\n"); + return CUPS_BACKEND_CANCEL; + } + job->jp.copies = le16_to_cpu(hdr.copies); + job->jp.rows = le16_to_cpu(hdr.rows); + job->jp.columns = le16_to_cpu(hdr.columns); + job->jp.media = hdr.media; + job->jp.oc_mode = hdr.oc_mode; + job->jp.method = hdr.method; + + /* Allocate buffer */ + job->datalen = job->jp.rows * job->jp.columns * 3; + job->databuf = malloc(job->datalen); + if (!job->databuf) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } + + { + int remain = job->datalen; + uint8_t *ptr = job->databuf; + do { + ret = read(data_fd, ptr, remain); + if (ret < 0) { + ERROR("Read failed (%d/%d/%d)\n", + ret, remain, job->datalen); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + ptr += ret; + remain -= ret; + } while (remain); + } + + return CUPS_BACKEND_OK; +} + +int sinfonia_raw28_read_parse(int data_fd, struct sinfonia_printjob *job) +{ + struct sinfonia_printcmd28_hdr hdr; + int ret; + + /* Read in header */ + ret = read(data_fd, &hdr, sizeof(hdr)); + if (ret < 0 || ret != sizeof(hdr)) { + if (ret == 0) + return CUPS_BACKEND_CANCEL; + ERROR("Read failed (%d/%d/%d)\n", + ret, 0, (int)sizeof(hdr)); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + /* Validate header */ + if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB || + le16_to_cpu(hdr.hdr.len) != 28) { + ERROR("Unrecognized data format!\n"); + return CUPS_BACKEND_CANCEL; + } + job->jp.copies = le16_to_cpu(hdr.copies); + job->jp.rows = le16_to_cpu(hdr.rows); + job->jp.columns = le16_to_cpu(hdr.columns); + job->jp.media = hdr.media; + job->jp.oc_mode = hdr.options & 0x03; + job->jp.quality = hdr.options & 0x08; + job->jp.method = hdr.method; + + /* Allocate buffer */ + job->datalen = job->jp.rows * job->jp.columns * 3; + job->databuf = malloc(job->datalen); + if (!job->databuf) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } + + { + int remain = job->datalen; + uint8_t *ptr = job->databuf; + do { + ret = read(data_fd, ptr, remain); + if (ret < 0) { + ERROR("Read failed (%d/%d/%d)\n", + ret, remain, job->datalen); + perror("ERROR: Read failed"); + return CUPS_BACKEND_CANCEL; + } + ptr += ret; + remain -= ret; + } while (remain); + } + + return CUPS_BACKEND_OK; +} + +void sinfonia_cleanup_job(const void *vjob) +{ + const struct sinfonia_printjob *job = vjob; + + if (job->databuf) + free(job->databuf); + + free((void*)job); +} + +int sinfonia_docmd(struct sinfonia_usbdev *usbh, + uint8_t *cmd, int cmdlen, + uint8_t *resp, int resplen, + int *num) +{ + libusb_device_handle *dev = usbh->dev; + uint8_t endp_up = usbh->endp_up; + uint8_t endp_down = usbh->endp_down; + int ret; + + struct sinfonia_cmd_hdr *cmdhdr = (struct sinfonia_cmd_hdr *) cmd; + struct sinfonia_status_hdr *resphdr = (struct sinfonia_status_hdr *)resp; + + if ((ret = send_data(dev, endp_down, + cmd, cmdlen))) { + goto fail; + } + + ret = read_data(dev, endp_up, + (uint8_t *)resp, resplen, num); + + if (ret < 0) + goto fail; + + if (resphdr->result != RESULT_SUCCESS) { + INFO("Printer Status: %02x (%s)\n", resphdr->status, + sinfonia_status_str(resphdr->status)); + INFO(" Result: 0x%02x Error: 0x%02x (0x%02x/0x%02x = %s)\n", + resphdr->result, resphdr->error, resphdr->printer_major, + resphdr->printer_minor, usbh->error_codes(resphdr->printer_major, resphdr->printer_minor)); + goto fail; + } + + return 0; +fail: + ERROR("Failed to execute %s command\n", sinfonia_cmd_names(cmdhdr->cmd)); + return ret; +} + +int sinfonia_flashled(struct sinfonia_usbdev *usbh) +{ + struct sinfonia_cmd_hdr cmd; + struct sinfonia_status_hdr resp; + int ret, num = 0; + + cmd.cmd = cpu_to_le16(SINFONIA_CMD_FLASHLED); + cmd.len = cpu_to_le16(0); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + return 0; +} + +int sinfonia_canceljob(struct sinfonia_usbdev *usbh, int id) +{ + struct sinfonia_cancel_cmd cmd; + struct sinfonia_status_hdr resp; + int ret, num = 0; + + cmd.id = id; + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_CANCELJOB); + cmd.hdr.len = cpu_to_le16(1); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + return 0; +} + +int sinfonia_getparam(struct sinfonia_usbdev *usbh, int target, uint32_t *param) +{ + struct sinfonia_getparam_cmd cmd; + struct sinfonia_getparam_resp resp; + int ret, num = 0; + + /* Set up command */ + cmd.target = target; + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_GETPARAM); + cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_getparam_cmd)-sizeof(cmd.hdr)); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + } + *param = le32_to_cpu(resp.param); + + return ret; +} + +int sinfonia_setparam(struct sinfonia_usbdev *usbh, int target, uint32_t param) +{ + struct sinfonia_setparam_cmd cmd; + struct sinfonia_status_hdr resp; + int ret, num = 0; + + /* Set up command */ + cmd.target = target; + cmd.param = cpu_to_le32(param); + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_SETPARAM); + cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_setparam_cmd)-sizeof(cmd.hdr)); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + } + + return ret; +} + +int sinfonia_getfwinfo(struct sinfonia_usbdev *usbh) +{ + struct sinfonia_fwinfo_cmd cmd; + struct sinfonia_fwinfo_resp resp; + int num = 0; + int i; + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_FWINFO); + cmd.hdr.len = cpu_to_le16(1); + + resp.hdr.payload_len = 0; + + INFO("FW Information:\n"); + + for (i = FWINFO_TARGET_MAIN_BOOT ; i <= FWINFO_TARGET_PRINT_TABLES2 ; i++) { + int ret; + cmd.target = i; + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + continue; + } + + if (resp.major == 0) + continue; + + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_fwinfo_resp) - sizeof(struct sinfonia_status_hdr))) + continue; + + INFO(" %s\t ver %02x.%02x\n", sinfonia_fwinfo_targets(i), + resp.major, resp.minor); +#if 0 + INFO(" name: '%s'\n", resp.name); + INFO(" type: '%s'\n", resp.type); + INFO(" date: '%s'\n", resp.date); + INFO(" version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor, + le16_to_cpu(resp.checksum)); +#endif + } + return 0; +} + +int sinfonia_geterrorlog(struct sinfonia_usbdev *usbh) +{ + struct sinfonia_cmd_hdr cmd; + struct sinfonia_errorlog_resp resp; + int ret, num = 0; + int i; + + cmd.cmd = cpu_to_le16(SINFONIA_CMD_ERRORLOG); + cmd.len = cpu_to_le16(0); + + resp.hdr.payload_len = 0; + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_errorlog_resp) - sizeof(struct sinfonia_status_hdr))) + return -2; + + INFO("Stored Error Events: %u entries:\n", resp.count); + for (i = 0 ; i < resp.count ; i++) { + INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i, + le32_to_cpu(resp.items[i].print_counter), + resp.items[i].major, resp.items[i].minor, + usbh->error_codes(resp.items[i].major, resp.items[i].minor)); + } + return 0; +} + +int sinfonia_resetcurve(struct sinfonia_usbdev *usbh, int target, int id) +{ + struct sinfonia_reset_cmd cmd; + struct sinfonia_status_hdr resp; + int ret, num = 0; + + cmd.target = target; + cmd.curveid = id; + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_RESET); + cmd.hdr.len = cpu_to_le16(2); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + return 0; +} + +int sinfonia_gettonecurve(struct sinfonia_usbdev *usbh, int type, char *fname) +{ + struct sinfonia_readtone_cmd cmd; + struct sinfonia_readtone_resp resp; + int ret, num = 0; + + uint8_t *data; + uint16_t curves[TONE_CURVE_SIZE] = { 0 }; + + int i,j; + + cmd.target = type; + cmd.curveid = TONE_CURVE_ID; + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_READTONE); + cmd.hdr.len = cpu_to_le16(1); + + resp.hdr.payload_len = 0; + + INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname); + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_readtone_resp) - sizeof(struct sinfonia_status_hdr))) + return -2; + + resp.total_size = le16_to_cpu(resp.total_size); + + data = malloc(resp.total_size * 2); + if (!data) { + ERROR("Memory Allocation Failure!\n"); + return -1; + } + + i = 0; + while (i < resp.total_size) { + ret = read_data(usbh->dev, usbh->endp_up, + data + i, + resp.total_size * 2 - i, + &num); + if (ret < 0) + goto done; + i += num; + } + + i = j = 0; + while (i < resp.total_size) { + memcpy(curves + j, data + i+2, data[i+1]); + j += data[i+1] / 2; + i += data[i+1] + 2; + } + + /* Open file and write it out */ + { + int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); + if (tc_fd < 0) { + ret = -1; + goto done; + } + + for (i = 0 ; i < TONE_CURVE_SIZE; i++) { + /* Byteswap appropriately */ + curves[i] = cpu_to_be16(le16_to_cpu(curves[i])); + } + ret = write(tc_fd, curves, TONE_CURVE_SIZE * sizeof(uint16_t)); + close(tc_fd); + } + +done: + free(data); + return ret; +} + +int sinfonia_settonecurve(struct sinfonia_usbdev *usbh, int target, char *fname) +{ + struct sinfonia_update_cmd cmd; + struct sinfonia_status_hdr resp; + int ret, num = 0; + + INFO("Set %s Tone Curve from '%s'\n", sinfonia_update_targets(target), fname); + + uint16_t *data = malloc(TONE_CURVE_SIZE * sizeof(uint16_t)); + if (!data) { + ERROR("Memory Allocation Failure!\n"); + return -1; + } + + /* Read in file */ + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE * sizeof(uint16_t), NULL))) { + ERROR("Failed to read Tone Curve file\n"); + goto done; + } + + /* Byteswap data to local CPU.. */ + for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) { + data[ret] = be16_to_cpu(data[ret]); + } + + /* Set up command */ + cmd.target = target; + cmd.curve_id = TONE_CURVE_ID; + cmd.reserved[0] = cmd.reserved[1] = cmd.reserved[2] = 0; + cmd.reset = 0; + cmd.size = cpu_to_le32(TONE_CURVE_SIZE * sizeof(uint16_t)); + + cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_UPDATE); + cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_update_cmd)-sizeof(cmd.hdr)); + + /* Byteswap data to format printer is expecting.. */ + for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) { + data[ret] = cpu_to_le16(data[ret]); + } + + if ((ret = sinfonia_docmd(usbh, + (uint8_t*)&cmd, sizeof(cmd), + (uint8_t*)&resp, sizeof(resp), + &num)) < 0) { + return ret; + } + + /* Sent transfer */ + if ((ret = send_data(usbh->dev, usbh->endp_down, + (uint8_t *) data, TONE_CURVE_SIZE * sizeof(uint16_t)))) { + goto done; + } + +done: + free(data); + + return ret; +} + +const char *sinfonia_update_targets (uint8_t v) { + switch (v) { + case UPDATE_TARGET_USER: + return "User"; + case UPDATE_TARGET_CURRENT: + return "Current"; + default: + return "Unknown"; + } +} + +const char *sinfonia_tonecurve_statuses (uint8_t v) +{ + switch(v) { + case 0: + return "Initial"; + case 1: + return "UserSet"; + case 2: + return "Current"; + default: + return "Unknown"; + } +} + +const char *sinfonia_bank_statuses(uint8_t v) +{ + switch (v) { + case BANK_STATUS_FREE: + return "Free"; + case BANK_STATUS_XFER: + return "Xfer"; + case BANK_STATUS_FULL: + return "Full"; + case BANK_STATUS_PRINTING: + return "Printing"; + default: + return "Unknown"; + } +} + +const char *sinfonia_error_str(uint8_t v) { + switch (v) { + case ERROR_NONE: + return "None"; + case ERROR_INVALID_PARAM: + return "Invalid Command Parameter"; + case ERROR_MAIN_APP_INACTIVE: + return "Main App Inactive"; + case ERROR_COMMS_TIMEOUT: + return "Main Communication Timeout"; + case ERROR_MAINT_NEEDED: + return "Maintenance Needed"; + case ERROR_BAD_COMMAND: + return "Inappropriate Command"; + case ERROR_PRINTER: + return "Printer Error"; + case ERROR_BUFFER_FULL: + return "Buffer Full"; + default: + return "Unknown"; + } +} + +const char *sinfonia_media_types(uint8_t v) { + switch (v) { + case MEDIA_TYPE_UNKNOWN: + return "Unknown"; + case MEDIA_TYPE_PAPER: + return "Paper"; + default: + return "Unknown"; + } +} + +const char *sinfonia_print_methods (uint8_t v) { + switch (v & 0xf) { + case PRINT_METHOD_STD: + return "Standard"; + case PRINT_METHOD_COMBO_2: + return "2up"; + case PRINT_METHOD_COMBO_3: + return "3up"; + case PRINT_METHOD_SPLIT: + return "Split"; + case PRINT_METHOD_DOUBLE: + return "Double"; + default: + return "Unknown"; + } +} + +const char *sinfonia_print_modes(uint8_t v) { + switch (v) { + case PRINT_MODE_NO_OC: + return "No Overcoat"; + case PRINT_MODE_GLOSSY: + return "Glossy"; + case PRINT_MODE_MATTE: + return "Matte"; + default: + return "Unknown"; + } +} + +const char *sinfonia_fwinfo_targets (uint8_t v) { + switch (v) { + case FWINFO_TARGET_MAIN_BOOT: + return "Main Boot "; + case FWINFO_TARGET_MAIN_APP: + return "Main App "; + case FWINFO_TARGET_PRINT_TABLES: + case FWINFO_TARGET_PRINT_TABLES2: // Seen on EK70xx + return "Print Tables"; + case FWINFO_TARGET_DSP: + return "DSP "; + case FWINFO_TARGET_USB: + return "USB "; + default: + return "Unknown "; + } +} + +const char *sinfonia_print_codes (uint8_t v, int eightinch) { + if (eightinch) { + switch (v) { + case CODE_8x10: + return "8x10"; + case CODE_8x12: + case CODE_8x12K: + return "8x12"; + case CODE_8x4: + return "8x4"; + case CODE_8x5: + return "8x5"; + case CODE_8x6: + return "8x6"; + case CODE_8x8: + return "8x8"; + case CODE_8x4_2: + return "8x4*2"; + case CODE_8x5_2: + return "8x5*2"; + case CODE_8x6_2: + return "8x6*2"; + case CODE_8x4_3: + return "8x4*3"; + default: + return "Unknown"; + } + } + + switch (v) { + case CODE_4x6: + return "4x6"; + case CODE_3_5x5: + return "3.5x5"; + case CODE_5x7: + return "5x7"; + case CODE_6x9: + return "6x9"; + case CODE_6x8: + return "6x8"; + case CODE_2x6: + return "2x6"; + case CODE_6x6: + return "6x6"; + case CODE_89x60mm: + return "89x60mm"; + case CODE_89x59mm: + return "89x59mm"; + case CODE_89x58mm: + return "89x58mm"; + case CODE_89x57mm: + return "89x57mm"; + case CODE_89x56mm: + return "89x56mm"; + case CODE_89x55mm: + return "89x55mm"; + default: + return "Unknown"; + } +} + +const char *sinfonia_status_str(uint8_t v) { + switch (v) { + case STATUS_READY: + return "Ready"; + case STATUS_INIT_CPU: + return "Initializing CPU"; + case STATUS_INIT_RIBBON: + return "Initializing Ribbon"; + case STATUS_INIT_PAPER: + return "Loading Paper"; + case STATUS_THERMAL_PROTECT: + return "Thermal Protection"; + case STATUS_USING_PANEL: + return "Using Operation Panel"; + case STATUS_SELF_DIAG: + return "Processing Self Diagnosis"; + case STATUS_DOWNLOADING: + return "Processing Download"; + case STATUS_FEEDING_PAPER: + return "Feeding Paper"; + case STATUS_PRE_HEAT: + return "Pre-Heating"; + case STATUS_PRINT_Y: + return "Printing Yellow"; + case STATUS_BACK_FEED_Y: + return "Back-Feeding - Yellow Complete"; + case STATUS_PRINT_M: + return "Printing Magenta"; + case STATUS_BACK_FEED_M: + return "Back-Feeding - Magenta Complete"; + case STATUS_PRINT_C: + return "Printing Cyan"; + case STATUS_BACK_FEED_C: + return "Back-Feeding - Cyan Complete"; + case STATUS_PRINT_OP: + return "Laminating"; + case STATUS_PAPER_CUT: + return "Cutting Paper"; + case STATUS_PAPER_EJECT: + return "Ejecting Paper"; + case STATUS_BACK_FEED_E: + return "Back-Feeding - Ejected"; + case STATUS_FINISHED: + return "Print Finished"; + case ERROR_PRINTER: + return "Printer Error"; + default: + return "Unknown"; + } +} + +const char *sinfonia_cmd_names(uint16_t v) { + switch (le16_to_cpu(v)) { + case SINFONIA_CMD_GETSTATUS: + return "Get Status"; + case SINFONIA_CMD_MEDIAINFO: + return "Get Media Info"; + case SINFONIA_CMD_MODELNAME: + return "Get Model Name"; + case SINFONIA_CMD_ERRORLOG: + return "Get Error Log"; + case SINFONIA_CMD_GETPARAM: + return "Get Parameter"; + case SINFONIA_CMD_GETSERIAL: + return "Get Serial Number"; + case SINFONIA_CMD_PRINTSTAT: + return "Get Print ID Status"; + case SINFONIA_CMD_EXTCOUNTER: + return "Get Extended Counters"; + case SINFONIA_CMD_PRINTJOB: + return "Print"; + case SINFONIA_CMD_CANCELJOB: + return "Cancel Print"; + case SINFONIA_CMD_FLASHLED: + return "Flash LEDs"; + case SINFONIA_CMD_RESET: + return "Reset"; + case SINFONIA_CMD_READTONE: + return "Read Tone Curve"; + case SINFONIA_CMD_BUTTON: + return "Button Enable"; + case SINFONIA_CMD_SETPARAM: + return "Set Parameter"; + case SINFONIA_CMD_GETUNIQUE: + return "Get Unique String"; + case SINFONIA_CMD_GETCORR: + return "Get Image Correction Parameter"; + case SINFONIA_CMD_GETEEPROM: + return "Get EEPROM Backup Parameter"; + case SINFONIA_CMD_SETEEPROM: + return "Set EEPROM Backup Parameter"; + case SINFONIA_CMD_SETTIME: + return "Time Setting"; + case SINFONIA_CMD_DIAGNOSTIC: + return "Diagnostic"; + case SINFONIA_CMD_FWINFO: + return "Get Firmware Info"; + case SINFONIA_CMD_UPDATE: + return "Update"; + case SINFONIA_CMD_SETUNIQUE: + return "Set Unique String"; + default: + return "Unknown Command"; + } +} + +const char *kodak6_mediatypes(int type) +{ + switch(type) { + case KODAK6_MEDIA_NONE: + return "No media"; + case KODAK6_MEDIA_6R: + case KODAK6_MEDIA_6TR2: + case KODAK7_MEDIA_6R: + return "Kodak 6R"; + + default: + return "Unknown"; + } + return "Unknown"; +} + +void kodak6_dumpmediacommon(int type) +{ + switch (type) { + case KODAK6_MEDIA_6R: + INFO("Media type: 6R (Kodak 197-4096 or equivalent)\n"); + break; + case KODAK6_MEDIA_6TR2: + INFO("Media type: 6R (Kodak 396-2941 or equivalent)\n"); + break; + case KODAK7_MEDIA_6R: + INFO("Media type: 6R (Kodak 659-9047 or equivalent)\n"); + break; + default: + INFO("Media type %02x (unknown, please report!)\n", type); + break; + } +} + +/* Below are for S1145 (EK68xx) and S1245 only! */ +const char *sinfonia_1x45_status_str(uint8_t status1, uint32_t status2, uint8_t error) +{ + switch(status1) { + case STATE_STATUS1_STANDBY: + return "Standby (Ready)"; + case STATE_STATUS1_WAIT: + switch (status2) { + case WAIT_STATUS2_INIT: + return "Wait (Initializing)"; + case WAIT_STATUS2_RIBBON: + return "Wait (Ribbon Winding)"; + case WAIT_STATUS2_THERMAL: + return "Wait (Thermal Protection)"; + case WAIT_STATUS2_OPERATING: + return "Wait (Operating)"; + case WAIT_STATUS2_BUSY: + return "Wait (Busy)"; + default: + return "Wait (Unknown)"; + } + case STATE_STATUS1_ERROR: + switch (status2) { + case ERROR_STATUS2_CTRL_CIRCUIT: + switch (error) { + case CTRL_CIR_ERROR_EEPROM1: + return "Error (EEPROM1)"; + case CTRL_CIR_ERROR_EEPROM2: + return "Error (EEPROM2)"; + case CTRL_CIR_ERROR_DSP: + return "Error (DSP)"; + case CTRL_CIR_ERROR_CRC_MAIN: + return "Error (Main CRC)"; + case CTRL_CIR_ERROR_DL_MAIN: + return "Error (Main Download)"; + case CTRL_CIR_ERROR_CRC_DSP: + return "Error (DSP CRC)"; + case CTRL_CIR_ERROR_DL_DSP: + return "Error (DSP Download)"; + case CTRL_CIR_ERROR_ASIC: + return "Error (ASIC)"; + case CTRL_CIR_ERROR_DRAM: + return "Error (DRAM)"; + case CTRL_CIR_ERROR_DSPCOMM: + return "Error (DSP Communincation)"; + default: + return "Error (Unknown Circuit)"; + } + case ERROR_STATUS2_MECHANISM_CTRL: + switch (error) { + case MECH_ERROR_HEAD_UP: + return "Error (Head Up Mechanism)"; + case MECH_ERROR_HEAD_DOWN: + return "Error (Head Down Mechanism)"; + case MECH_ERROR_MAIN_PINCH_UP: + return "Error (Main Pinch Up Mechanism)"; + case MECH_ERROR_MAIN_PINCH_DOWN: + return "Error (Main Pinch Down Mechanism)"; + case MECH_ERROR_SUB_PINCH_UP: + return "Error (Sub Pinch Up Mechanism)"; + case MECH_ERROR_SUB_PINCH_DOWN: + return "Error (Sub Pinch Down Mechanism)"; + case MECH_ERROR_FEEDIN_PINCH_UP: + return "Error (Feed-in Pinch Up Mechanism)"; + case MECH_ERROR_FEEDIN_PINCH_DOWN: + return "Error (Feed-in Pinch Down Mechanism)"; + case MECH_ERROR_FEEDOUT_PINCH_UP: + return "Error (Feed-out Pinch Up Mechanism)"; + case MECH_ERROR_FEEDOUT_PINCH_DOWN: + return "Error (Feed-out Pinch Down Mechanism)"; + case MECH_ERROR_CUTTER_LR: + return "Error (Left->Right Cutter)"; + case MECH_ERROR_CUTTER_RL: + return "Error (Right->Left Cutter)"; + default: + return "Error (Unknown Mechanism)"; + } + case ERROR_STATUS2_SENSOR: + switch (error) { + case SENSOR_ERROR_CUTTER: + return "Error (Cutter Sensor)"; + case SENSOR_ERROR_HEAD_DOWN: + return "Error (Head Down Sensor)"; + case SENSOR_ERROR_HEAD_UP: + return "Error (Head Up Sensor)"; + case SENSOR_ERROR_MAIN_PINCH_DOWN: + return "Error (Main Pinch Down Sensor)"; + case SENSOR_ERROR_MAIN_PINCH_UP: + return "Error (Main Pinch Up Sensor)"; + case SENSOR_ERROR_FEED_PINCH_DOWN: + return "Error (Feed Pinch Down Sensor)"; + case SENSOR_ERROR_FEED_PINCH_UP: + return "Error (Feed Pinch Up Sensor)"; + case SENSOR_ERROR_EXIT_PINCH_DOWN: + return "Error (Exit Pinch Up Sensor)"; + case SENSOR_ERROR_EXIT_PINCH_UP: + return "Error (Exit Pinch Up Sensor)"; + case SENSOR_ERROR_LEFT_CUTTER: + return "Error (Left Cutter Sensor)"; + case SENSOR_ERROR_RIGHT_CUTTER: + return "Error (Right Cutter Sensor)"; + case SENSOR_ERROR_CENTER_CUTTER: + return "Error (Center Cutter Sensor)"; + case SENSOR_ERROR_UPPER_CUTTER: + return "Error (Upper Cutter Sensor)"; + case SENSOR_ERROR_PAPER_FEED_COVER: + return "Error (Paper Feed Cover)"; + default: + return "Error (Unknown Sensor)"; + } + case ERROR_STATUS2_COVER_OPEN: + switch (error) { + case COVER_OPEN_ERROR_UPPER: + return "Error (Upper Cover Open)"; + case COVER_OPEN_ERROR_LOWER: + return "Error (Lower Cover Open)"; + default: + return "Error (Unknown Cover Open)"; + } + case ERROR_STATUS2_TEMP_SENSOR: + switch (error) { + case TEMP_SENSOR_ERROR_HEAD_HIGH: + return "Error (Head Temperature High)"; + case TEMP_SENSOR_ERROR_HEAD_LOW: + return "Error (Head Temperature Low)"; + case TEMP_SENSOR_ERROR_ENV_HIGH: + return "Error (Environmental Temperature High)"; + case TEMP_SENSOR_ERROR_ENV_LOW: + return "Error (Environmental Temperature Low)"; + default: + return "Error (Unknown Temperature)"; + } + case ERROR_STATUS2_PAPER_JAM: + return "Error (Paper Jam)"; + case ERROR_STATUS2_PAPER_EMPTY: + return "Error (Paper Empty)"; + case ERROR_STATUS2_RIBBON_ERR: + return "Error (Ribbon)"; + default: + return "Error (Unknown)"; + } + default: + return "Unknown!"; + } +} diff --git a/src/cups/backend_sinfonia.h b/src/cups/backend_sinfonia.h new file mode 100644 index 0000000..9f8030e --- /dev/null +++ b/src/cups/backend_sinfonia.h @@ -0,0 +1,562 @@ + /* + * Shinko/Sinfonia Common Code + * + * (c) 2019 Solomon Peachy <pizza@shaftnet.org> + * + * The latest version of this program can be found at: + * + * http://git.shaftnet.org/cgit/selphy_print.git + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * [http://www.gnu.org/licenses/gpl-2.0.html] + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#define LIBSINFONIA_VER "0.08" + +#define SINFONIA_HDR1_LEN 0x10 +#define SINFONIA_HDR2_LEN 0x64 +#define SINFONIA_HDR_LEN (SINFONIA_HDR1_LEN + SINFONIA_HDR2_LEN) +#define SINFONIA_DPI 300 + +struct sinfonia_job_param { + uint32_t columns; + uint32_t rows; + uint32_t copies; + + uint32_t method; + uint32_t media; + uint32_t oc_mode; + + uint32_t quality; + + int mattedepth; + uint32_t dust; + + uint32_t ext_flags; +}; + +struct sinfonia_printjob { + struct sinfonia_job_param jp; + + uint8_t *databuf; + int datalen; + int copies; +}; + +int sinfonia_read_parse(int data_fd, uint32_t model, + struct sinfonia_printjob *job); + +int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job); +int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job); +int sinfonia_raw28_read_parse(int data_fd, struct sinfonia_printjob *job); +void sinfonia_cleanup_job(const void *vjob); + +/* Common usb functions */ +struct sinfonia_usbdev { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + int type; + + char const *(*error_codes)(uint8_t major, uint8_t minor); +}; +int sinfonia_docmd(struct sinfonia_usbdev *usbh, + uint8_t *cmd, int cmdlen, + uint8_t *resp, int resplen, + int *num); +int sinfonia_flashled(struct sinfonia_usbdev *usbh); +int sinfonia_canceljob(struct sinfonia_usbdev *usbh, int id); +int sinfonia_getparam(struct sinfonia_usbdev *usbh, int target, uint32_t *param); +int sinfonia_setparam(struct sinfonia_usbdev *usbh, int target, uint32_t param); +int sinfonia_getfwinfo(struct sinfonia_usbdev *usbh); +int sinfonia_geterrorlog(struct sinfonia_usbdev *usbh); +int sinfonia_resetcurve(struct sinfonia_usbdev *usbh, int target, int id); +int sinfonia_gettonecurve(struct sinfonia_usbdev *usbh, int type, char *fname); +int sinfonia_settonecurve(struct sinfonia_usbdev *usbh, int target, char *fname); + +#define BANK_STATUS_FREE 0x00 +#define BANK_STATUS_XFER 0x01 +#define BANK_STATUS_FULL 0x02 +#define BANK_STATUS_PRINTING 0x12 /* Not on S2145 */ + +const char *sinfonia_bank_statuses(uint8_t v); + +#define UPDATE_TARGET_USER 0x03 +#define UPDATE_TARGET_CURRENT 0x04 + +/* Update is three channels, Y, M, C; + each is 256 entries of 11-bit data padded to 16-bits. + Printer expects LE data. We use BE data on disk. +*/ +#define TONE_CURVE_SIZE 0x600 +const char *sinfonia_update_targets (uint8_t v); + +#define TONECURVE_INIT 0x00 +#define TONECURVE_USER 0x01 +#define TONECURVE_CURRENT 0x02 + +const char *sinfonia_tonecurve_statuses (uint8_t v); + +struct sinfonia_error_item { + uint8_t major; + uint8_t minor; + uint32_t print_counter; +} __attribute__((packed)); + +#define ERROR_NONE 0x00 +#define ERROR_INVALID_PARAM 0x01 +#define ERROR_MAIN_APP_INACTIVE 0x02 +#define ERROR_COMMS_TIMEOUT 0x03 +#define ERROR_MAINT_NEEDED 0x04 +#define ERROR_BAD_COMMAND 0x05 +#define ERROR_PRINTER 0x11 +#define ERROR_BUFFER_FULL 0x21 + +const char *sinfonia_error_str(uint8_t v); + +enum { + MEDIA_TYPE_UNKNOWN = 0x00, + MEDIA_TYPE_PAPER = 0x01, +}; + +const char *sinfonia_media_types(uint8_t v); + +#define PRINT_MODE_NO_OC 0x01 +#define PRINT_MODE_GLOSSY 0x02 +#define PRINT_MODE_MATTE 0x03 +const char *sinfonia_print_modes(uint8_t v); + +#define PRINT_METHOD_STD 0x00 +#define PRINT_METHOD_COMBO_2 0x02 +#define PRINT_METHOD_COMBO_3 0x03 // S6245 only +#define PRINT_METHOD_SPLIT 0x04 +#define PRINT_METHOD_DOUBLE 0x08 // S6145 only +#define PRINT_METHOD_DISABLE_ERR 0x10 // S6245 only +#define PRINT_METHOD_NOTRIM 0x80 // S6145 only + +const char *sinfonia_print_methods (uint8_t v); + +#define FWINFO_TARGET_MAIN_BOOT 0x01 +#define FWINFO_TARGET_MAIN_APP 0x02 +#define FWINFO_TARGET_PRINT_TABLES 0x03 +#define FWINFO_TARGET_DSP 0x04 +#define FWINFO_TARGET_USB 0x06 +#define FWINFO_TARGET_PRINT_TABLES2 0x07 + +const char *sinfonia_fwinfo_targets (uint8_t v); + +/* Common command structs */ +struct sinfonia_cmd_hdr { + uint16_t cmd; + uint16_t len; /* Not including this header */ +} __attribute__((packed)); + +struct sinfonia_status_hdr { + uint8_t result; + uint8_t error; + uint8_t printer_major; + uint8_t printer_minor; + uint8_t reserved[2]; + uint8_t mode; /* S6245 and EK605 only, so far */ + uint8_t status; + uint16_t payload_len; +} __attribute__((packed)); + +struct sinfonia_cancel_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t id; +} __attribute__((packed)); + +struct sinfonia_fwinfo_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; +} __attribute__((packed)); + +struct sinfonia_fwinfo_resp { + struct sinfonia_status_hdr hdr; + uint8_t name[8]; + uint8_t type[16]; + uint8_t date[10]; + uint8_t major; + uint8_t minor; + uint16_t checksum; +} __attribute__((packed)); + +struct sinfonia_errorlog_resp { + struct sinfonia_status_hdr hdr; + uint8_t count; + struct sinfonia_error_item items[10]; /* Not all necessarily used */ +} __attribute__((packed)); + +struct sinfonia_mediainfo_item { + uint8_t code; + uint16_t columns; + uint16_t rows; + uint8_t type; /* S2145, EK68xx, EK605 only -- MEDIA_TYPE_* */ + uint8_t method; /* PRINT_METHOD_* */ + uint8_t flag; /* EK68xx only */ + uint8_t reserved[2]; +} __attribute__((packed)); + +struct sinfonia_setparam_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; + uint32_t param; +} __attribute__((packed)); + +struct sinfonia_diagnostic_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t arg1; + uint8_t arg2; + uint8_t arg3; +} __attribute__((packed)); + +struct sinfonia_getparam_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; +} __attribute__((packed)); + +struct sinfonia_getparam_resp { + struct sinfonia_status_hdr hdr; + uint32_t param; +} __attribute__((packed)); + +struct sinfonia_getprintidstatus_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t id; +} __attribute__((packed)); + +struct sinfonia_getprintidstatus_resp { + struct sinfonia_status_hdr hdr; + uint8_t id; + uint16_t remaining; + uint16_t finished; + uint16_t specified; + uint16_t status; +} __attribute__((packed)); + +#define IDSTATUS_WAITING 0x0000 +#define IDSTATUS_PRINTING 0x0100 +#define IDSTATUS_COMPLETED 0x0200 +#define IDSTATUS_ERROR 0xFFFF + +struct sinfonia_reset_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; + uint8_t curveid; +} __attribute__((packed)); + +#define RESET_PRINTER 0x03 +#define RESET_TONE_CURVE 0x04 + +#define TONE_CURVE_ID 0x01 + +struct sinfonia_readtone_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; + uint8_t curveid; +} __attribute__((packed)); + +#define READ_TONE_CURVE_USER 0x01 +#define READ_TONE_CURVE_CURR 0x02 + +struct sinfonia_readtone_resp { + struct sinfonia_status_hdr hdr; + uint16_t total_size; +} __attribute__((packed)); + +struct sinfonia_update_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t target; + uint8_t curve_id; + uint8_t reset; // ?? + uint8_t reserved[3]; + uint32_t size; +} __attribute__((packed)); + +struct sinfonia_getserial_resp { + struct sinfonia_status_hdr hdr; + uint8_t data[8]; +} __attribute__((packed)); + +struct sinfonia_getextcounter_resp { + struct sinfonia_status_hdr hdr; + uint32_t lifetime_distance; /* Inches */ + uint32_t maint_distance; + uint32_t head_distance; + uint8_t reserved[32]; +} __attribute__((packed)); + +struct sinfonia_seteeprom_cmd { + struct sinfonia_cmd_hdr hdr; + uint8_t data[256]; /* Maxlen */ +} __attribute__((packed)); + +struct sinfonia_printcmd10_hdr { + struct sinfonia_cmd_hdr hdr; + uint8_t jobid; + uint16_t copies; + uint16_t columns; + uint16_t rows; + uint8_t media; + uint8_t oc_mode; + uint8_t method; +} __attribute__((packed)); + +struct sinfonia_printcmd18_hdr { + struct sinfonia_cmd_hdr hdr; + uint8_t jobid; + uint16_t copies; + uint16_t columns; + uint16_t rows; + uint8_t reserved[8]; // columns and rows repeated, then nulls + uint8_t oc_mode; + uint8_t method; + uint8_t media; // reserved? +} __attribute__((packed)); + +struct sinfonia_printcmd28_hdr { + struct sinfonia_cmd_hdr hdr; + uint8_t jobid; + uint16_t copies; + uint16_t columns; + uint16_t rows; + uint8_t media; + uint8_t reserved[7]; + uint8_t options; + uint8_t method; + uint8_t reserved2[11]; +} __attribute__((packed)); + +#define CODE_4x6 0x00 +#define CODE_3_5x5 0x01 +#define CODE_5x7 0x03 +#define CODE_6x9 0x05 +#define CODE_6x8 0x06 +#define CODE_2x6 0x07 +#define CODE_6x6 0x08 + +#define CODE_8x10 0x10 +#define CODE_8x12 0x11 +#define CODE_8x4 0x20 +#define CODE_8x5 0x21 +#define CODE_8x6 0x22 +#define CODE_8x8 0x23 +#define CODE_8x4_2 0x30 +#define CODE_8x5_2 0x31 +#define CODE_8x6_2 0x32 +#define CODE_8x4_3 0x40 + +#define CODE_8x12K 0x02 /* Kodak 8810 */ + + +#define CODE_89x60mm 0x10 +#define CODE_89x59mm 0x11 +#define CODE_89x58mm 0x12 +#define CODE_89x57mm 0x13 +#define CODE_89x56mm 0x14 +#define CODE_89x55mm 0x15 + +const char *sinfonia_print_codes (uint8_t v, int eightinch); + +#define STATUS_READY 0x00 +#define STATUS_INIT_CPU 0x31 +#define STATUS_INIT_RIBBON 0x32 +#define STATUS_INIT_PAPER 0x33 +#define STATUS_THERMAL_PROTECT 0x34 +#define STATUS_USING_PANEL 0x35 +#define STATUS_SELF_DIAG 0x36 +#define STATUS_DOWNLOADING 0x37 + +#define STATUS_FEEDING_PAPER 0x61 +#define STATUS_PRE_HEAT 0x62 +#define STATUS_PRINT_Y 0x63 +#define STATUS_BACK_FEED_Y 0x64 +#define STATUS_PRINT_M 0x65 +#define STATUS_BACK_FEED_M 0x66 +#define STATUS_PRINT_C 0x67 +#define STATUS_BACK_FEED_C 0x68 +#define STATUS_PRINT_OP 0x69 +#define STATUS_PAPER_CUT 0x6A +#define STATUS_PAPER_EJECT 0x6B +#define STATUS_BACK_FEED_E 0x6C +#define STATUS_FINISHED 0x6D + +const char *sinfonia_status_str(uint8_t v); + +#define SINFONIA_CMD_GETSTATUS 0x0001 +#define SINFONIA_CMD_MEDIAINFO 0x0002 +#define SINFONIA_CMD_MODELNAME 0x0003 // 2145 only +#define SINFONIA_CMD_ERRORLOG 0x0004 +#define SINFONIA_CMD_GETPARAM 0x0005 // !2145 +#define SINFONIA_CMD_GETSERIAL 0x0006 // !2145 +#define SINFONIA_CMD_PRINTSTAT 0x0007 // !2145 +#define SINFONIA_CMD_EXTCOUNTER 0x0008 // !2145 + +#define SINFONIA_CMD_MEMORYBANK 0x000A // Brava 21 only? + +#define SINFONIA_CMD_PRINTJOB 0x4001 +#define SINFONIA_CMD_CANCELJOB 0x4002 +#define SINFONIA_CMD_FLASHLED 0x4003 +#define SINFONIA_CMD_RESET 0x4004 +#define SINFONIA_CMD_READTONE 0x4005 +#define SINFONIA_CMD_BUTTON 0x4006 // 2145 only +#define SINFONIA_CMD_SETPARAM 0x4007 + +#define SINFONIA_CMD_GETUNIQUE 0x8003 // 2145 only + +#define SINFONIA_CMD_GETCORR 0x400D +#define SINFONIA_CMD_GETEEPROM 0x400E +#define SINFONIA_CMD_SETEEPROM 0x400F +#define SINFONIA_CMD_SETTIME 0x4011 // 6245 only + +#define SINFONIA_CMD_DIAGNOSTIC 0xC001 // ?? +#define SINFONIA_CMD_FWINFO 0xC003 +#define SINFONIA_CMD_UPDATE 0xC004 +#define SINFONIA_CMD_SETUNIQUE 0xC007 // 2145 only + +const char *sinfonia_cmd_names(uint16_t v); + +//#define KODAK6_MEDIA_5R // 189-9160 +#define KODAK6_MEDIA_6R 0x0b // 197-4096 [ Also: 101-0867, 141-9597, 659-9054, 169-6418, DNP-900-060 ] +#define KODAK6_MEDIA_UNK 0x03 // ??? reported but unknown +#define KODAK6_MEDIA_6TR2 0x2c // 396-2941 +//#define KODAK6_MEDIA_5FR2 // 6900-compatible +//#define KODAK6_MEDIA_6FR2 // 6900-compatible, 102-5925 +#define KODAK6_MEDIA_NONE 0x00 +//#define KODAK7_MEDIA_5R // 164-9011 137-0600 +#define KODAK7_MEDIA_6R 0x29 // 659-9047 166-1925 396-2966 846-2004 103-7688 DNP-900-070 -- ALSO FUJI R68-D2P570 16578944 +//#define KODAK7_MEDIA_6TA2 +//#define KODAK7_MEDIA_5TA2 + +const char *kodak6_mediatypes(int type); +void kodak6_dumpmediacommon(int type); + +#define RESULT_SUCCESS 0x01 +#define RESULT_FAIL 0x02 + +/* ********** Below are for the old S1145 (EK68xx) and S1245 only! */ + +enum { + CMD_CODE_OK = 1, + CMD_CODE_BAD = 2, +}; + +enum { + STATUS_PRINTING = 1, + STATUS_IDLE = 2, +}; + +enum { + STATE_STATUS1_STANDBY = 1, + STATE_STATUS1_ERROR = 2, + STATE_STATUS1_WAIT = 3, +}; + +#define STATE_STANDBY_STATUS2 0x0 + +enum { + WAIT_STATUS2_INIT = 0, + WAIT_STATUS2_RIBBON = 1, + WAIT_STATUS2_THERMAL = 2, + WAIT_STATUS2_OPERATING = 3, + WAIT_STATUS2_BUSY = 4, +}; + +#define ERROR_STATUS2_CTRL_CIRCUIT (0x80000000) +#define ERROR_STATUS2_MECHANISM_CTRL (0x40000000) +#define ERROR_STATUS2_SENSOR (0x00002000) +#define ERROR_STATUS2_COVER_OPEN (0x00001000) +#define ERROR_STATUS2_TEMP_SENSOR (0x00000200) +#define ERROR_STATUS2_PAPER_JAM (0x00000100) +#define ERROR_STATUS2_PAPER_EMPTY (0x00000040) +#define ERROR_STATUS2_RIBBON_ERR (0x00000010) + +enum { + CTRL_CIR_ERROR_EEPROM1 = 0x01, + CTRL_CIR_ERROR_EEPROM2 = 0x02, + CTRL_CIR_ERROR_DSP = 0x04, + CTRL_CIR_ERROR_CRC_MAIN = 0x06, + CTRL_CIR_ERROR_DL_MAIN = 0x07, + CTRL_CIR_ERROR_CRC_DSP = 0x08, + CTRL_CIR_ERROR_DL_DSP = 0x09, + CTRL_CIR_ERROR_ASIC = 0x0a, + CTRL_CIR_ERROR_DRAM = 0x0b, + CTRL_CIR_ERROR_DSPCOMM = 0x29, +}; + +enum { + MECH_ERROR_HEAD_UP = 0x01, + MECH_ERROR_HEAD_DOWN = 0x02, + MECH_ERROR_MAIN_PINCH_UP = 0x03, + MECH_ERROR_MAIN_PINCH_DOWN = 0x04, + MECH_ERROR_SUB_PINCH_UP = 0x05, + MECH_ERROR_SUB_PINCH_DOWN = 0x06, + MECH_ERROR_FEEDIN_PINCH_UP = 0x07, + MECH_ERROR_FEEDIN_PINCH_DOWN = 0x08, + MECH_ERROR_FEEDOUT_PINCH_UP = 0x09, + MECH_ERROR_FEEDOUT_PINCH_DOWN = 0x0a, + MECH_ERROR_CUTTER_LR = 0x0b, + MECH_ERROR_CUTTER_RL = 0x0c, +}; + +enum { + SENSOR_ERROR_CUTTER = 0x05, + SENSOR_ERROR_HEAD_DOWN = 0x09, + SENSOR_ERROR_HEAD_UP = 0x0a, + SENSOR_ERROR_MAIN_PINCH_DOWN = 0x0b, + SENSOR_ERROR_MAIN_PINCH_UP = 0x0c, + SENSOR_ERROR_FEED_PINCH_DOWN = 0x0d, + SENSOR_ERROR_FEED_PINCH_UP = 0x0e, + SENSOR_ERROR_EXIT_PINCH_DOWN = 0x0f, + SENSOR_ERROR_EXIT_PINCH_UP = 0x10, + SENSOR_ERROR_LEFT_CUTTER = 0x11, + SENSOR_ERROR_RIGHT_CUTTER = 0x12, + SENSOR_ERROR_CENTER_CUTTER = 0x13, + SENSOR_ERROR_UPPER_CUTTER = 0x14, + SENSOR_ERROR_PAPER_FEED_COVER = 0x15, +}; + +enum { + TEMP_SENSOR_ERROR_HEAD_HIGH = 0x01, + TEMP_SENSOR_ERROR_HEAD_LOW = 0x02, + TEMP_SENSOR_ERROR_ENV_HIGH = 0x03, + TEMP_SENSOR_ERROR_ENV_LOW = 0x04, +}; + +enum { + COVER_OPEN_ERROR_UPPER = 0x01, + COVER_OPEN_ERROR_LOWER = 0x02, +}; + +enum { + PAPER_EMPTY_ERROR = 0x00, +}; + +enum { + RIBBON_ERROR = 0x00, +}; + +enum { + CURVE_TABLE_STATUS_INITIAL = 0x00, + CURVE_TABLE_STATUS_USERSET = 0x01, + CURVE_TABLE_STATUS_CURRENT = 0x02, +}; + +const char *sinfonia_1x45_status_str(uint8_t status1, uint32_t status2, uint8_t error); diff --git a/src/cups/backend_sonyupd.c b/src/cups/backend_sonyupd.c new file mode 100644 index 0000000..1180039 --- /dev/null +++ b/src/cups/backend_sonyupd.c @@ -0,0 +1,1024 @@ +/* + * Sony UP-D series Photo Printer CUPS backend -- libusb-1.0 version + * + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> + * + * The latest version of this program can be found at: + * + * http://git.shaftnet.org/cgit/selphy_print.git + * + * 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 <https://www.gnu.org/licenses/>. + * + * [http://www.gnu.org/licenses/gpl-2.0.html] + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> + +#define BACKEND sonyupd_backend + +#include "backend_common.h" + +/* Printer status + --> 1b e0 00 00 00 00 XX 00 [[ XX is 0xe on UPD895, 0xf on others ]] + <-- this struct +*/ +struct sony_updsts { + uint8_t len; /* 0x0d/0x0e (ie number of bytes AFTER this one) */ + uint8_t zero1; /* 0x00 */ + uint8_t printing; /* UPD_PRINTING_* */ + uint8_t remain; /* Number of remaining pages */ + uint8_t zero2; + uint8_t sts1; /* UPD_STS1_* */ + uint8_t sts2; /* seconday status */ + uint8_t sts3; /* tertiary status */ + uint16_t unk; /* seen 0x04a0 UP-CR10L, 0x04a8 on UP-DR150 */ + uint16_t max_cols; /* BE */ + uint16_t max_rows; /* BE */ + uint8_t percent; /* 0-99, if job is printing (UP-D89x) */ +} __attribute__((packed)); + +#define UPD_PRINTING_BW 0xe0 /* UPD-895/897 only */ +#define UPD_PRINTING_Y 0x40 +#define UPD_PRINTING_M 0x80 +#define UPD_PRINTING_C 0xc0 +#define UPD_PRINTING_O 0x20 +#define UPD_PRINTING_IDLE 0x00 + +#define UPD_STS1_IDLE 0x00 +#define UPD_STS1_DOOROPEN 0x08 +#define UPD_STS1_NOPAPER 0x40 +#define UPD_STS1_PRINTING 0x80 + +/* Private data structures */ +struct upd_printjob { + uint8_t *databuf; + int datalen; + + int copies; + uint16_t rows; + uint16_t cols; + uint32_t imglen; +}; + +struct upd_ctx { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + int type; + + int native_bpp; + + struct sony_updsts stsbuf; + + struct marker marker; +}; + +/* Now for the code */ +static void* upd_init(void) +{ + struct upd_ctx *ctx = malloc(sizeof(struct upd_ctx)); + if (!ctx) { + ERROR("Memory Allocation Failure!"); + return NULL; + } + memset(ctx, 0, sizeof(struct upd_ctx)); + return ctx; +} + +static int upd_attach(void *vctx, struct libusb_device_handle *dev, int type, + uint8_t endp_up, uint8_t endp_down, uint8_t jobid) +{ + struct upd_ctx *ctx = vctx; + + UNUSED(jobid); + + ctx->dev = dev; + ctx->endp_up = endp_up; + ctx->endp_down = endp_down; + ctx->type = type; + + if (ctx->type == P_SONY_UPD895 || ctx->type == P_SONY_UPD897) { + ctx->marker.color = "#000000"; /* Ie black! */ + ctx->native_bpp = 1; + } else { + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->native_bpp = 3; + } + + ctx->marker.name = "Unknown"; + ctx->marker.levelmax = -1; + ctx->marker.levelnow = -2; + + return CUPS_BACKEND_OK; +} + +static void upd_cleanup_job(const void *vjob) +{ + const struct upd_printjob *job = vjob; + + if (job->databuf) + free(job->databuf); + + free((void*)job); +} + +// UP-DR200 +// 2UPC-R203 3.5x5 (770) +// 2UPC-R204 4x6 (700) +// 2UPC-R205 5x7 (400) +// 2UPC-R206 6x8 (350) + +// UP-DR150 +// 2UPC-R153 (610) +// 2UPC-R154 (550) +// 2UPC-R155 (335) +// 2UPC-R156 (295) + +// print order: ->YMCO-> +// current prints (power on) +// total prints (lifetime) +// f/w version + +static char* upd895_statuses(uint8_t code) +{ + switch (code) { + case UPD_STS1_IDLE: + return "Idle"; + case UPD_STS1_DOOROPEN: + return "Door open"; + case UPD_STS1_NOPAPER: + return "No paper"; + case UPD_STS1_PRINTING: + return "Printing"; + default: + return "Unknown"; + } +} + +static int sony_get_status(struct upd_ctx *ctx, struct sony_updsts *buf) +{ + int ret, num = 0; + uint8_t query[7] = { 0x1b, 0xe0, 0, 0, 0, 0x0f, 0 }; + + if (ctx->type == P_SONY_UPD895) + query[5] = 0x0e; + + if ((ret = send_data(ctx->dev, ctx->endp_down, + query, sizeof(query)))) + return CUPS_BACKEND_FAILED; + + ret = read_data(ctx->dev, ctx->endp_up, (uint8_t*) buf, sizeof(*buf), + &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; +#if 0 + if (ctx->type == P_SONY_UPD895 && ret != 14) + return CUPS_BACKEND_FAILED; + else if (ret != 15) + return CUPS_BACKEND_FAILED; +#endif + + ctx->stsbuf.max_cols = be16_to_cpu(ctx->stsbuf.max_cols); + ctx->stsbuf.max_rows = be16_to_cpu(ctx->stsbuf.max_rows); + + return CUPS_BACKEND_OK; +} + +#define MAX_PRINTJOB_LEN (2048*2764*3 + 2048) + +static int upd_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { + struct upd_ctx *ctx = vctx; + int len, run = 1; + uint32_t copies_offset = 0; + uint32_t param_offset = 0; + uint32_t data_offset = 0; + + struct upd_printjob *job = NULL; + + if (!ctx) + return CUPS_BACKEND_FAILED; + + job = malloc(sizeof(*job)); + if (!job) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } + memset(job, 0, sizeof(*job)); + job->copies = copies; + + job->datalen = 0; + job->databuf = malloc(MAX_PRINTJOB_LEN); + if (!job->databuf) { + ERROR("Memory allocation failure!\n"); + upd_cleanup_job(job); + return CUPS_BACKEND_RETRY_CURRENT; + } + + while(run) { + int i; + int keep = 0; + i = read(data_fd, job->databuf + job->datalen, 4); + if (i < 0) { + upd_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + if (i == 0) + break; + + memcpy(&len, job->databuf + job->datalen, sizeof(len)); + len = le32_to_cpu(len); + + /* Filter out chunks we don't send to the printer */ + if (len & 0xf0000000) { + switch (len) { + case 0xfffffff3: + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 0); + len = 0; + if (ctx->type == P_SONY_UPDR150) + run = 0; + break; + case 0xfffffff7: + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 0); + len = 0; + if (ctx->type == P_SONY_UPCR10) + run = 0; + break; + case 0xfffffff8: // 895 + case 0xfffffff4: // 897 + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 0); + len = 0; + if (ctx->type == P_SONY_UPD895 || ctx->type == P_SONY_UPD897) + run = 0; + break; + case 0xffffff97: + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 12); + len = 12; + break; + case 0xffffffef: + if (ctx->type == P_SONY_UPD895 || ctx->type == P_SONY_UPD897) { + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 0); + len = 0; + break; + } + /* Intentional Fallthrough */ + case 0xffffffeb: + case 0xffffffee: + case 0xfffffff5: + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 4); + len = 4; + break; + case 0xffffffec: + if (ctx->type == P_SONY_UPD897) { + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 4); + len = 4; + break; + } + /* Intentional Fallthrough */ + default: + if(dyesub_debug) + DEBUG("Block ID '%08x' (len %d)\n", len, 0); + len = 0; + break; + } + } else { + /* Only keep these chunks */ + if(dyesub_debug) + DEBUG("Data block (len %d)\n", len); + if (len > 0) + keep = 1; + } + if (keep) + job->datalen += sizeof(uint32_t); + + /* Make sure we're not too large */ + if (job->datalen + len > MAX_PRINTJOB_LEN) { + ERROR("Buffer overflow when parsing printjob! (%d+%d)\n", + job->datalen, len); + upd_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + + /* Read in the data chunk */ + while(len > 0) { + i = read(data_fd, job->databuf + job->datalen, len); + if (i < 0) { + upd_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + if (i == 0) + break; + + /* Work out offset of copies command */ + if (job->databuf[job->datalen] == 0x1b) { + int offset = 0; + if (i == 7) + offset = 4; + + switch (job->databuf[job->datalen + 1]) { + case 0x15: /* Print dimensions */ + param_offset = job->datalen + 16 + offset; + break; + case 0xee: + copies_offset = job->datalen + 7 + offset; + break; + case 0xe1: /* Image dimensions */ + param_offset = job->datalen + 14 + offset; + break; + case 0xea: + data_offset = job->datalen + 6 + offset; + break; + default: + break; + } + } + + if (keep) + job->datalen += i; + len -= i; + } + } + if (!job->datalen) { + upd_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + + /* Some models specify copies in the print job */ + if (copies_offset) { + uint16_t tmp = copies; + tmp = cpu_to_be16(copies); + memcpy(job->databuf + copies_offset, &tmp, sizeof(tmp)); + job->copies = 1; + } + + /* Parse some other stuff */ + if (param_offset) { + memcpy(&job->cols, job->databuf + param_offset, sizeof(uint16_t)); + memcpy(&job->rows, job->databuf + param_offset + 2, sizeof(uint16_t)); + job->cols = be16_to_cpu(job->cols); + job->rows = be16_to_cpu(job->rows); + } + if (data_offset) { + memcpy(&job->imglen, job->databuf + data_offset, sizeof(uint32_t)); + job->imglen = be32_to_cpu(job->imglen); + } + + /* Sanity check job parameters */ + if (job->imglen != (uint32_t)(job->rows * job->cols * ctx->native_bpp)) + { + ERROR("Job data length mismatch (%u vs %d)!\n", + job->imglen, job->rows * job->cols * ctx->native_bpp); + upd_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + + *vjob = job; + + return CUPS_BACKEND_OK; +} + +static int upd_main_loop(void *vctx, const void *vjob) { + struct upd_ctx *ctx = vctx; + int i, ret; + int copies; + + const struct upd_printjob *job = vjob; + + if (!ctx) + return CUPS_BACKEND_FAILED; + if (!job) + return CUPS_BACKEND_FAILED; + + copies = job->copies; + +top: + /* Send Unknown CMD. Resets? */ + if (ctx->type == P_SONY_UPD897) { + const uint8_t cmdbuf[7] = { 0x1b, 0x1f, 0, 0, 0, 0, 0 }; + ret = send_data(ctx->dev, ctx->endp_down, + cmdbuf, sizeof(cmdbuf)); + if (ret) + return CUPS_BACKEND_FAILED; + } + + /* Query printer status */ + ret = sony_get_status(ctx, &ctx->stsbuf); + + if (ret) + return CUPS_BACKEND_FAILED; + + /* Sanity check job parameters */ + if (job->rows > ctx->stsbuf.max_rows || + job->cols > ctx->stsbuf.max_cols) { + ERROR("Job dimensions (%u/%u) exceed printer max (%u/%u)\n", + job->cols, job->rows, + ctx->stsbuf.max_cols, + ctx->stsbuf.max_rows); + return CUPS_BACKEND_CANCEL; + } + + /* Check for idle */ + if (ctx->stsbuf.sts1 != 0x00) { + if (ctx->stsbuf.sts1 == 0x80) { + INFO("Waiting for printer idle...\n"); + sleep(1); + goto top; + } + } + + /* Send RESET */ + if (ctx->type != P_SONY_UPD895) { + const uint8_t rstbuf[7] = { 0x1b, 0x16, 0, 0, 0, 0, 0 }; + ret = send_data(ctx->dev, ctx->endp_down, + rstbuf, sizeof(rstbuf)); + if (ret) + return CUPS_BACKEND_FAILED; + } + +#if 0 /* Unknown query */ + if (ctx->type == P_SONY_UPD897) { + // -> 1b e6 00 00 00 08 00 + // <- ??? + } +#endif + + /* Send over job */ + i = 0; + while (i < job->datalen) { + uint32_t len; + memcpy(&len, job->databuf + i, sizeof(len)); + len = le32_to_cpu(len); + + i += sizeof(uint32_t); + + if ((ret = send_data(ctx->dev, ctx->endp_down, + job->databuf + i, len))) + return CUPS_BACKEND_FAILED; + + i += len; + } + + // XXX generate and send copy cmd instead of using the offset. + // 1b ee 00 00 00 02 00 NN NN (BE) + + /* Wait for completion! */ +retry: + sleep(1); + + /* Check for idle */ + ret = sony_get_status(ctx, &ctx->stsbuf); + if (ret) + return ret; + + switch (ctx->stsbuf.sts1) { + case UPD_STS1_IDLE: + goto done; + case UPD_STS1_PRINTING: + break; + default: + ERROR("Printer error: %s (%02x)\n", upd895_statuses(ctx->stsbuf.sts1), + ctx->stsbuf.sts1); + return CUPS_BACKEND_STOP; + } + + if (fast_return && ctx->stsbuf.printing != UPD_PRINTING_IDLE) { + INFO("Fast return mode enabled.\n"); + } else { + goto retry; + } + + /* Clean up */ + if (terminate) + copies = 1; + +done: + INFO("Print complete (%d copies remaining)\n", copies - 1); + + if (copies && --copies) { + goto top; + } + + return CUPS_BACKEND_OK; +} + +static int upd895_dump_status(struct upd_ctx *ctx) +{ + int ret = sony_get_status(ctx, &ctx->stsbuf); + if (ret < 0) + return CUPS_BACKEND_FAILED; + + INFO("Printer status: %s (%02x)\n", upd895_statuses(ctx->stsbuf.sts1), ctx->stsbuf.sts1); + if (ctx->stsbuf.printing != UPD_PRINTING_IDLE && + ctx->stsbuf.sts1 == UPD_STS1_PRINTING) + INFO("Remaining copies: %d\n", ctx->stsbuf.remain); + + return CUPS_BACKEND_OK; +} + + +static void upd_cmdline(void) +{ + DEBUG("\t\t[ -s ] # Query printer status\n"); +} + +static int upd_cmdline_arg(void *vctx, int argc, char **argv) +{ + struct upd_ctx *ctx = vctx; + int i, j = 0; + + if (!ctx) + return -1; + + while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "s")) >= 0) { + switch(i) { + GETOPT_PROCESS_GLOBAL + case 's': + j = upd895_dump_status(ctx); + break; + } + + if (j) return j; + } + + return 0; +} + +static int upd_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct upd_ctx *ctx = vctx; + int ret = sony_get_status(ctx, &ctx->stsbuf); + + *markers = &ctx->marker; + *count = 1; + + if (ret) + return CUPS_BACKEND_FAILED; + + if (ctx->stsbuf.sts1 == 0x40 || + ctx->stsbuf.sts1 == 0x08) { + ctx->marker.levelnow = 0; + STATE("+media-empty\n"); + } else { + ctx->marker.levelnow = -3; + STATE("-media-empty\n"); + } + + return CUPS_BACKEND_OK; +} + +static const char *sonyupd_prefixes[] = { + "sonyupd", + "sony-updr150", "sony-updr200", "sony-upcr10l", + "sony-upd895", "sony-upd897", "dnp-sl10", + // Backwards compatibility + "sonyupdr150", + "sonyupdr200", "sonyupcr10", + NULL +}; + +/* Exported */ +#define USB_VID_SONY 0x054C +#define USB_PID_SONY_UPDR150 0x01E8 +#define USB_PID_SONY_UPDR200 0x035F +#define USB_PID_SONY_UPCR10 0x0226 +#define USB_PID_SONY_UPD895 0x0049 +#define USB_PID_SONY_UPD897 0x01E7 + +struct dyesub_backend sonyupd_backend = { + .name = "Sony UP-D", + .version = "0.37", + .uri_prefixes = sonyupd_prefixes, + .cmdline_arg = upd_cmdline_arg, + .cmdline_usage = upd_cmdline, + .init = upd_init, + .attach = upd_attach, + .cleanup_job = upd_cleanup_job, + .read_parse = upd_read_parse, + .main_loop = upd_main_loop, + .query_markers = upd_query_markers, + .devices = { + { USB_VID_SONY, USB_PID_SONY_UPDR150, P_SONY_UPDR150, NULL, "sony-updr150"}, + { USB_VID_SONY, USB_PID_SONY_UPDR200, P_SONY_UPDR150, NULL, "sony-updr200"}, + { USB_VID_SONY, USB_PID_SONY_UPCR10, P_SONY_UPCR10, NULL, "sony-upcr10l"}, + { USB_VID_SONY, USB_PID_SONY_UPD895, P_SONY_UPD895, NULL, "sonyupd895"}, + { USB_VID_SONY, USB_PID_SONY_UPD897, P_SONY_UPD897, NULL, "sony-upd897"}, + { 0, 0, 0, NULL, NULL} + } +}; + +/* Sony spool file format + + The spool file is a series of 4-byte commands, followed by optional + arguments. The purpose of the commands is unknown, but they presumably + instruct the driver to perform certain things. + + If you treat these 4 bytes as a 32-bit little-endian number, if any of the + least significant 4 bits are non-zero, the value is is to + be interpreted as a driver command. If the most significant bits are + zero, the value signifies that the following N bytes of data should be + sent to the printer as-is. + + Known driver "commands": + + 97 ff ff ff + eb ff ff ff ?? 00 00 00 + ec ff ff ff ?? 00 00 00 + ed ff ff ff ?? 00 00 00 + ee ff ff ff ?? 00 00 00 + ef ff ff ff XX 00 00 00 # XX == print size (0x01/0x02/0x03/0x04) + ef ff ff ff # On UP-D895/897 + f3 ff ff ff + f4 ff ff ff # End of job on UP-D897 + f5 ff ff ff YY 00 00 00 # YY == ??? (seen 0x01) + f7 ff ff ff # End of job on UP-D895 + + All printer commands start with 0x1b, and are at least 7 bytes long. + General Command format: + + 1b XX ?? ?? ?? LL 00 # XX is cmd, LL is data or response length. + + UNKNOWN QUERY [possibly media?] + + <- 1b 03 00 00 00 13 00 + -> 70 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 00 + 00 00 00 + + UNKNOWN CMD (UP-DR & SL10 & UP-D895 & UP-DP10) [ possibly START ] + + <- 1b 0a 00 00 00 00 00 + + PRINT DIMENSIONS + + <- 1b 15 00 00 00 0d 00 + <- 00 00 00 00 ZZ QQ QQ WW WW YY YY XX XX + + QQ/WW/YY/XX are (origin_cols/origin_rows/cols/rows) in BE. + ZZ is 0x07 on UP-DR series, 0x01 on UP-D89x series. + + RESET + + <- 1b 16 00 00 00 00 00 + + UNKNOWN CMD (UP-DR & SL & UP-D897, may be PRINT START?) + + <- 1b 17 00 00 00 00 00 + + UNKNOWN CMD + + <- 1b 1f 00 00 00 00 00 + + SET PARAM + + <- 1b c0 00 NN LL 00 00 # LL is response length, NN is number. + <- [ NN bytes] + + QUERY PARAM + + <- 1b c1 00 NN LL 00 00 # LL is response length, NN is number. + -> [ NN bytes ] + + PARAMS SEEN: + 03, len 5 [ 02 03 00 01 XX ] (UPDR200, 00 = normal, 02 is multicut/div2 print, 01 seen at end of stream too.. + 02, len 06 [ 02 02 00 03 00 00 ] + 01, len 10 [ 02 01 00 06 00 02 00 00 00 00 ] (UP-D897) + 00, len 5 [ 02 01 00 01 XX ] XX == Gamma table + + STATUS QUERY + + <- 1b e0 00 00 00 XX 00 # XX = 0xe (UP-D895), 0xf (All others) + -> [14 or 15 bytes, see 'struct sony_updsts' ] + + IMAGE DIMENSIONS & OVERCOAT + + <- 1b e1 00 00 00 0b 00 + <- 00 ZZ QQ 00 00 00 00 XX XX YY YY # XX = cols, YY == rows, ZZ == 0x04 on UP-DP10, otherwise 0x80. QQ == 00 glossy, 08 texture (UP-DP10 + UP-DR150), 0c matte, +0x10 for "nocorrection" on UP-DR200.. + + UNKNOWN + + <- 1b e5 00 00 00 08 00 + <- 00 00 00 00 00 00 00 XX 00 # Seen 01, 12, 0d, etc. + + UNKNOWN (UP-D897) + + <- 1b e6 00 00 00 08 00 + <- 07 00 00 00 00 00 00 00 + + DATA TRANSFER + + <- 1b ea 00 00 00 00 ZZ ZZ ZZ ZZ 00 # ZZ is BIG ENDIAN + <- [ ZZ ZZ ZZ ZZ bytes of data ] + + UNKNOWN CMD (UP-DR and UP-D) + + <- 1b ed 00 00 00 00 00 + + UNKNOWN (UPDR series) + + <- 1b ef 00 00 00 06 00 + -> 05 00 00 00 00 22 + + COPIES + + <- 1b ee 00 00 00 02 00 + <- NN NN # Number of copies (BE, 1-???) + + UNKNOWN (UPDR series) + + <- 1b f5 00 00 00 02 00 + <- ?? ?? + + ************************************************************************ + + The data stream sent to the printer consists of all the commands in the + spool file, plus a couple other ones that generate responses. It is + unknown if those additional commands are necessary. This is a typical + sequence: + +[[ Sniff start of a UP-DR150 ]] + +<- 1b e0 00 00 00 0f 00 [ STATUS QUERY ] +-> 0e 00 00 00 00 00 00 00 04 a8 08 00 0a a4 00 + ----- ----- + MAX_C MAX_R +<- 1b 16 00 00 00 00 00 +-> "reset" ?? + +[[ begin job ]] + +<- 1b ef 00 00 00 06 00 +-> 05 00 00 00 00 22 + +<- 1b e5 00 00 00 08 00 ** In spool file +<- 00 00 00 00 00 00 01 00 + +<- 1b c1 00 02 06 00 00 [ Query Param 2, length 6 ] +-> 02 02 00 03 00 00 + +<- 1b ee 00 00 00 02 00 ** In spool file +<- 00 01 + +<- 1b 15 00 00 00 0d 00 ** In spool file +<- 00 00 00 00 07 00 00 00 00 08 00 0a a4 + +<- 1b 03 00 00 00 13 00 +-> 70 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 00 + 00 00 00 + +<- 1b e1 00 00 00 0b 00 ** In spool file +<- 00 80 00 00 00 00 00 08 00 0a a4 + +<- 1b 03 00 00 00 13 00 +-> 70 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 00 + 00 00 00 + +<- 1b ea 00 00 00 00 00 ff 60 00 00 ** In spool file +<- [[ 0x0060ff00 bytes of data ]] + +<- 1b e0 00 00 00 0f 00 +-> 0e 00 00 00 00 00 00 00 04 a8 08 00 0a a4 00 + +<- 1b 0a 00 00 00 00 00 ** In spool file +<- 1b 17 00 00 00 00 00 ** In spool file + +[[fin]] + + ************** + + Sony UP-CL10 / DNP SL-10 spool format: + +60 ff ff ff f8 ff ff ff fd ff ff ff +14 00 00 00 +1b 15 00 00 00 0d 00 00 00 00 00 07 00 00 00 00 WW WW HH HH +fb ff ff ff f4 ff ff ff +0b 00 00 00 +1b ea 00 00 00 00 SH SH SH SH 00 +SL SL SL SL + + [[ Data, rows * cols * 3 bytes ]] + +f3 ff ff ff +0f 00 00 00 +1b e5 00 00 00 08 00 00 00 00 00 00 00 00 00 +12 00 00 00 +1b e1 00 00 00 0b 00 00 80 00 00 00 00 00 WW WW HH HH +fa ff ff ff +09 00 00 00 +1b ee 00 00 00 02 00 00 NN +07 00 00 00 +1b 0a 00 00 00 00 00 +f9 ff ff ff fc ff ff ff +07 00 00 00 +1b 17 00 00 00 00 00 +f7 ff ff ff + + WW WW == Columns, Big Endian + HH HH == Rows, Big Endian + SL SL SL SL == Plane size, Little Endian (Rows * Cols * 3) + SH SH SH SH == Plane size, Big Endian (Rows * Cols * 3) + NN == Copies + + ************** + + Sony UP-D895 spool format: + + XX XX == cols, BE (fixed at 1280/0x500) + YY YY == rows, BE (798/0x031e,1038/0x040e,1475/0x05c3, 2484/09b4) @ 960/1280/1920/3840+4096 + SS SS SS SS == data len (rows * cols, LE) + S' S' S' S' == data len (rows * cols, BE) + NN == copies (1 -> ??) + GG GG == ??? 0000/0050/011b/04aa/05aa at each resolution. + G' == Gamma 01 (soft), 03 (hard), 02 (normal) + + 9c ff ff ff 97 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff + + 14 00 00 00 + 1b 15 00 00 00 0d 00 00 00 00 00 01 GG GG 00 00 YY YY XX XX + 0b 00 00 00 + 1b ea 00 00 00 00 S' S' S' S' 00 + SS SS SS SS + ...DATA... (rows * cols) + ff ff ff ff + 09 00 00 00 + 1b ee 00 00 00 02 00 00 NN + 0f 00 00 00 + 1b e5 00 00 00 08 00 00 00 00 00 00 00 00 00 + 0c 00 00 00 + 1b c0 00 00 00 05 00 02 00 00 01 G' + 11 00 00 00 + 1b c0 00 01 00 0a 00 02 01 00 06 00 00 00 00 00 00 + 12 00 00 00 + 1b e1 00 00 00 0b 00 00 08 00 GG GG 00 00 YY YY XX XX + 07 00 00 00 + 1b 0a 00 00 00 00 00 + fd ff ff ff f7 ff ff ff f8 ff ff ff + + ************** + + Sony UP-D897 spool format: + + NN NN == copies (00 for printer selected) + XX XX == cols (fixed @ 1280) + YY YY == rows + GG == gamma -- Table 2 == 2, Table 1 == 3, Table 3 == 1, Table 4 == 4 + DD == "dark" +- 64. + LL == "light" +- 64. + AA == "advanced" +- 32. + SS == Sharpness 0-14 + ZZ ZZ ZZ ZZ == Data length (BE) + Z` Z` Z` Z` == Data length (LE) + + + 83 ff ff ff fc ff ff ff + fb ff ff ff f5 ff ff ff + f1 ff ff ff f0 ff ff ff + ef ff ff ff + + 14 00 00 00 + 1b 15 00 00 00 0d 00 00 00 00 00 01 00 a2 00 00 YY YY XX XX + + 0b 00 00 00 + 1b ea 00 00 00 00 ZZ ZZ ZZ ZZ 00 + + Z` Z` Z` Z` + ...DATA... + + ea ff ff ff + + 09 00 00 00 + 1b ee 00 00 00 02 00 NN NN + + ee ff ff ff 01 00 00 00 + + 0e 00 00 00 + 1b e5 00 00 00 08 00 00 00 00 00 DD LL SS AA + + eb ff ff ff ?? 00 00 00 <--- 02/05 5 at #3, 2 otherwise. Sharpness? + + 0c 00 00 00 + 1b c0 00 00 00 05 00 02 00 00 01 GG + + ec ff ff ff ?? 00 00 00 <--- 01/00/02/01/01 Seen. Unknown. + + 11 00 00 00 + 1b c0 00 01 00 0a 00 02 01 00 06 00 00 00 00 00 00 + + ed ff ff ff 00 00 00 00 + + 12 00 00 00 + 1b e1 00 00 00 0b 00 00 08 00 00 a2 00 00 YY YY XX XX + + fa ff ff ff + + 07 00 00 00 + 1b 0a 00 00 00 00 00 + + fc ff ff ff fd ff ff ff ff ff ff ff + + 07 00 00 00 + 1b 17 00 00 00 00 00 + + f4 ff ff ff + + **************** + + UP-D895 comms protocol: + + <-- 1b e0 00 00 00 0e 00 + --> 0d 00 XX YY 00 SS 00 ZZ 00 00 10 00 05 00 + + XX : 0xe0 when printing, 0x00 otherwise. + YY : Number of remaining copies + SS : Status + 0x00 = Idle + 0x08 = Door open + 0x40 = Paper empty + 0x80 = Printing + ?? = Cooling down + ?? = Busy / Waiting + ZZ : Status2 + 0x01 = Print complete + 0x02 = no prints yet + + UP-D897 comms protocol: + + <-- 1b e0 00 00 00 0f 00 + --> 0e 00 XX YY 00 SS RR 01 02 02 10 00 05 00 PP + + XX : 0xe0 when printing, 0x00 otherwise. + YY : Number of remaining copies + SS : Status + 0x00 = Idle +?? 0x08 = Door open + 0x40 = Paper empty + 0x80 = Printing + ?? = Cooling down + ?? = Busy / Waiting + RR : Status 2 + 0x00 = Okay + 0x08 = ?? Error state? + 0x80 = Printing + PP : Percentage complete (0-99) + +Other commands seen: + + <-- 1b 16 00 00 00 00 00 -- Reset + + <-- 1b c1 00 01 00 0a 00 -- Query ID 1, legth 10 + --> 02 01 00 06 00 02 00 00 00 00 + + <-- 1b c1 00 00 00 05 00 -- Query id 0, length 5 + --> 02 01 00 01 03 + + <-- 1b e6 00 00 00 08 00 + --> 07 00 00 00 00 00 00 00 + + <-- 1b 17 00 00 00 00 00 -- Unknown? + + UP-CR10L + + 2UPC-C13 (300) + 2UPC-C14 (200) + 2UPC-C15 (172) + + Status progression when printing: + + 0e 00 00 00 00 00 00 00 04 a0 04 e0 07 38 00 + 0e 00 00 01 00 80 00 01 04 a0 04 e0 07 38 64 + 0e 00 40 01 00 80 00 01 04 a0 04 e0 07 38 64 <-- Y + 0e 00 80 01 00 80 00 01 04 a0 04 e0 07 38 64 <-- M + 0e 00 c0 01 00 80 00 01 04 a0 04 e0 07 38 64 <-- C + 0e 00 20 01 00 80 00 01 04 a0 04 e0 07 38 64 <-- O + 0e 00 20 01 00 80 00 01 04 a0 04 e0 07 38 00 + 0e 00 00 01 00 80 00 01 04 a0 04 e0 07 38 00 + 0e 00 00 00 00 00 00 00 04 a0 04 e0 07 38 00 + +*/ diff --git a/src/cups/backend_sonyupdr150.c b/src/cups/backend_sonyupdr150.c deleted file mode 100644 index 5e8ae2e..0000000 --- a/src/cups/backend_sonyupdr150.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Sony UP-DR150 Photo Printer CUPS backend -- libusb-1.0 version - * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> - * - * The latest version of this program can be found at: - * - * http://git.shaftnet.org/cgit/selphy_print.git - * - * 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 <https://www.gnu.org/licenses/>. - * - * [http://www.gnu.org/licenses/gpl-2.0.html] - * - * SPDX-License-Identifier: GPL-2.0+ - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <signal.h> - -#define BACKEND updr150_backend - -#include "backend_common.h" - -/* Private data structure */ -struct updr150_printjob { - uint8_t *databuf; - int datalen; - int copies; -}; - -struct updr150_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; - - struct marker marker; -}; - -static void* updr150_init(void) -{ - struct updr150_ctx *ctx = malloc(sizeof(struct updr150_ctx)); - if (!ctx) { - ERROR("Memory Allocation Failure!"); - return NULL; - } - memset(ctx, 0, sizeof(struct updr150_ctx)); - return ctx; -} - -static int updr150_attach(void *vctx, struct libusb_device_handle *dev, int type, - uint8_t endp_up, uint8_t endp_down, uint8_t jobid) -{ - struct updr150_ctx *ctx = vctx; - - UNUSED(jobid); - - ctx->dev = dev; - ctx->endp_up = endp_up; - ctx->endp_down = endp_down; - ctx->type = type; - - ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = "Unknown"; - ctx->marker.levelmax = -1; - ctx->marker.levelnow = -2; - - return CUPS_BACKEND_OK; -} - -static void updr150_cleanup_job(const void *vjob) -{ - const struct updr150_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void updr150_teardown(void *vctx) { - struct updr150_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - -#define MAX_PRINTJOB_LEN 16736455 -static int updr150_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { - struct updr150_ctx *ctx = vctx; - int len, run = 1; - uint32_t copies_offset = 0; - - struct updr150_printjob *job = NULL; - - if (!ctx) - return CUPS_BACKEND_FAILED; - - job = malloc(sizeof(*job)); - if (!job) { - ERROR("Memory allocation failure!\n"); - return CUPS_BACKEND_RETRY_CURRENT; - } - memset(job, 0, sizeof(*job)); - job->copies = copies; - - job->datalen = 0; - job->databuf = malloc(MAX_PRINTJOB_LEN); - if (!job->databuf) { - ERROR("Memory allocation failure!\n"); - updr150_cleanup_job(job); - return CUPS_BACKEND_RETRY_CURRENT; - } - - while(run) { - int i; - int keep = 0; - i = read(data_fd, job->databuf + job->datalen, 4); - if (i < 0) { - updr150_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - if (i == 0) - break; - - memcpy(&len, job->databuf + job->datalen, sizeof(len)); - len = le32_to_cpu(len); - - /* Filter out chunks we don't send to the printer */ - if (len & 0xf0000000) { - switch (len) { - case 0xfffffff3: - if(dyesub_debug) - DEBUG("Block ID '%08x' (len %d)\n", len, 0); - len = 0; - if (ctx->type == P_SONY_UPDR150) - run = 0; - break; - case 0xfffffff7: - if(dyesub_debug) - DEBUG("Block ID '%08x' (len %d)\n", len, 0); - len = 0; - if (ctx->type == P_SONY_UPCR10) - run = 0; - break; - case 0xfffffff8: // 895 - case 0xfffffff4: // 897 - if(dyesub_debug) - DEBUG("Block ID '%08x' (len %d)\n", len, 0); - len = 0; - if (ctx->type == P_SONY_UPD89x) - run = 0; - break; - case 0xffffffeb: - case 0xffffffec: - case 0xffffffed: - case 0xffffffee: - case 0xffffffef: - case 0xfffffff5: - if(dyesub_debug) - DEBUG("Block ID '%08x' (len %d)\n", len, 4); - len = 4; - break; - default: - if(dyesub_debug) - DEBUG("Block ID '%08x' (len %d)\n", len, 0); - len = 0; - break; - } - } else { - /* Only keep these chunks */ - if(dyesub_debug) - DEBUG("Data block (len %d)\n", len); - keep = 1; - } - if (keep) - job->datalen += sizeof(uint32_t); - - /* Read in the data chunk */ - while(len > 0) { - i = read(data_fd, job->databuf + job->datalen, len); - if (i < 0) { - updr150_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - if (i == 0) - break; - - if (job->databuf[job->datalen] == 0x1b && - job->databuf[job->datalen + 1] == 0xee) { - if (ctx->type == P_SONY_UPCR10) - copies_offset = job->datalen + 8; - else - copies_offset = job->datalen + 12; - } - - if (keep) - job->datalen += i; - len -= i; - } - } - if (!job->datalen) { - updr150_cleanup_job(job); - return CUPS_BACKEND_CANCEL; - } - - /* Some models specify copies in the print job */ - if (copies_offset) { - job->databuf[copies_offset] = job->copies; - job->copies = 1; - } - - *vjob = job; - - return CUPS_BACKEND_OK; -} - -static int updr150_main_loop(void *vctx, const void *vjob) { - struct updr150_ctx *ctx = vctx; - int i, ret; - int copies; - - const struct updr150_printjob *job = vjob; - - if (!ctx) - return CUPS_BACKEND_FAILED; - if (!job) - return CUPS_BACKEND_FAILED; - - copies = job->copies; - -top: - i = 0; - while (i < job->datalen) { - uint32_t len; - memcpy(&len, job->databuf + i, sizeof(len)); - len = le32_to_cpu(len); - - i += sizeof(uint32_t); - - if ((ret = send_data(ctx->dev, ctx->endp_down, - job->databuf + i, len))) - return CUPS_BACKEND_FAILED; - - i += len; - } - - /* Clean up */ - if (terminate) - copies = 1; - - INFO("Print complete (%d copies remaining)\n", copies - 1); - - if (copies && --copies) { - goto top; - } - - return CUPS_BACKEND_OK; -} - -static int updr150_cmdline_arg(void *vctx, int argc, char **argv) -{ - struct updr150_ctx *ctx = vctx; - int i, j = 0; - - if (!ctx) - return -1; - - while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL)) >= 0) { - switch(i) { - GETOPT_PROCESS_GLOBAL - } - - if (j) return j; - } - - return 0; -} - -static int updr150_query_markers(void *vctx, struct marker **markers, int *count) -{ - struct updr150_ctx *ctx = vctx; - - *markers = &ctx->marker; - *count = 1; - - return CUPS_BACKEND_OK; -} - -static const char *sonyupdr150_prefixes[] = { - "sonyupdr150", // Family name. - "sony-updr150", "sony-updr200", "sony-upcr10", - // Backwards compatibility - "sonyupdr200", "sonyupcr10", -// "sonyupd895", "sonyupd897", "sonyupd898", - NULL -}; - -/* Exported */ -#define USB_VID_SONY 0x054C -#define USB_PID_SONY_UPDR150 0x01E8 -#define USB_PID_SONY_UPDR200 0x035F -#define USB_PID_SONY_UPCR10 0x0226 -//#define USB_PID_SONY_UPD895 XXXXX // 0x7ea6? -//#define USB_PID_SONY_UPD897 XXXXX // 0xbce7? -//#define USB_PID_SONY_UPD898 XXXXX // 0x589a? - -struct dyesub_backend updr150_backend = { - .name = "Sony UP-DR150/UP-DR200/UP-CR10", - .version = "0.26", - .uri_prefixes = sonyupdr150_prefixes, - .cmdline_arg = updr150_cmdline_arg, - .init = updr150_init, - .attach = updr150_attach, - .teardown = updr150_teardown, - .cleanup_job = updr150_cleanup_job, - .read_parse = updr150_read_parse, - .main_loop = updr150_main_loop, - .query_markers = updr150_query_markers, - .devices = { - { USB_VID_SONY, USB_PID_SONY_UPDR150, P_SONY_UPDR150, NULL, "sony-updr150"}, - { USB_VID_SONY, USB_PID_SONY_UPDR200, P_SONY_UPDR150, NULL, "sony-updr200"}, - { USB_VID_SONY, USB_PID_SONY_UPCR10, P_SONY_UPCR10, NULL, "sony-upcr10"}, -// { USB_VID_SONY, USB_PID_SONY_UPD895MD, P_SONY_UPD89x, NULL, "sonyupd895"}, -// { USB_VID_SONY, USB_PID_SONY_UPD897MD, P_SONY_UPD89x, NULL, "sonyupd897"}, -// { USB_VID_SONY, USB_PID_SONY_UPD898MD, P_SONY_UPD89x, NULL, "sonyupd898"}, - { 0, 0, 0, NULL, NULL} - } -}; - -/* Sony UP-DR150/UP-DR200 Spool file format - - The spool file is a series of 4-byte commands, followed by optional - arguments. The purpose of the commands is unknown, but they presumably - instruct the driver to perform certain things. - - If you treat these 4 bytes as a 32-bit little-endian number, if any of the - most significant 4 bits are non-zero, the value is is to - be interpreted as a driver command. If the most significant bits are - zero, the value signifies that the following N bytes of data should be - sent to the printer as-is. - - Known driver "commands": - - eb ff ff ff ?? 00 00 00 - ec ff ff ff ?? 00 00 00 - ed ff ff ff ?? 00 00 00 - ee ff ff ff ?? 00 00 00 - ef ff ff ff XX 00 00 00 # XX == print size (0x01/0x02/0x03/0x04) - f5 ff ff ff YY 00 00 00 # YY == ??? (seen 0x01) - - All printer commands start with 0x1b, and are at least 7 bytes long. - - ************************************************************************ - - The data stream sent to the printer consists of all the commands in the - spool file, plus a couple other ones that generate responses. It is - unknown if those additional commands are necessary. This is a typical - sequence: - -[[ Sniff start of a UP-DR150 ]] - -<- 1b e0 00 00 00 0f 00 --> 0e 00 00 00 00 00 00 00 00 04 a8 08 0a a4 00 - -<- 1b 16 00 00 00 00 00 --> "reset" ?? - -[[ begin job ]] - -<- 1b ef 00 00 00 06 00 --> 05 00 00 00 00 22 - -<- 1b e5 00 00 00 08 00 ** In spool file -<- 00 00 00 00 00 00 01 00 - -<- 1b c1 00 02 06 00 00 --> 02 02 00 03 00 00 - -<- 1b ee 00 00 00 02 00 ** In spool file -<- 00 01 - -<- 1b 15 00 00 00 0d 00 ** In spool file -<- 00 00 00 00 07 00 00 00 00 08 00 0a a4 - -<- 1b 03 00 00 00 13 00 --> 70 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 00 - 00 00 00 - -<- 1b e1 00 00 00 0b 00 ** In spool file -<- 00 80 00 00 00 00 00 08 00 0a a4 - -<- 1b 03 00 00 00 13 00 --> 70 00 00 00 00 00 00 0b 00 00 00 00 00 00 00 00 - 00 00 00 - -<- 1b ea 00 00 00 00 00 ff 60 00 00 ** In spool file -<- [[ 0x0060ff00 bytes of data ]] - -<- 1b e0 00 00 00 0f 00 --> 0e 00 00 00 00 00 00 00 04 a8 08 00 0a a4 00 - -<- 1b 0a 00 00 00 00 00 ** In spool file -<- 1b 17 00 00 00 00 00 ** In spool file - -[[fin]] - - ************** - - Sony UP-CL10 / DNP SL-10 spool format: - -60 ff ff ff -f8 ff ff ff -fd ff ff ff 14 00 00 00 1b 15 00 00 00 0d 00 00 00 00 00 07 00 00 00 00 WW WW HH HH -fb ff ff ff -f4 ff ff ff 0b 00 00 00 1b ea 00 00 00 00 SH SH SH SH 00 SL SL SL SL - - [[ Data, rows * cols * 3 bytes ]] - -f3 ff ff ff 0f 00 00 00 1b e5 00 00 00 08 00 00 00 00 00 00 00 00 00 - 12 00 00 00 1b e1 00 00 00 0b 00 00 80 00 00 00 00 00 WW WW HH HH -fa ff ff ff 09 00 00 00 1b ee 00 00 00 02 00 00 NN - 07 00 00 00 1b 0a 00 00 00 00 00 -f9 ff ff ff -fc ff ff ff 07 00 00 00 1b 17 00 00 00 00 00 -f7 ff ff ff - - WW WW == Columns, Big Endian - HH HH == Rows, Big Endian - SL SL SL SL == Plane size, Little Endian (Rows * Cols * 3) - SH SH SH SH == Plane size, Big Endian (Rows * Cols * 3) - NN == Copies - - ************** - - Sony UP-D895 spool format: - - XX XX == cols, BE (fixed at 1280/0x500) - YY YY == rows, BE (798/0x031e,1038/0x040e,1475/0x05c3, 2484/09b4) @ 960/1280/1920/3840+4096 - SS SS SS SS == data len (rows * cols, LE) - S' S' S' S' == data len (rows * cols, BE) - NN == copies (1 -> ??) - GG GG == ??? 0000/0050/011b/04aa/05aa at each resolution. - G' == Gamma 01 (soft), 03 (hard), 02 (normal) - - 9c ff ff ff 97 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff - - 14 00 00 00 - 1b 15 00 00 00 0d 00 00 00 00 00 01 GG GG 00 00 YY YY XX XX - 0b 00 00 00 - 1b ea 00 00 00 00 S' S' S' S' 00 - SS SS SS SS - ...DATA... (rows * cols) - ff ff ff ff - 09 00 00 00 - 1b ee 00 00 00 02 00 00 NN - 0f 00 00 00 - 1b e5 00 00 00 08 00 00 00 00 00 00 00 00 00 - 0c 00 00 00 - 1b c0 00 00 00 05 00 02 00 00 01 G' - 11 00 00 00 - 1b c0 00 01 00 0a 00 02 01 00 06 00 00 00 00 00 00 - 12 00 00 00 - 1b e1 00 00 00 0b 00 00 08 00 GG GG 00 00 YY YY XX XX - 07 00 00 00 - 1b 0a 00 00 00 00 00 - fd ff ff ff f7 ff ff ff f8 ff ff ff - - ************** - - Sony UP-D897 spool format: - - NN NN == copies (00 for printer selected) - XX XX == cols (fixed @ 1280) - YY YY == rows - GG == gamma -- Table 2 == 2, Table 1 == 3, Table 3 == 1, Table 4 == 4 - DD == "dark" +- 64. - LL == "light" +- 64. - AA == "advanced" +- 32. - SS == Sharpness 0-14 - ZZ ZZ ZZ ZZ == Data length (BE) - Z` Z` Z` Z` == Data length (LE) - - - 83 ff ff ff fc ff ff ff fb ff ff ff f5 ff ff ff f1 ff ff ff f0 ff ff ff ef ff ff ff - - 07 00 00 00 - 1b 15 00 00 00 0d 00 - 0d 00 00 00 - 00 00 00 00 01 00 a2 00 00 YY YY XX XX - - 0b 00 00 00 - 1b ea 00 00 00 00 ZZ ZZ ZZ ZZ 00 - - Z` Z` Z` Z` - ...DATA... - - ea ff ff ff - - 07 00 00 00 - 1b ee 00 00 00 02 00 - 02 00 00 00 - 00 NN - - ee ff ff ff 01 00 00 00 - - 07 00 00 00 - 1b e5 00 00 00 08 00 - 08 00 00 00 - 00 00 00 00 DD LL SS AA - - eb ff ff ff ?? 00 00 00 <--- 02/05 5 at #3, 2 otherwise. Sharpness? - - 07 00 00 00 - 1b c0 00 00 00 05 00 - 05 00 00 00 - 02 00 00 01 GG - - ec ff ff ff ?? 00 00 00 <--- 01/00/02/01/01 Seen. Unknown. - - 07 00 00 00 - 1b c0 00 01 00 0a 00 - 0a 00 00 00 - 02 01 00 06 00 00 00 00 00 00 - - ed ff ff ff 00 00 00 00 - - 07 00 00 00 - 1b e1 00 00 00 0b 00 - 0b 00 00 00 - 00 08 00 00 a2 00 00 YY YY XX XX - - fa ff ff ff - - 07 00 00 00 - 1b 0a 00 00 00 00 00 - - fc ff ff ff - fd ff ff ff - ff ff ff ff - - 07 00 00 00 - 1b 17 00 00 00 00 00 - - f4 ff ff ff - -*/ diff --git a/src/cups/blacklist b/src/cups/blacklist index 157fd47..7bd61c6 100644 --- a/src/cups/blacklist +++ b/src/cups/blacklist @@ -123,6 +123,18 @@ # Kodak 6850 0x040a 0x402b blacklist +# Kodak 7000 +0x040a 0x4035 blacklist + +# Kodak 7010/7015 +0x040a 0x4037 blacklist + +# Kodak 8800/9810 +0x040a 0x4023 blacklist + +# Kodak 8810 +0x040a 0x404d blacklist + # Kodak 605 0x040a 0x402e blacklist @@ -135,6 +147,9 @@ # Shinko CHC-S2145 (aka Sinfonia S2) 0x10ce 0x000e blacklist +# Shinko CHC-S2245 (aka Sinfonia S3) +0x10ce 0x0039 blacklist + # Shinko CHC-S6145 (aka Sinfonia CS2) 0x10ce 0x0019 blacklist @@ -150,6 +165,12 @@ # Sony UP-CR10L 0x054c 0x0226 blacklist +# Sony UP-D895 +0x054c 0x0049 blacklist + +# Sony UP-D897 +0x054c 0x01e7 blacklist + # Mitsubishi CP-D70DW/CP-D707DW 0x06d3 0x3b30 blacklist @@ -226,6 +247,9 @@ # Fujifilm ASK-300 0x04cb 0x5006 blacklist +# HiTi M610 +0x0d16 0x0010 blacklist + # HiTi P910L 0x0d16 0x000e blacklist diff --git a/src/cups/cups-genppd.c b/src/cups/cups-genppd.c index fde7c46..f8791fa 100644 --- a/src/cups/cups-genppd.c +++ b/src/cups/cups-genppd.c @@ -70,6 +70,8 @@ main(int argc, /* I - Number of command-line arguments */ no color opts = 4 */ unsigned parallel = 1; /* Generate PPD files in parallel */ unsigned rotor = 0; /* Rotor for generating PPD files in parallel */ + unsigned test_rotor = 0; /* Testing (serialized) rotor */ + unsigned test_rotor_circumference = 1; /* Testing (serialized) rotor size */ pid_t *subprocesses = NULL; int parent = 1; #ifdef HAVE_LIBZ @@ -88,7 +90,7 @@ main(int argc, /* I - Number of command-line arguments */ for (;;) { - if ((i = getopt(argc, argv, "23hvqc:p:l:LMVd:saNCbZzS")) == -1) + if ((i = getopt(argc, argv, "23hvqc:p:l:LMVd:saNCbZzSr:R:")) == -1) break; switch (i) @@ -175,12 +177,23 @@ main(int argc, /* I - Number of command-line arguments */ case 'S': skip_duplicate_ppds = 1; break; + case 'r': + test_rotor = atoi(optarg); + break; + case 'R': + test_rotor_circumference = atoi(optarg); + break; default: usage(); exit(EXIT_FAILURE); break; } } + if (test_rotor_circumference < 1 || test_rotor >= test_rotor_circumference) + { + test_rotor = 0; + test_rotor_circumference = 1; + } #ifdef HAVE_LIBZ if (use_compression) gpext = ".gz"; @@ -280,6 +293,7 @@ main(int argc, /* I - Number of command-line arguments */ } else { + int test_rotor_current = -1; stp_string_list_t *seen_models = NULL; if (skip_duplicate_ppds) seen_models = stp_string_list_create(); @@ -287,6 +301,7 @@ main(int argc, /* I - Number of command-line arguments */ for (i = 0; i < stp_printer_model_count(); i++) { printer = stp_get_printer_by_index(i); + test_rotor_current++; if (skip_duplicate_ppds) { char model_family[128]; @@ -299,7 +314,8 @@ main(int argc, /* I - Number of command-line arguments */ stp_string_list_add_string_unsafe(seen_models, model_family, model_family); } - + if (test_rotor_current % test_rotor_circumference != test_rotor) + continue; if (i % parallel == rotor && printer) { if (! verbose && (i % 100) == 0) @@ -488,6 +504,9 @@ help(void) " -Z Don't compress PPD files.\n" #endif " -S Skip PPD files with duplicate model identifiers.\n" + " -R size Generate every size'th PPD file.\n" + " -r divisor Generate the PPD files (N % size == divisor).\n" + "\n" "models:\n" " A list of printer models, either the driver or quoted full name.\n"); } diff --git a/src/cups/gutenprint.c b/src/cups/gutenprint.c index 6ab2194..56b5599 100644 --- a/src/cups/gutenprint.c +++ b/src/cups/gutenprint.c @@ -122,7 +122,7 @@ cat_ppd(const char *uri) /* I - Driver URI */ const char *lang = NULL; char *s; char filename[1024], /* Filename */ - ppd_location[1024]; /* Installed location */ + ppd_location[2048]; /* Installed location */ const char *infix = ""; ppd_type_t ppd_type = PPD_STANDARD; gpfile outFD; diff --git a/src/cups/test-ppds.in b/src/cups/test-ppds.test.in index 3664f4e..84dfbfc 100644 --- a/src/cups/test-ppds.in +++ b/src/cups/test-ppds.test.in @@ -39,30 +39,36 @@ if [[ -n "$STP_TEST_LOG_PREFIX" ]] ; then exec 2>&1 fi -[[ -n "$STP_TEST_DEBUG" ]] && DEBUG=echo +DEBUG=${STP_TEST_DEBUG:+echo} [[ -z $STP_TEST_SUITE || -z $STP_TEST_PROFILE ]] && STP_TEST_PROFILE=full +[[ -n $STP_TEST_COMPONENTS && $STP_TEST_COMPONENTS != '*CUPS*' && $STP_TEST_COMPONENTS != '*test-ppds*' ]] && exit 77 + PPD_DIR=ppdtest PPD_PARALLEL=200 +echo '****************************************************************' + +rotor="-R ${STP_TEST_ROTOR_CIRCUMFERENCE:-1} -r ${STP_TEST_ROTOR:-0}" + function test_full() { rm -rf "$PPD_DIR" echo "GENERATING PPD FILES (all):" set -e - $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS='-b -Z' ppd-clean ppd-global-a ppd-nls-a ppd-nonls-a + $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS="$rotor -b -Z" ppd-clean ppd-global-a ppd-nls-a ppd-nonls-a } function test_fast() { rm -rf "$PPD_DIR" echo "GENERATING PPD FILES (fast):" set -e - $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS='-b -Z' ppd-clean ppd-nonls + $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS="$rotor -b -Z" ppd-clean ppd-nonls if [[ -n $STP_TEST_DIST ]] ; then echo "GENERATING PPD FILES (global):" set -e - $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS='-b -Z -S' ppd-global + $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS="$rotor -b -Z -S" ppd-global fi PPD_PARALLEL=20 } @@ -71,7 +77,7 @@ function test_minimal() { rm -rf "$PPD_DIR" echo "GENERATING PPD FILES (minimal):" set -e - $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS='-b -Z -S' ppd-clean ppd-nonls + $DEBUG make "PPD_DIR=$PPD_DIR" EXTRA_GENPPD_OPTS="$rotor -b -Z -S" ppd-clean ppd-nonls PPD_PARALLEL=20 } @@ -84,7 +90,7 @@ case "$STP_TEST_PROFILE" in esac if [[ -n "$STP_TEST_DEBUG" ]] ; then - echo "Would run $0 $@" + echo "Would run $0 $*" exit 0 fi @@ -120,7 +126,7 @@ fi # Use this with PPD files with translated numbers (genppd -N) # With normal globalized PPD files this will yield hundreds of megabytes # of errors. -echo $failures | xargs cupstestppd -r $cupstestppdopts 2>&1 +echo "$failures" | xargs cupstestppd -r $cupstestppdopts 2>&1 fail_count=`echo "$failures" | wc -l` echo "$fail_count/$ppd_count fail" diff --git a/src/cups/test-rastertogutenprint.in b/src/cups/test-rastertogutenprint.in index 410814d..0d9f761 100644 --- a/src/cups/test-rastertogutenprint.in +++ b/src/cups/test-rastertogutenprint.in @@ -37,10 +37,11 @@ declare make_ppds=1 declare skip_simplified=0 declare postscript=0 declare use_explicit_quality=0 -declare extra_genppd_opts=-Z +declare extra_genppd_opts="-Z" declare use_smallest_pagesize=0 declare cupsargs='' -declare printers_to_test='' +declare -a printers_to_test +declare dontrun=0 if [ -n "$STP_TEST_DEBUG" ] ; then echo "Would run with single=$single skip_simplified=$skip_simplified extra_genppd_opts=$extra_genppd_opts cupsargs=$cupsargs use_explicit_quality=$use_explicit_quality valopts=$valopts valgrind=$valgrind" @@ -86,11 +87,12 @@ Usage: test-rastertogutenprint [options] [PPD files...] -L Use highest available quality setting -X Don't use explicit quality setting -N Use the smallest available page size + -d Don't actually run the command EOF exit 0; } -while getopts "hvcgsVnO:m:o:p:St:lLXf:N" opt ; do +while getopts "hvcgsVnO:m:o:p:PSt:lLXf:Nd" opt ; do case "$opt" in h*) usage ;; v) valgrind=$((valgrind + 1)) ;; @@ -98,7 +100,7 @@ while getopts "hvcgsVnO:m:o:p:St:lLXf:N" opt ; do g) valopts='--vgdb=yes --error-exitcode=1' ;; s) single=1 ;; V) verbose=$((verbose+1)) ;; - n) make_ppds='' ;; + n) make_ppds=0 ;; O) outdir="$OPTARG"; mkdir -p "$outdir" ;; o) cupsargs="$cupsargs $OPTARG" ;; m) md5dir="$OPTARG"; mkdir -p "$md5dir" ;; @@ -111,11 +113,15 @@ while getopts "hvcgsVnO:m:o:p:St:lLXf:N" opt ; do l) use_explicit_quality=1 ;; L) use_explicit_quality=2 ;; N) use_smallest_pagesize=1 ;; + d) dontrun=1 ;; \?) usage ;; *) echo "Unknown argument $opt"; usage ;; esac done +STP_TEST_ROTOR=${STP_TEST_ROTOR:-0} +STP_TEST_ROTOR_CIRCUMFERENCE=${STP_TEST_ROTOR_CIRCUMFERENCE:-1} + case "$valgrind" in 4) valopts='--tool=callgrind --dump-instr=yes --trace-jump=yes --error-exitcode=1' @@ -129,6 +135,25 @@ esac shift $((OPTIND - 1)) +if (( $# > 0 )) ; then + single=0 + for i in $(seq 1 $#) ; do + (( (i - 1) % $STP_TEST_ROTOR_CIRCUMFERENCE == $STP_TEST_ROTOR )) && printers_to_test+=($1) + shift + done + (( ${#printers_to_test[@]} == 0 )) && exit 77 +fi + +(( single > 0 )) && extra_genppd_opts="$extra_genppd_opts -S" + +if (( STP_TEST_ROTOR_CIRCUMFERENCE > 1 && + STP_TEST_ROTOR >= 0 && + STP_TEST_ROTOR < STP_TEST_ROTOR_CIRCUMFERENCE )) ; then + extra_genppd_opts="$extra_genppd_opts -R $STP_TEST_ROTOR_CIRCUMFERENCE -r $STP_TEST_ROTOR" + STP_TEST_ROTOR=0 + STP_TEST_ROTOR_CIRCUMFERENCE=1 +fi + version="@GUTENPRINT_RELEASE_VERSION@"; rgp="./rastertogutenprint.$version" cupsdir="$(cups-config --serverbin)/filter" @@ -145,8 +170,8 @@ if [[ ! -x $cgpdftoraster && ! -x $pdftops && ! -x $gstoraster ]] ; then fi if [[ -x $pstoraster || -x $gstoraster || -x $cgpdftoraster ]] ; then - pages="24-$((24 + $npages - 1))" - (( $postscript > 0 )) && pages="page-ranges=$pages" + pages="24-$((24 + npages - 1))" + (( postscript > 0 )) && pages="page-ranges=$pages" else pages='' fi @@ -157,20 +182,20 @@ cleanup() { } pdfjam=$(type -p pdfjam) -[[ -n $pdfjam ]] && postscript=1 +[[ -z $pdfjam ]] && postscript=1 -if (( $postscript > 0 )) ; then +if (( postscript > 0 )) ; then pdftops=$(type -p pdftops) if [[ -n $pdftops && ! -x $cgpdftoraster ]] ; then tfile=$(mktemp) trap cleanup 1 2 3 6 14 15 30 - "$pdftops" -f 24 -l $((24 + $npages - 1)) "$testfile" $tfile + "$pdftops" -f 24 -l $((24 + npages - 1)) "$testfile" "$tfile" fi else tfile=$(mktemp) trap cleanup 1 2 3 6 14 15 30 - "$pdfjam" -q "$testfile" "$pages" -o $tfile + "$pdfjam" -q "$testfile" "$pages" -o "$tfile" fi case "$verbose" in @@ -193,10 +218,10 @@ esac #cupsargs='PageSize=A8' get_ppds() { - if [[ -n $@ || -n $printers_to_test ]] ; then - for f in "$@" $printers_to_test ; do + if [[ -n $* ]] ; then + for f in "$@" ; do if [[ -r $f ]] ; then - echo $f + echo "$f" elif [[ -r ppd/C/$f ]] ; then echo "ppd/C/$f" elif [[ -f ppd/C/${f}.ppd ]] ; then @@ -248,19 +273,21 @@ get_ppds() { fi } -if [[ -n $make_ppds || ! -d ppd/C ]] ; then +if [[ $make_ppds -gt 0 || ! -d ppd/C ]] ; then rm -rf ppd/C ## not all systems can work with gzipped PPDs + extra_genppd_opts="$extra_genppd_opts ${printers_to_test[*]}" if [[ $skip_simplified == 1 ]] ; then - EXTRA_GENPPD_OPTS="$extra_genppd_opts" make ppd-nonls + echo make ppd-nonls EXTRA_GENPPD_OPTS="$extra_genppd_opts" + make ppd-nonls EXTRA_GENPPD_OPTS="$extra_genppd_opts" else - EXTRA_GENPPD_OPTS="$extra_genppd_opts" make ppd-nonls-a + make ppd-nonls-a EXTRA_GENPPD_OPTS="$extra_genppd_opts" fi fi find_page_size() { ppd=$1 - (( $use_smallest_pagesize == 0 )) && return; + (( use_smallest_pagesize == 0 )) && return; driver=$(grep '^\*StpDriverName' "$ppd" | sed -e 's/^[^"]*"//' -e 's/"//g') pagesize=$(./min-pagesize "$driver") [[ -n "$pagesize" ]] && echo "PageSize=$pagesize" @@ -275,20 +302,20 @@ find_resolution() { high_resolution=0 high_resolution_name='' for r in $resolutions ; do - res=$(sed -e 's/dpi//' -e 's/x/ \\\* /' -e 's/^\([0-9]*\)$/\1 \\\* \1/' <<< $r) + res=$(sed -e 's/dpi//' -e 's/x/ \\\* /' -e 's/^\([0-9]*\)$/\1 \\\* \1/' <<< "$r") resnum=$(eval "expr $res") - if (( $resnum > $high_resolution )) ; then + if (( resnum > high_resolution )) ; then high_resolution=$resnum high_resolution_name=$r fi - if (( $resnum < $low_resolution )) ; then + if (( resnum < low_resolution )) ; then low_resolution=$resnum low_resolution_name=$r fi done - if (( $use_explicit_quality == 1 )) ; then + if (( use_explicit_quality == 1 )) ; then echo "Resolution=$low_resolution_name" - elif (( $use_explicit_quality == 2 )) ; then + elif (( use_explicit_quality == 2 )) ; then echo "Resolution=$high_resolution_name" fi @@ -296,16 +323,16 @@ find_resolution() { find_quality_preset() { ppd=$1 - if (( $use_explicit_quality == 1 )) ; then - for q in ${quality_presets[@]} ; do + if (( use_explicit_quality == 1 )) ; then + for q in "${quality_presets[@]}" ; do if grep -q "^\\*StpQuality $q" "$ppd" ; then echo "StpQuality=$q" return fi done - elif (( "$use_explicit_quality" == 2 )) ; then + elif (( use_explicit_quality == 2 )) ; then best_quality='' - for q in ${quality_presets[@]} ; do + for q in "${quality_presets[@]}" ; do grep -q "^\\*StpQuality $q" "$ppd" && best_quality=$q done [[ -n $best_quality ]] && echo "StpQuality=$best_quality" @@ -318,11 +345,11 @@ find_quality() { echo "Can't find $ppd!" 1>&2 exit 1; fi - (( "$use_explicit_quality" == 0 )) && return + (( use_explicit_quality == 0 )) && return if grep -q '\*Resolution' "$ppd" ; then - find_resolution $ppd + find_resolution "$ppd" else - find_quality_preset $ppd + find_quality_preset "$ppd" fi } @@ -330,30 +357,30 @@ xgrep() { pat=$1 file=$2 if [[ $file == *.gz ]] ; then - egrep -m1 $pat $file + grep -E -m1 "$pat" "$file" else - zgrep $pat $file + zgrep "$pat" "$file" fi } runcmd() { qualarg=$(find_quality "$PPD") sizearg=$(find_page_size "$PPD") - a='1 1 1 1' + a=(1 1 1 1) qarg="$qualarg $sizearg $cupsargs" if [[ -x $cgpdftoraster ]] ; then # cgpdftoraster doesn't like arguments. How rude. - $cgpdftoraster $a "" < "$tfile" + $cgpdftoraster "${a[@]}" "" < "$tfile" elif [[ -f $tfile && -x $gstoraster ]] ; then - $gstoraster $a "$qarg" < "$tfile" + $gstoraster "${a[@]}" "$qarg" < "$tfile" elif [[ -f $tfile ]] ; then - $pstops $a $"qarg" < "$tfile" + $pstops "${a[@]}" $"qarg" < "$tfile" elif [[ -x $pstoraster ]] ; then - $pdftops $a "$qarg" < "$tfile" | $pstops $a "$pages$qarg" | $pstoraster + $pdftops "${a[@]}" "$qarg" < "$tfile" | $pstops "${a[@]}" "$pages$qarg" | $pstoraster elif [[ -x $gstoraster ]] ; then - $pdftops $a "$qarg" < "$tfile" | $gstoraster $a "$pages$qarg" + $pdftops "${a[@]}" "$qarg" < "$tfile" | $gstoraster "${a[@]}" "$pages$qarg" else - $imagetoraster $a "$qarg" < calibrate.ppm + $imagetoraster "${a[@]}" "$qarg" < calibrate.ppm fi } @@ -385,19 +412,22 @@ run_rastertogp() { 4) $vg $rgpc "$qarg" ;; 5) cat ;; 6) cat > /dev/null ;; - *) $rgp 1 1 1 1 "$qarg" + *) $rgpc "$qarg" esac } runme() { f="$1" + m=${all_models[$f]} p=${f#*stp-} p=${p/${version}./} export PPD=$f - if [[ -n $outdir || -n $md5dir ]] ; then - output="${p%.ppd*}...$( (runcmd 2>/dev/null | run_rastertogp | do_output) 2>&1 3>&2)" + if (( dontrun > 0 )) ; then + output="${p%.ppd*} ($m)" + elif [[ -n $outdir || -n $md5dir ]] ; then + output="${p%.ppd*} ($m)...$( (runcmd 2>/dev/null | run_rastertogp | do_output) 2>&1 3>&2)" else - output="${p%.ppd*}...$( (runcmd 2>/dev/null | run_rastertogp >/dev/null) 2>&1 3>&2)" + output="${p%.ppd*} ($m)...$( (runcmd 2>/dev/null | run_rastertogp >/dev/null) 2>&1 3>&2)" fi return $? } @@ -409,13 +439,12 @@ runall() { retval=0 jobno=0 for f in "$@" ; do - if (( $jobno == $rotor )) ; then - runme "$f" - (( $? != 0 )) && retval=1 + if (( jobno == rotor )) ; then + runme "$f" || retval=1 echo "$output" grep -q 'ERROR:' <<< "$output" && retval=1 fi - jobno=$((($jobno+1) % $jobs)) + jobno=$(((jobno+1) % jobs)) done return $retval } @@ -423,8 +452,8 @@ runall() { get_models() { re='\*StpDriverModelFamily: ' if (( ${#all_models[*]} <= 1 )) ; then - declare -a models=($(xargs grep -m1 -H "^$re" <<< $@ | sed "s/:$re/=/")) - for m in ${models[@]} ; do + declare -a models=($(xargs grep -m1 -H "^$re" <<< "$*" | sed "s/:$re/=/")) + for m in "${models[@]}" ; do model=${m#*=} file=${m%%=*} all_models[$file]=$model @@ -434,50 +463,48 @@ get_models() { retval=0 if [[ -d ppd/C ]] ; then - declare -a files=($(get_ppds "$@")) + declare -a files=($(get_ppds)) declare -A models declare -a nfiles - if (( $skip_simplified > 0 )) ; then - for f in ${files[@]} ; do - [[ $f != *.sim.ppd* ]] && nfiles+=($f) + if (( skip_simplified > 0 )) ; then + for f in "${files[@]}" ; do + [[ $f != *.sim.ppd* ]] && nfiles+=("$f") done - files=(${nfiles[@]}) + files=("${nfiles[@]}") fi + get_models "${files[@]}" if [[ -n $family ]] ; then - get_models ${files[@]} nfiles=() - for f in ${files[@]} ; do - [[ ${all_models[$f]} =~ $family ]] && nfiles+=($f) + for f in "${files[@]}" ; do + [[ ${all_models[$f]} =~ $family ]] && nfiles+=("$f") done - files=(${nfiles[@]}) + files=("${nfiles[@]}") fi - if (( $single != 0 )) ; then + if (( single != 0 )) ; then declare -A seen_models nfiles=() - get_models ${files[@]} - for f in ${files[@]} ; do + get_models "${files[@]}" + for f in "${files[@]}" ; do model=${all_models[$f]} [[ $f == *.sim.ppd ]] && model="${model}_sim" if [[ -z ${seen_models[$model]} ]] ; then - nfiles+=($f) + nfiles+=("$f") seen_models[$model]=1 fi done - files=(${nfiles[@]}) + files=("${nfiles[@]}") fi - (( ${#files[@]} < $jobs )) && jobs=${#files[@]} - declare -a subproc=($(seq 0 $((jobs-1)))) + (( ${#files[@]} < jobs )) && jobs=${#files[@]} # Fire 'em off in the background... - for i in ${subproc[@]} ; do - runall $jobs $i ${files[@]} & + for i in $(seq 0 $((jobs-1))) ; do + runall "$jobs" "$i" "${files[@]}" & done # And wait for them to complete. - for i in ${subproc[@]} ; do - wait -n - (( $? != 0 )) && retval=1 + for i in $(seq 0 $((jobs-1))) ; do + wait -n || retval=1 done fi [[ -n $tfile ]] && rm -f "$tfile" -(( $retval == 0 )) && rm -rf ppd/C && rmdir ppd -exit $retval +(( retval == 0 && make_ppds > 0 )) && rm -rf ppd/C && rmdir ppd +exit "$retval" diff --git a/src/cups/test-rastertogutenprint.check.in b/src/cups/test-rastertogutenprint.test.in index cd3f38b..e2f74f8 100644 --- a/src/cups/test-rastertogutenprint.check.in +++ b/src/cups/test-rastertogutenprint.test.in @@ -29,6 +29,8 @@ fi STP_TEST_PROFILE=${STP_TEST_PROFILE:-full} +[[ -n $STP_TEST_COMPONENTS && $STP_TEST_COMPONENTS != '*CUPS*' && $STP_TEST_COMPONENTS != '*test-rastertogutenprint*' ]] && exit 77 + set -e declare FASTOPT="-o StpDitherAlgorithm=VeryFast -l -N -o ColorCorrection=Raw" @@ -69,7 +71,7 @@ function test_valgrind() { case "$STP_TEST_PROFILE" in full|fast|valgrind|valgrind_minimal|valgrind_fast|minimal) - test_$STP_TEST_PROFILE + test_"$STP_TEST_PROFILE" ;; *) exit 77 |