sinfonia: Common header/job parsing code for Sinfonia models.

Covers:  S2145, S6145, S6245
This commit is contained in:
Solomon Peachy 2019-04-28 10:16:21 -04:00
parent ff2dda1c97
commit ce0fa508f0
3 changed files with 118 additions and 218 deletions

View file

@ -1460,64 +1460,70 @@ static void shinkos2145_teardown(void *vctx) {
free(ctx);
}
static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct shinkos2145_ctx *ctx = vctx;
int ret;
#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];
struct shinkos2145_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; // XXX hdr.copies
/* Read in then validate header */
ret = read(data_fd, &job->hdr, sizeof(job->hdr));
if (ret < 0 || ret != sizeof(job->hdr)) {
/* 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/%d)\n",
ret, 0, (int)sizeof(job->hdr));
ERROR("Read failed (%d/%d)\n",
ret, SINFONIA_HDR_LEN);
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) {
/* 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 (le32_to_cpu(job->hdr.model) != 2145) {
ERROR("Unrecognized printer (%u)!\n", le32_to_cpu(job->hdr.model));
if (hdr[1] != model) {
ERROR("job/printer mismatch (%u/%u)!\n", hdr[1], 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) {
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 */
{
int remain = job->datalen;
uint8_t *ptr = job->databuf;
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, job->datalen);
ret, remain, *datalen);
perror("ERROR: Read failed");
free(*data);
*data = NULL;
return ret;
}
ptr += ret;
@ -1528,9 +1534,10 @@ static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, in
/* 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);
ERROR("Read failed (%d/%d)\n", ret, 4);
perror("ERROR: Read failed");
free(*data);
*data = NULL;
return ret;
}
if (tmpbuf[0] != 0x04 ||
@ -1538,9 +1545,41 @@ static int shinkos2145_read_parse(void *vctx, const void **vjob, int data_fd, in
tmpbuf[2] != 0x02 ||
tmpbuf[3] != 0x01) {
ERROR("Unrecognized footer data format!\n");
return CUPS_BACKEND_FAILED;
free (*data);
*data = NULL;
return CUPS_BACKEND_CANCEL;
}
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;
int ret;
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));
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 2145, &job->hdr, &job->databuf, &job->datalen);
if (ret) {
free(job);
return ret;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.copies;
else
job->copies = copies;
*vjob = job;
return CUPS_BACKEND_OK;
@ -1564,9 +1603,9 @@ static int shinkos2145_main_loop(void *vctx, const void *vjob) {
/* 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 (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(job->hdr.columns) &&
le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(job->hdr.rows) &&
ctx->media.items[i].print_type == job->hdr.method)
break;
}
if (i == ctx->media.count) {
@ -1647,11 +1686,11 @@ top:
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);
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.mode;
print->method = job->hdr.method;
if ((ret = s2145_do_cmd(ctx,
cmdbuf, sizeof(*print),
@ -1799,7 +1838,7 @@ static const char *shinkos2145_prefixes[] = {
struct dyesub_backend shinkos2145_backend = {
.name = "Shinko/Sinfonia CHC-S2145/S2",
.version = "0.56",
.version = "0.57",
.uri_prefixes = shinkos2145_prefixes,
.cmdline_usage = shinkos2145_cmdline,
.cmdline_arg = shinkos2145_cmdline_arg,

View file

@ -1001,7 +1001,7 @@ static const char *print_ribbons (uint8_t v) {
return "6x8";
case RIBBON_6x9:
return "6x9";
// XXX 89x??? rubbons.
// XXX 89x??? ribbons.
default:
return "Unknown";
}
@ -1083,7 +1083,7 @@ struct s6145_imagecorr_data {
/* Private data structure */
struct shinkos6145_printjob {
uint8_t *databuf;
size_t datalen;
int datalen;
struct s6145_printjob_hdr hdr;
@ -2074,13 +2074,13 @@ 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;
int ret;
uint8_t tmpbuf[4];
uint8_t input_ymc;
struct shinkos6145_printjob *job = NULL;
int ret;
uint8_t input_ymc;
if (!ctx)
return CUPS_BACKEND_FAILED;
@ -2091,57 +2091,18 @@ static int shinkos6145_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)) {
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");
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 6145, &job->hdr, &job->databuf, &job->datalen);
if (ret) {
free(job);
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;
}
if (job->hdr.model != 6145) {
ERROR("Unrecognized printer (%u)!\n", job->hdr.model);
shinkos6145_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
if (!job->hdr.rows || !job->hdr.columns) {
ERROR("Bad print job header!\n");
shinkos6145_cleanup_job(job);
return CUPS_BACKEND_CANCEL;
}
if (job->hdr.copies > 1)
job->copies = job->hdr.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
@ -2149,49 +2110,6 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
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;
}
/* Convert packed RGB to planar YMC if necessary */
if (!input_ymc) {
INFO("Converting Packed RGB to Planar YMC\n");
@ -2569,7 +2487,7 @@ static const char *shinkos6145_prefixes[] = {
struct dyesub_backend shinkos6145_backend = {
.name = "Shinko/Sinfonia CHC-S6145/CS2",
.version = "0.31",
.version = "0.32",
.uri_prefixes = shinkos6145_prefixes,
.cmdline_usage = shinkos6145_cmdline,
.cmdline_arg = shinkos6145_cmdline_arg,

View file

@ -1530,12 +1530,12 @@ 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;
int ret;
uint8_t tmpbuf[4];
struct shinkos6245_printjob *job = NULL;
int ret;
if (!ctx)
return CUPS_BACKEND_FAILED;
@ -1546,75 +1546,18 @@ 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");
/* Common read/parse code */
ret = sinfonia_read_parse(data_fd, 6245, &job->hdr, &job->databuf, &job->datalen);
if (ret) {
free(job);
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);
}
/* 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");
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->hdr.copies > 1)
job->copies = job->hdr.copies;
else
job->copies = copies;
*vjob = job;
@ -1647,7 +1590,7 @@ static int shinkos6245_main_loop(void *vctx, const void *vjob) {
copies = 120;
/* Set up mcut */
switch (le32_to_cpu(job->hdr.media)) {
switch (job->hdr.media) {
case MEDIA_8x4_2:
case MEDIA_8x5_2:
case MEDIA_8x6_2:
@ -1664,8 +1607,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 (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 (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(job->hdr.columns) &&
le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(job->hdr.rows))
break;
}
if (i == ctx->media.count) {
@ -1776,9 +1719,9 @@ top:
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 = cpu_to_le16(job->hdr.columns);
print->rows = cpu_to_le16(job->hdr.rows);
print->mode = job->hdr.oc_mode;
print->method = mcut;
if ((ret = s6245_do_cmd(ctx,
@ -1917,7 +1860,7 @@ static const char *shinkos6245_prefixes[] = {
struct dyesub_backend shinkos6245_backend = {
.name = "Shinko/Sinfonia CHC-S6245",
.version = "0.15WIP",
.version = "0.16WIP",
.uri_prefixes = shinkos6245_prefixes,
.cmdline_usage = shinkos6245_cmdline,
.cmdline_arg = shinkos6245_cmdline_arg,