summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2019-04-17 13:58:42 -0400
committerSolomon Peachy <pizza@shaftnet.org>2019-04-17 13:58:42 -0400
commitfcb54b904000ec71dbd685e73d9fed1585c97473 (patch)
tree00c56795133f9c42cd14e7b637b4ffdada0df00b
parent07c2783d2cae3f8dedb5e38de95102166300a42b (diff)
downloadselphy_print-fcb54b904000ec71dbd685e73d9fed1585c97473.tar.gz
selphy_print-fcb54b904000ec71dbd685e73d9fed1585c97473.tar.bz2
selphy_print-fcb54b904000ec71dbd685e73d9fed1585c97473.zip
sonyupdneo: Add WIP backend for newer Sony printers
Covers these models: * UP-DR80MD * UP-CR20SL * UP-D898 / UP-X898 Includes sample files generated by Windows drivers. Note that I do not have USB VID/PIDs for any these models, and the post-parsing code has not been tested.
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--backend_common.c2
-rw-r--r--backend_common.h3
-rw-r--r--backend_sonyupd.c2
-rw-r--r--backend_sonyupdneo.c354
-rw-r--r--regression.csv20
-rw-r--r--testjobs/sony_upcr20l_4x6.rawbin0 -> 6274101 bytes
-rw-r--r--testjobs/sony_upd898-1280x960.rawbin0 -> 658101 bytes
-rw-r--r--testjobs/sony_updr80md-a4.rawbin0 -> 24399861 bytes
10 files changed, 374 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 1b6d6d7..febaba0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
*.so
sonyupd
+sonyupdneo
kodak6800
kodak605
kodak1400
diff --git a/Makefile b/Makefile
index 55b8e17..5304004 100644
--- a/Makefile
+++ b/Makefile
@@ -52,7 +52,7 @@ CPPFLAGS += -DURI_PREFIX=\"$(BACKEND_NAME)\" $(OLD_URI)
CFLAGS += -funit-at-a-time
# List of backends
-BACKENDS = sonyupd kodak6800 kodak1400 shinkos2145 shinkos1245 canonselphy mitsu70x kodak605 dnpds40 mitsu9550 shinkos6245 shinkos6145 canonselphyneo mitsup95d magicard mitsud90
+BACKENDS = sonyupd sonyupdneo kodak6800 kodak1400 shinkos2145 shinkos1245 canonselphy mitsu70x kodak605 dnpds40 mitsu9550 shinkos6245 shinkos6145 canonselphyneo mitsup95d magicard mitsud90
# For the s6145 and mitsu70x backends
CPPFLAGS += -DUSE_DLOPEN
diff --git a/backend_common.c b/backend_common.c
index c2ab330..218e572 100644
--- a/backend_common.c
+++ b/backend_common.c
@@ -667,6 +667,7 @@ abort:
}
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;
@@ -694,6 +695,7 @@ static struct dyesub_backend *backends[] = {
&shinkos6145_backend,
&shinkos6245_backend,
&sonyupd_backend,
+ &sonyupdneo_backend,
&mitsu70x_backend,
&mitsud90_backend,
&mitsu9550_backend,
diff --git a/backend_common.h b/backend_common.h
index 555c896..821fd5d 100644
--- a/backend_common.h
+++ b/backend_common.h
@@ -155,6 +155,9 @@ enum {
P_MAGICARD = 43,
P_SONY_UPD895 = 44,
P_SONY_UPD897 = 45,
+ P_SONY_UPD898 = 46,
+ P_SONY_UPCR20L = 47,
+ P_SONY_UPDR80 = 48,
P_END,
};
diff --git a/backend_sonyupd.c b/backend_sonyupd.c
index 3153bb4..03c594c 100644
--- a/backend_sonyupd.c
+++ b/backend_sonyupd.c
@@ -606,7 +606,6 @@ static const char *sonyupd_prefixes[] = {
#define USB_PID_SONY_UPCR10 0x0226
#define USB_PID_SONY_UPD895 0x0049
#define USB_PID_SONY_UPD897 0x01E7
-//#define USB_PID_SONY_UPD898 XXXXX // 0x589a?
struct dyesub_backend sonyupd_backend = {
.name = "Sony UP-D",
@@ -627,7 +626,6 @@ struct dyesub_backend sonyupd_backend = {
{ 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"},
-// { USB_VID_SONY, USB_PID_SONY_UPD898MD, P_SONY_UPD89x, NULL, "sonyupd898"},
{ 0, 0, 0, NULL, NULL}
}
};
diff --git a/backend_sonyupdneo.c b/backend_sonyupdneo.c
new file mode 100644
index 0000000..cbdbc86
--- /dev/null
+++ b/backend_sonyupdneo.c
@@ -0,0 +1,354 @@
+/*
+ * Sony UP-D series (new) Photo Printer CUPS backend -- libusb-1.0 version
+ *
+ * (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 3 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-3.0.html]
+ *
+ * SPDX-License-Identifier: GPL-3.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 sonyupdneo_backend
+
+#include "backend_common.h"
+
+/* Private data structures */
+struct updneo_printjob {
+ uint8_t *databuf;
+ int datalen;
+
+ int copies_offset;
+ int payload_offset;
+
+ int copies;
+
+ uint16_t rows;
+ uint16_t cols;
+};
+
+struct updneo_ctx {
+ struct libusb_device_handle *dev;
+ uint8_t endp_up;
+ uint8_t endp_down;
+ int type;
+
+ int native_bpp;
+
+ struct marker marker;
+};
+
+/* Now for the code */
+static void* updneo_init(void)
+{
+ struct updneo_ctx *ctx = malloc(sizeof(struct updneo_ctx));
+ if (!ctx) {
+ ERROR("Memory Allocation Failure!");
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(struct updneo_ctx));
+ return ctx;
+}
+
+static int updneo_attach(void *vctx, struct libusb_device_handle *dev, int type,
+ uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
+{
+ struct updneo_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_UPD898) {
+ 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 updneo_cleanup_job(const void *vjob)
+{
+ const struct updneo_printjob *job = vjob;
+
+ if (job->databuf)
+ free(job->databuf);
+
+ free((void*)job);
+}
+
+static void updneo_teardown(void *vctx) {
+ struct updneo_ctx *ctx = vctx;
+
+ if (!ctx)
+ return;
+
+ free(ctx);
+}
+
+#define MAX_PRINTJOB_LEN (3400*2392*3 + 2048)
+
+static int updneo_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
+ struct updneo_ctx *ctx = vctx;
+ int len, run = 1;
+
+ struct updneo_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");
+ updneo_cleanup_job(job);
+ return CUPS_BACKEND_RETRY_CURRENT;
+ }
+
+ /* Read in data chunks. */
+ while(run) {
+ int i;
+
+ /* Read in data block header (256 bytes) */
+ i = read(data_fd, job->databuf + job->datalen, 256);
+ if (i < 0) {
+ updneo_cleanup_job(job);
+ return CUPS_BACKEND_CANCEL;
+ }
+ if (i == 0)
+ break;
+
+ /* Explicitly null terminate */
+ job->databuf[job->datalen + 255] = 0;
+
+ /* Parse header. Format:
+
+ JOBSIZE=pdlname,blocklen,printsize,arg1,..,argN<NULL>
+
+ */
+
+ if (strncmp("JOBSIZE=", (char*) job->databuf + job->datalen, 8)) {
+ ERROR("Invalid spool format!\n");
+ return CUPS_BACKEND_CANCEL;
+ }
+ i = 0;
+
+ /* PDL */
+ char *tok = strtok((char*)job->databuf + job->datalen + 8, "\r\n,");
+ if (!tok) {
+ ERROR("Invalid spool format (PDL)!\n");
+ return CUPS_BACKEND_CANCEL;
+ }
+
+ /* Behavior based on the various blocks */
+ if (!strncmp("PJL-T", tok, 5))
+ run = 1;
+ else if (!strncmp("SONY-PDL-DS2", tok, 12))
+ job->payload_offset = job->datalen;
+
+// DEBUG("Read block '%s' @ %d ...\n", tok, job->datalen);
+
+ /* Payload length */
+ tok = strtok(NULL, "\r\n,");
+ if (!tok) {
+ ERROR("Invalid spool format (block length missing)!\n");
+ return CUPS_BACKEND_CANCEL;
+ }
+ len = atoi(tok);
+ if (len == 0 || len > MAX_PRINTJOB_LEN) {
+ ERROR("Invalid spool format (block length %d)!\n", len);
+ return CUPS_BACKEND_CANCEL;
+ }
+// DEBUG("...len '%d'\n", len);
+
+ // parse the rest?
+ // 898MD: 6,0,0,0
+ // D80MD: 4
+ // CR20L: 64,0,0,0
+
+ /* Read in the data chunk */
+ while(len > 0) {
+ i = read(data_fd, job->databuf + job->datalen, len);
+ if (i < 0) {
+ updneo_cleanup_job(job);
+ return CUPS_BACKEND_CANCEL;
+ }
+ if (i == 0)
+ break;
+
+ job->datalen += i;
+ len -= i;
+ }
+ }
+
+ if (!job->datalen) {
+ updneo_cleanup_job(job);
+ return CUPS_BACKEND_CANCEL;
+ }
+
+ /* Sanity check job parameters */
+ // rows * cols lines up with imgsize, and others?
+
+ *vjob = job;
+
+ return CUPS_BACKEND_OK;
+}
+
+static int updneo_main_loop(void *vctx, const void *vjob) {
+ struct updneo_ctx *ctx = vctx;
+ int ret;
+ int copies;
+
+ const struct updneo_printjob *job = vjob;
+
+ if (!ctx)
+ return CUPS_BACKEND_FAILED;
+ if (!job)
+ return CUPS_BACKEND_FAILED;
+
+ copies = job->copies;
+
+top:
+
+ // Query printer status
+ // Sanity check job parameters vs printer status
+ // Check for idle
+
+ // send over job
+ if ((ret = send_data(ctx->dev, ctx->endp_down,
+ job->databuf, job->datalen)))
+ return CUPS_BACKEND_FAILED;
+
+ /* Wait for completion! */
+retry:
+ sleep(1);
+
+ // Check for idle
+ if (fast_return /*&& ctx->stsbuf.printing > 0 */) {
+ 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 updneo_cmdline_arg(void *vctx, int argc, char **argv)
+{
+ struct updneo_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
+ }
+
+ if (j) return j;
+ }
+
+ return 0;
+}
+
+static int updneo_query_markers(void *vctx, struct marker **markers, int *count)
+{
+ struct updneo_ctx *ctx = vctx;
+
+ *markers = &ctx->marker;
+ *count = 1;
+
+ // Do something?
+
+ return CUPS_BACKEND_OK;
+}
+
+static const char *sonyupdneo_prefixes[] = {
+ "sonyupdneo",
+ "sony-upd898", "sony-upcr20l", "sony-updr80",
+ NULL
+};
+
+/* Exported */
+#define USB_VID_SONY 0x054C
+#define USB_PID_SONY_UPD898MD 0xabcd // 0x589a?
+#define USB_PID_SONY_UPCR20L 0xbcde
+#define USB_PID_SONY_UPDR80MD 0xcdef
+
+struct dyesub_backend sonyupdneo_backend = {
+ .name = "Sony UP-D Neo",
+ .version = "0.01WIP",
+ .uri_prefixes = sonyupdneo_prefixes,
+ .cmdline_arg = updneo_cmdline_arg,
+ .init = updneo_init,
+ .attach = updneo_attach,
+ .teardown = updneo_teardown,
+ .cleanup_job = updneo_cleanup_job,
+ .read_parse = updneo_read_parse,
+ .main_loop = updneo_main_loop,
+ .query_markers = updneo_query_markers,
+ .devices = {
+ { USB_VID_SONY, USB_PID_SONY_UPD898MD, P_SONY_UPD898, NULL, "sony-upd898"},
+ { USB_VID_SONY, USB_PID_SONY_UPCR20L, P_SONY_UPCR20L, NULL, "sony-upcr20l"},
+ { USB_VID_SONY, USB_PID_SONY_UPDR80MD, P_SONY_UPDR80, NULL, "sony-upd80"},
+ { 0, 0, 0, NULL, NULL}
+ }
+};
diff --git a/regression.csv b/regression.csv
index d455e71..1fbb414 100644
--- a/regression.csv
+++ b/regression.csv
@@ -91,18 +91,24 @@ shinkos6245,0x10ce,0x001d,shinko_s6245_8x10.raw,0x11
shinkos6245,0x10ce,0x001d,shinko_s6245_8x10.raw,0x12
hitip910,0x0d16,0x000e,shinko_s6245_8x10.raw,0x11
#
-# 'sonyupdr150'
+# 'sonyupd'
#
sonyupcr10,0x054c,0x0226,sony_upcr10l_4x6.raw,
-sonyupdr150,0x054c,0x01e8,sony_updr150_4x6.raw,
-sonyupdr150,0x054c,0x01e8,sony_updr150_8x6.raw,
-sonyupdr200,0x054c,0x035f,sony_updr200_2x6.raw,
-sonyupdr200,0x054c,0x035f,sony_updr200_4x6.raw,
-sony-upd895,0x054c,0x0049,sony_upd895-1280x960.raw,
-sony-upd895,0x054c,0x0049,sony_upd895-1280x1280.raw,
+sonyupdr150,0x054c,0x01e8,sony_updr150_4x6.raw,
+sonyupdr150,0x054c,0x01e8,sony_updr150_8x6.raw,
+sonyupdr200,0x054c,0x035f,sony_updr200_2x6.raw,
+sonyupdr200,0x054c,0x035f,sony_updr200_4x6.raw,
+sony-upd895,0x054c,0x0049,sony_upd895-1280x960.raw,
+sony-upd895,0x054c,0x0049,sony_upd895-1280x1280.raw,
sony-upd897,0x054c,0x01e7,sony_upd897-1280x960.raw,
sony-upd897,0x054c,0x01e7,sony_upd897-1280x1280.raw,
#
+# 'sonyupdneo'
+#
+sony-updr80,0x054c,0xcdef,sony_updr80md-a4.raw,
+sony-upcr20l,0x054c,0xbcde,sony_upcr20l_4x6.raw,
+sony-upd898,0x054c,0xabcd,sony_upd898-1280x960.raw
+#
# 'mitsu9xxx' [9810/9820 need MATTE job]
#
#mitsu9000,0x06d3,0x0394,file_fixme,
diff --git a/testjobs/sony_upcr20l_4x6.raw b/testjobs/sony_upcr20l_4x6.raw
new file mode 100644
index 0000000..e4b17d2
--- /dev/null
+++ b/testjobs/sony_upcr20l_4x6.raw
Binary files differ
diff --git a/testjobs/sony_upd898-1280x960.raw b/testjobs/sony_upd898-1280x960.raw
new file mode 100644
index 0000000..047d5cb
--- /dev/null
+++ b/testjobs/sony_upd898-1280x960.raw
Binary files differ
diff --git a/testjobs/sony_updr80md-a4.raw b/testjobs/sony_updr80md-a4.raw
new file mode 100644
index 0000000..e16eecd
--- /dev/null
+++ b/testjobs/sony_updr80md-a4.raw
Binary files differ