shinko: Start pulling out common code into one place.

This commit is contained in:
Solomon Peachy 2019-05-06 16:28:07 -04:00
parent ed8e2f18b1
commit 16e11039c7
8 changed files with 386 additions and 431 deletions

View File

@ -61,12 +61,8 @@ LDFLAGS += -ldl
#LDFLAGS += -lltdl
# Build stuff
DEPS += backend_common.h
SOURCES = backend_common.c $(addsuffix .c,$(addprefix backend_,$(BACKENDS)))
# Backend-specific joy:
backend_mitsu70x.o: CPPFLAGS += -DCORRTABLE_PATH=\"$(BACKEND_DATA_DIR)\" -include lib70x/libMitsuD70ImageReProcess.h
backend_mitsu9550.o: CPPFLAGS += -DCORRTABLE_PATH=\"$(BACKEND_DATA_DIR)\" -include lib70x/libMitsuD70ImageReProcess.h
DEPS += backend_common.h backend_shinko.h
SOURCES = backend_common.c backend_shinko.c $(addsuffix .c,$(addprefix backend_,$(BACKENDS)))
# And now the rules!
.PHONY: clean all install cppcheck
@ -115,3 +111,8 @@ release:
cp -a *.c *.h Makefile blacklist COPYING README lib6145 D70 selphy_print-rel
tar -czvf selphy_print-rel.tar.gz selphy_print-rel
$(RM) -Rf selphy_print-rel
# Backend-specific joy:
backend_mitsu70x.o: CPPFLAGS += -DCORRTABLE_PATH=\"$(BACKEND_DATA_DIR)\" -include lib70x/libMitsuD70ImageReProcess.h
backend_mitsu9550.o: CPPFLAGS += -DCORRTABLE_PATH=\"$(BACKEND_DATA_DIR)\" -include lib70x/libMitsuD70ImageReProcess.h
#backend_shinko%.o: backend_shinko.h

View File

@ -40,6 +40,7 @@
#define BACKEND kodak605_backend
#include "backend_common.h"
#include "backend_shinko.h"
#define USB_VID_KODAK 0x040A
#define USB_PID_KODAK_605 0x402E
@ -187,27 +188,6 @@ struct kodak605_hdr {
uint8_t mode; /* Print mode -- 0x00, 0x01 seen */
} __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) {
@ -605,10 +585,10 @@ static void kodak605_dump_status(struct kodak605_ctx *ctx, struct kodak605_statu
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));
@ -710,7 +690,6 @@ static void kodak605_dump_mediainfo(struct kodak605_media_list *media)
DEBUG("\n");
}
#define UPDATE_SIZE 1536
static int kodak605_set_tonecurve(struct kodak605_ctx *ctx, char *fname)
{
libusb_device_handle *dev = ctx->dev;
@ -892,7 +871,7 @@ static const char *kodak605_prefixes[] = {
/* Exported */
struct dyesub_backend kodak605_backend = {
.name = "Kodak 605",
.version = "0.37",
.version = "0.38",
.uri_prefixes = kodak605_prefixes,
.cmdline_usage = kodak605_cmdline,
.cmdline_arg = kodak605_cmdline_arg,

193
backend_shinko.c Normal file
View File

@ -0,0 +1,193 @@
/*
* 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 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>
#include "backend_common.h"
#include "backend_shinko.h"
int sinfonia_read_parse(int data_fd, uint32_t model,
struct sinfonia_job_param *jp,
uint8_t **data, int *datalen)
{
uint32_t hdr[28];
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 */
*datalen = hdr[13] * hdr[14] * 3;
*data = malloc(*datalen);
if (!*data) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
/* Read in payload data */
{
uint32_t remain = *datalen;
uint8_t *ptr = *data;
do {
ret = read(data_fd, ptr, remain);
if (ret < 0) {
ERROR("Read failed (%d/%d/%d)\n",
ret, remain, *datalen);
perror("ERROR: Read failed");
free(*data);
*data = 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(*data);
*data = NULL;
return ret;
}
if (tmpbuf[0] != 0x04 ||
tmpbuf[1] != 0x03 ||
tmpbuf[2] != 0x02 ||
tmpbuf[3] != 0x01) {
ERROR("Unrecognized footer data format!\n");
free (*data);
*data = NULL;
return CUPS_BACKEND_CANCEL;
}
/* Fill out job params */
if (jp) {
jp->media = hdr[6];
if (hdr[1] != 6245)
jp->method = hdr[8];
if (hdr[1] == 1245 || hdr[1] == 2145)
jp->oc_mode = hdr[9];
else
jp->oc_mode = hdr[10];
if (hdr[1] == 1245)
jp->mattedepth = hdr[11];
if (hdr[1] == 1245)
jp->dust = hdr[12];
jp->rows = hdr[13];
jp->columns = hdr[14];
jp->copies = hdr[15];
if (hdr[1] == 6145)
jp->ext_flags = hdr[28];
}
return CUPS_BACKEND_OK;
}
char *sinfonia_update_targets (uint8_t v) {
switch (v) {
case UPDATE_TARGET_USER:
return "User";
case UPDATE_TARGET_CURRENT:
return "Current";
default:
return "Unknown";
}
}
char *sinfonia_tonecurve_statuses (uint8_t v)
{
switch(v) {
case 0:
return "Initial";
case 1:
return "UserSet";
case 2:
return "Current";
default:
return "Unknown";
}
}
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";
}
}

85
backend_shinko.h Normal file
View File

@ -0,0 +1,85 @@
/*
* 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 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+
*
*/
#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;
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_job_param *jp,
uint8_t **data, int *datalen);
#define BANK_STATUS_FREE 0x00
#define BANK_STATUS_XFER 0x01
#define BANK_STATUS_FULL 0x02
#define BANK_STATUS_PRINTING 0x12 /* Not on S2145 */
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 UPDATE_SIZE 0x600
char *sinfonia_update_targets (uint8_t v);
#define TONECURVE_INIT 0x00
#define TONECURVE_USER 0x01
#define TONECURVE_CURRENT 0x02
char *sinfonia_tonecurve_statuses (uint8_t v);

View File

@ -42,7 +42,9 @@
#define BACKEND shinkos1245_backend
#include "backend_common.h"
#include "backend_shinko.h"
#if 0
/* Structure of printjob header. All fields are LITTLE ENDIAN */
struct s1245_printjob_hdr {
uint32_t len1; /* Fixed at 0x10 */
@ -82,6 +84,7 @@ struct s1245_printjob_hdr {
uint32_t unk21; /* Null */
} __attribute__((packed));
#endif
/* Printer data structures */
struct shinkos1245_cmd_hdr {
@ -403,15 +406,6 @@ struct shinkos1245_resp_matte {
#define MATTE_MODE_MATTE 0x00
/* Private data structure */
struct shinkos1245_printjob {
uint8_t *databuf;
int datalen;
struct s1245_printjob_hdr hdr;
int copies;
};
struct shinkos1245_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
@ -1314,7 +1308,7 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, int
static void shinkos1245_cleanup_job(const void *vjob)
{
const struct shinkos1245_printjob *job = vjob;
const struct sinfonia_printjob *job = vjob;
if (job->databuf)
free(job->databuf);
@ -1331,13 +1325,11 @@ static void shinkos1245_teardown(void *vctx) {
free(ctx);
}
int sinfonia_read_parse(int data_fd, uint32_t model, void *vhdr, uint8_t **data, int *datalen);
static int shinkos1245_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct shinkos1245_ctx *ctx = vctx;
int ret;
struct shinkos1245_printjob *job = NULL;
struct sinfonia_printjob *job = NULL;
if (!ctx)
return CUPS_BACKEND_FAILED;
@ -1350,14 +1342,14 @@ static int shinkos1245_read_parse(void *vctx, const void **vjob, int data_fd, in
memset(job, 0, sizeof(*job));
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 1245, &job->hdr, &job->databuf, &job->datalen);
ret = sinfonia_read_parse(data_fd, 1245, &job->jp, &job->databuf, &job->datalen);
if (ret) {
free(job);
return ret;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.copies;
if (job->jp.copies > 1)
job->copies = job->jp.copies;
else
job->copies = copies;
@ -1370,7 +1362,7 @@ static int shinkos1245_main_loop(void *vctx, const void *vjob) {
int i, num, last_state = -1, state = S_IDLE;
struct shinkos1245_resp_status status1, status2;
const struct shinkos1245_printjob *job = vjob;
const struct sinfonia_printjob *job = vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
@ -1381,10 +1373,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 (job->hdr.media == ctx->medias[i].code &&
job->hdr.method == ctx->medias[i].print_type &&
job->hdr.rows == ctx->medias[i].rows &&
job->hdr.columns == ctx->medias[i].columns)
if (job->jp.media == ctx->medias[i].code &&
job->jp.method == ctx->medias[i].print_type &&
job->jp.rows == ctx->medias[i].rows &&
job->jp.columns == ctx->medias[i].columns)
break;
}
if (i == ctx->num_medias) {
@ -1464,13 +1456,13 @@ top:
struct shinkos1245_cmd_print cmd;
/* Set matte intensity */
if (job->hdr.mattedepth != 0x7fffffff) {
if (job->jp.mattedepth != 0x7fffffff) {
int current = -1;
i = shinkos1245_get_matte(ctx, &current);
if (i < 0)
goto printer_error;
if (current != job->hdr.mattedepth) {
i = shinkos1245_set_matte(ctx, job->hdr.mattedepth);
if (current != job->jp.mattedepth) {
i = shinkos1245_set_matte(ctx, job->jp.mattedepth);
if (i < 0)
goto printer_error;
if (i > 0) {
@ -1490,11 +1482,11 @@ top:
cmd.id = ctx->jobid;
cmd.count = cpu_to_be16(uint16_to_packed_bcd(copies));
cmd.columns = cpu_to_be16(job->hdr.columns);
cmd.rows = cpu_to_be16(job->hdr.rows);
cmd.media = job->hdr.media;
cmd.mode = (job->hdr.oc_mode & 0x3f) || ((job->hdr.dust & 0x3) << 6);
cmd.combo = job->hdr.method;
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),

View File

@ -1,4 +1,4 @@
/*
/*
* Shinko/Sinfonia CHC-S2145 CUPS backend -- libusb-1.0 version
*
* (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org>
@ -44,6 +44,7 @@
#define BACKEND shinkos2145_backend
#include "backend_common.h"
#include "backend_shinko.h"
enum {
S_IDLE = 0,
@ -52,6 +53,7 @@ enum {
S_FINISHED,
};
#if 0
/* Structure of printjob header. All fields are LITTLE ENDIAN */
struct s2145_printjob_hdr {
uint32_t len1; /* Fixed at 0x10 */
@ -91,6 +93,7 @@ struct s2145_printjob_hdr {
uint32_t unk21;
} __attribute__((packed));
#endif
/* Structs for printer */
struct s2145_cmd_hdr {
@ -317,25 +320,7 @@ struct s2145_update_cmd {
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;
@ -681,42 +666,6 @@ 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;
uint16_t total_size;
@ -727,7 +676,7 @@ struct s2145_mediainfo_item {
uint16_t columns;
uint16_t rows;
uint8_t media_type;
uint8_t print_type; /* The same as the "print method" */
uint8_t print_method;
uint8_t reserved[3];
} __attribute__((packed));
@ -786,14 +735,6 @@ struct s2145_getunique_resp {
} __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;
@ -889,20 +830,20 @@ static int get_status(struct shinkos2145_ctx *ctx)
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_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));
return 0;
}
@ -989,7 +930,7 @@ static void dump_mediainfo(struct s2145_mediainfo_resp *resp)
resp->items[i].columns,
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));
resp->items[i].print_method, print_methods(resp->items[i].print_method));
}
}
@ -1154,7 +1095,7 @@ static int get_tonecurve(struct shinkos2145_ctx *ctx, int type, char *fname)
cmd.hdr.cmd = cpu_to_le16(S2145_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,
(uint8_t*)&cmd, sizeof(cmd),
@ -1224,7 +1165,7 @@ static int set_tonecurve(struct shinkos2145_ctx *ctx, int target, char *fname)
struct s2145_status_hdr *resp = (struct s2145_status_hdr *) rdbuf;
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));
@ -1449,7 +1390,7 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int
static void shinkos2145_cleanup_job(const void *vjob)
{
const struct shinkos2145_printjob *job = vjob;
const struct sinfonia_printjob *job = vjob;
if (job->databuf)
free(job->databuf);
@ -1466,111 +1407,9 @@ static void shinkos2145_teardown(void *vctx) {
free(ctx);
}
#define SINFONIA_HDR1_LEN 0x10
#define SINFONIA_HDR2_LEN 0x64
#define SINFONIA_HDR_LEN (SINFONIA_HDR1_LEN + SINFONIA_HDR2_LEN)
#define SINFONIA_DPI 300
int sinfonia_read_parse(int data_fd, uint32_t model, void *vhdr,
uint8_t **data, int *datalen)
{
uint32_t *hdr = vhdr;
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 parameters!\n");
return CUPS_BACKEND_CANCEL;
}
/* Work out data length */
*datalen = hdr[13] * hdr[14] * 3;
*data = malloc(*datalen);
if (!*data) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
/* Read in payload data */
{
uint32_t remain = *datalen;
uint8_t *ptr = *data;
do {
ret = read(data_fd, ptr, remain);
if (ret < 0) {
ERROR("Read failed (%d/%d/%d)\n",
ret, remain, *datalen);
perror("ERROR: Read failed");
free(*data);
*data = 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(*data);
*data = NULL;
return ret;
}
if (tmpbuf[0] != 0x04 ||
tmpbuf[1] != 0x03 ||
tmpbuf[2] != 0x02 ||
tmpbuf[3] != 0x01) {
ERROR("Unrecognized footer data format!\n");
free (*data);
*data = NULL;
return CUPS_BACKEND_CANCEL;
}
/* Fill in what's left */
// *copies =
// *oc_mode =
// *media =
// *method =
// *cols =
// *rows =
return CUPS_BACKEND_OK;
}
static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct shinkos2145_ctx *ctx = vctx;
struct shinkos2145_printjob *job = NULL;
struct sinfonia_printjob *job = NULL;
int ret;
if (!ctx)
@ -1584,14 +1423,14 @@ static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, in
memset(job, 0, sizeof(*job));
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 2145, &job->hdr, &job->databuf, &job->datalen);
ret = sinfonia_read_parse(data_fd, 2145, &job->jp, &job->databuf, &job->datalen);
if (ret) {
free(job);
return ret;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.copies;
if (job->jp.copies > 1)
job->copies = job->jp.copies;
else
job->copies = copies;
@ -1613,14 +1452,14 @@ static int shinkos2145_main_loop(void *vctx, const void *vjob) {
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;
/* Validate print sizes */
for (i = 0; i < ctx->media.count ; i++) {
/* Look for matching media */
if (ctx->media.items[i].columns == job->hdr.columns &&
ctx->media.items[i].rows == job->hdr.rows &&
ctx->media.items[i].print_type == job->hdr.method)
if (ctx->media.items[i].columns == job->jp.columns &&
ctx->media.items[i].rows == job->jp.rows &&
ctx->media.items[i].print_method == job->jp.method)
break;
}
if (i == ctx->media.count) {
@ -1701,11 +1540,11 @@ top:
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->media = job->hdr.media;
print->mode = job->hdr.oc_mode;
print->method = job->hdr.method;
print->columns = cpu_to_le16(job->jp.columns);
print->rows = cpu_to_le16(job->jp.rows);
print->media = job->jp.media;
print->mode = job->jp.oc_mode;
print->method = job->jp.method;
if ((ret = s2145_do_cmd(ctx,
cmdbuf, sizeof(*print),

View File

@ -80,6 +80,7 @@
#define BACKEND shinkos6145_backend
#include "backend_common.h"
#include "backend_shinko.h"
/* Image processing library function prototypes */
typedef int (*ImageProcessingFN)(unsigned char *, unsigned short *, void *);
@ -95,6 +96,7 @@ enum {
S_FINISHED,
};
#if 0
/* Structure of printjob header. All fields are LITTLE ENDIAN */
struct s6145_printjob_hdr {
uint32_t len1; /* Fixed at 0x10 */
@ -134,6 +136,7 @@ struct s6145_printjob_hdr {
uint32_t ext_flags; /* 0x00 in the official headers. 0x01 to mark inout data as YMC planar */
} __attribute__((packed));
#endif
/* "Image Correction Parameter" File */
// 128 bytes total, apparently an array of 32-bit values
@ -500,26 +503,6 @@ struct s6145_update_cmd {
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;
@ -856,45 +839,6 @@ 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;
uint8_t data[256];
@ -1081,15 +1025,6 @@ struct s6145_imagecorr_data {
} __attribute__((packed));
/* Private data structure */
struct shinkos6145_printjob {
uint8_t *databuf;
int datalen;
struct s6145_printjob_hdr hdr;
int copies;
};
struct shinkos6145_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
@ -1202,20 +1137,20 @@ static int get_status(struct shinkos6145_ctx *ctx)
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_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(S6145_CMD_EXTCOUNTER);
@ -1564,7 +1499,7 @@ static int get_tonecurve(struct shinkos6145_ctx *ctx, int type, char *fname)
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);
INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname);
if ((ret = s6145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
@ -1627,7 +1562,7 @@ static int set_tonecurve(struct shinkos6145_ctx *ctx, int target, char *fname)
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);
INFO("Set %s Tone Curve from '%s'\n", sinfonia_update_targets(target), fname);
uint16_t *data = malloc(UPDATE_SIZE * sizeof(uint16_t));
if (!data) {
@ -1963,7 +1898,7 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, int
static void shinkos6145_cleanup_job(const void *vjob)
{
const struct shinkos6145_printjob *job = vjob;
const struct sinfonia_printjob *job = vjob;
if (job->databuf)
free(job->databuf);
@ -1990,7 +1925,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;
@ -2081,11 +2016,9 @@ static void lib6145_process_image(uint8_t *src, uint16_t *dest,
}
}
int sinfonia_read_parse(int data_fd, uint32_t model, void *vhdr, uint8_t **data, int *datalen);
static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct shinkos6145_ctx *ctx = vctx;
struct shinkos6145_printjob *job = NULL;
struct sinfonia_printjob *job = NULL;
int ret;
uint8_t input_ymc;
@ -2100,14 +2033,14 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
memset(job, 0, sizeof(*job));
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 6145, &job->hdr, &job->databuf, &job->datalen);
ret = sinfonia_read_parse(data_fd, 6145, &job->jp, &job->databuf, &job->datalen);
if (ret) {
free(job);
return ret;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.copies;
if (job->jp.copies > 1)
job->copies = job->jp.copies;
else
job->copies = copies;
@ -2115,12 +2048,12 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
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;
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) {
@ -2167,7 +2100,7 @@ static int shinkos6145_main_loop(void *vctx, const void *vjob) {
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;
@ -2191,10 +2124,10 @@ static int shinkos6145_main_loop(void *vctx, const void *vjob) {
/* Validate print sizes */
for (i = 0; i < media->count ; i++) {
/* Look for matching media */
if (media->items[i].columns == job->hdr.columns &&
media->items[i].rows == job->hdr.rows &&
media->items[i].print_method == job->hdr.method &&
media->items[i].media_code == job->hdr.media)
if (media->items[i].columns == job->jp.columns &&
media->items[i].rows == job->jp.rows &&
media->items[i].print_method == job->jp.method &&
media->items[i].media_code == job->jp.media)
break;
}
if (i == media->count) {
@ -2265,7 +2198,7 @@ top:
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 */
@ -2306,19 +2239,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;
@ -2328,7 +2261,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);
}
@ -2344,15 +2277,15 @@ top:
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->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->hdr.method);
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->media = job->jp.media;
print->unk_1 = 0x01;
}

View File

@ -43,7 +43,7 @@
#define BACKEND shinkos6245_backend
#include "backend_common.h"
#include "backend_shinko.h"
enum {
S_IDLE = 0,
@ -52,6 +52,7 @@ enum {
S_FINISHED,
};
#if 0
/* Structure of printjob header. All fields are LITTLE ENDIAN */
struct s6245_printjob_hdr {
uint32_t len1; /* Fixed at 0x10 */
@ -91,6 +92,7 @@ struct s6245_printjob_hdr {
uint32_t unk21;
} __attribute__((packed));
#endif
/* Structs for printer */
struct s6245_cmd_hdr {
@ -326,26 +328,6 @@ struct s6245_update_cmd {
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;
@ -705,45 +687,6 @@ 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;
uint8_t data[256];
@ -908,14 +851,6 @@ struct s6245_fwinfo_resp {
} __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;
@ -1004,20 +939,20 @@ static int get_status(struct shinkos6245_ctx *ctx)
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_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);
@ -1242,7 +1177,7 @@ static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname)
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);
INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname);
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
@ -1305,7 +1240,7 @@ static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname)
struct s6245_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));
if (!data) {
@ -1521,7 +1456,7 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, int
static void shinkos6245_cleanup_job(const void *vjob)
{
const struct shinkos6245_printjob *job = vjob;
const struct sinfonia_printjob *job = vjob;
if (job->databuf)
free(job->databuf);
@ -1538,11 +1473,9 @@ static void shinkos6245_teardown(void *vctx) {
free(ctx);
}
int sinfonia_read_parse(int data_fd, uint32_t model, void *vhdr, uint8_t **data, int *datalen);
static int shinkos6245_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct shinkos6245_ctx *ctx = vctx;
struct shinkos6245_printjob *job = NULL;
struct sinfonia_printjob *job = NULL;
int ret;
if (!ctx)
@ -1556,14 +1489,14 @@ static int shinkos6245_read_parse(void *vctx, const void **vjob, int data_fd, in
memset(job, 0, sizeof(*job));
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 6245, &job->hdr, &job->databuf, &job->datalen);
ret = sinfonia_read_parse(data_fd, 6245, &job->jp, &job->databuf, &job->datalen);
if (ret) {
free(job);
return ret;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.copies;
if (job->jp.copies > 1)
job->copies = job->jp.copies;
else
job->copies = copies;
@ -1587,7 +1520,7 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) {
struct s6245_status_resp sts, sts2;
struct s6245_status_hdr resp;
struct shinkos6245_printjob *job = (struct shinkos6245_printjob*) vjob;
struct sinfonia_printjob *job = (struct sinfonia_printjob*) vjob;
copies = job->copies;
@ -1598,7 +1531,7 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) {
copies = 120;
/* Set up mcut */
switch (job->hdr.media) {
switch (job->jp.media) {
case MEDIA_8x4_2:
case MEDIA_8x5_2:
case MEDIA_8x6_2:
@ -1615,8 +1548,8 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) {
/* Validate print sizes */
for (i = 0; i < ctx->media.count ; i++) {
/* Look for matching media */
if (ctx->media.items[i].columns == job->hdr.columns &&
ctx->media.items[i].rows == 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) {
@ -1727,9 +1660,9 @@ top:
print->id = ctx->jobid;
print->count = cpu_to_le16(copies);
print->columns = cpu_to_le16(job->hdr.columns);
print->rows = cpu_to_le16(job->hdr.rows);
print->mode = job->hdr.oc_mode;
print->columns = cpu_to_le16(job->jp.columns);
print->rows = cpu_to_le16(job->jp.rows);
print->mode = job->jp.oc_mode;
print->method = mcut;
if ((ret = s6245_do_cmd(ctx,