common: better split between parsing and printing.

parsing returns a self-contained job, which is then passed to printing
code.  No global state is modified.

mitsu 70x:
  Still need to move the image processing code to the print side.
This commit is contained in:
Solomon Peachy 2018-06-15 14:55:03 -04:00
parent 68701c746d
commit fd9b38202e
18 changed files with 1474 additions and 1099 deletions

View file

@ -536,18 +536,9 @@ done:
}
/* Private data structure */
struct canonselphy_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
struct printer_data *printer;
struct marker marker;
uint8_t bw_mode;
struct canonselphy_printjob {
int16_t paper_code;
uint8_t bw_mode;
uint32_t plane_len;
@ -557,7 +548,17 @@ struct canonselphy_ctx {
uint8_t *plane_c;
uint8_t *footer;
uint8_t *buffer;
int copies;
};
struct canonselphy_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
struct printer_data *printer;
struct marker marker;
uint8_t cp900;
};
@ -611,13 +612,6 @@ static void *canonselphy_init(void)
/* Static initialization */
setup_paper_codes();
ctx->buffer = malloc(MAX_HEADER);
if (!ctx->buffer) {
ERROR("Memory Allocation Failure!\n");
free(ctx);
ctx = NULL;
}
return ctx;
}
@ -679,42 +673,56 @@ static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev, int
return CUPS_BACKEND_OK;
}
static void canonselphy_cleanup_job(const void *vjob) {
const struct canonselphy_printjob *job = vjob;
if (job->header)
free(job->header);
if (job->plane_y)
free(job->plane_y);
if (job->plane_m)
free(job->plane_m);
if (job->plane_c)
free(job->plane_c);
if (job->footer)
free(job->footer);
free((void*)job);
}
static void canonselphy_teardown(void *vctx) {
struct canonselphy_ctx *ctx = vctx;
if (!ctx)
return;
if (ctx->header)
free(ctx->header);
if (ctx->plane_y)
free(ctx->plane_y);
if (ctx->plane_m)
free(ctx->plane_m);
if (ctx->plane_c)
free(ctx->plane_c);
if (ctx->footer)
free(ctx->footer);
if (ctx->buffer)
free(ctx->buffer);
free(ctx);
}
static int canonselphy_read_parse(void *vctx, int data_fd)
static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, int copies)
{
struct canonselphy_ctx *ctx = vctx;
int i, remain;
int printer_type;
int offset = 0;
uint8_t rdbuf[MAX_HEADER];
struct canonselphy_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;
/* The CP900 job *may* have a 4-byte null footer after the
job contents. Ignore it if it comes through here.. */
i = read(data_fd, ctx->buffer, 4);
i = read(data_fd, rdbuf, 4);
if (i != 4) {
if (i == 0)
return CUPS_BACKEND_CANCEL;
@ -723,15 +731,15 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
return CUPS_BACKEND_FAILED;
}
/* if it's not the null header.. don't ignore! */
if (ctx->buffer[0] != 0 ||
ctx->buffer[1] != 0 ||
ctx->buffer[2] != 0 ||
ctx->buffer[3] != 0) {
if (rdbuf[0] != 0 ||
rdbuf[1] != 0 ||
rdbuf[2] != 0 ||
rdbuf[3] != 0) {
offset = 4;
}
/* Read the rest of the header.. */
i = read(data_fd, ctx->buffer + offset, MAX_HEADER - offset);
i = read(data_fd, rdbuf + offset, MAX_HEADER - offset);
if (i != MAX_HEADER - offset) {
if (i == 0)
return CUPS_BACKEND_CANCEL;
@ -742,7 +750,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
}
/* Figure out printer this file is intended for */
printer_type = parse_printjob(ctx->buffer, &ctx->bw_mode, &ctx->plane_len);
printer_type = parse_printjob(rdbuf, &job->bw_mode, &job->plane_len);
/* Special cases for some models */
if (printer_type == P_ES40_CP790) {
if (ctx->type == P_CP790)
@ -762,78 +770,56 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
return CUPS_BACKEND_CANCEL;
}
INFO("%sFile intended for a '%s' printer\n", ctx->bw_mode? "B/W " : "", ctx->printer->model);
INFO("%sFile intended for a '%s' printer\n", job->bw_mode? "B/W " : "", ctx->printer->model);
/* Paper code setup */
if (ctx->printer->pgcode_offset != -1)
ctx->paper_code = ctx->printer->paper_codes[ctx->buffer[ctx->printer->pgcode_offset]];
job->paper_code = ctx->printer->paper_codes[rdbuf[ctx->printer->pgcode_offset]];
else
ctx->paper_code = -1;
job->paper_code = -1;
/* Add in plane header length! */
ctx->plane_len += 12;
/* Now prep for the job */
if (ctx->header) {
free(ctx->header);
ctx->header = NULL;
}
if (ctx->plane_y) {
free(ctx->plane_y);
ctx->plane_y = NULL;
}
if (ctx->plane_m) {
free(ctx->plane_m);
ctx->plane_m = NULL;
}
if (ctx->plane_c) {
free(ctx->plane_c);
ctx->plane_c = NULL;
}
if (ctx->footer) {
free(ctx->footer);
ctx->footer = NULL;
}
job->plane_len += 12;
/* Set up buffers */
ctx->plane_y = malloc(ctx->plane_len);
ctx->plane_m = malloc(ctx->plane_len);
ctx->plane_c = malloc(ctx->plane_len);
ctx->header = malloc(ctx->printer->init_length);
ctx->footer = malloc(ctx->printer->foot_length);
if (!ctx->plane_y || !ctx->plane_m || !ctx->plane_c || !ctx->header ||
(ctx->printer->foot_length && !ctx->footer)) {
job->plane_y = malloc(job->plane_len);
job->plane_m = malloc(job->plane_len);
job->plane_c = malloc(job->plane_len);
job->header = malloc(ctx->printer->init_length);
job->footer = malloc(ctx->printer->foot_length);
if (!job->plane_y || !job->plane_m || !job->plane_c || !job->header ||
(ctx->printer->foot_length && !job->footer)) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
/* Move over chunks already read in */
memcpy(ctx->header, ctx->buffer, ctx->printer->init_length);
memcpy(ctx->plane_y, ctx->buffer+ctx->printer->init_length,
memcpy(job->header, rdbuf, ctx->printer->init_length);
memcpy(job->plane_y, rdbuf+ctx->printer->init_length,
MAX_HEADER-ctx->printer->init_length);
/* Read in YELLOW plane */
remain = ctx->plane_len - (MAX_HEADER-ctx->printer->init_length);
remain = job->plane_len - (MAX_HEADER-ctx->printer->init_length);
while (remain > 0) {
i = read(data_fd, ctx->plane_y + (ctx->plane_len - remain), remain);
i = read(data_fd, job->plane_y + (job->plane_len - remain), remain);
if (i < 0)
return CUPS_BACKEND_CANCEL;
remain -= i;
}
/* Read in MAGENTA plane */
remain = ctx->plane_len;
remain = job->plane_len;
while (remain > 0) {
i = read(data_fd, ctx->plane_m + (ctx->plane_len - remain), remain);
i = read(data_fd, job->plane_m + (job->plane_len - remain), remain);
if (i < 0)
return CUPS_BACKEND_CANCEL;
remain -= i;
}
/* Read in CYAN plane */
remain = ctx->plane_len;
remain = job->plane_len;
while (remain > 0) {
i = read(data_fd, ctx->plane_c + (ctx->plane_len - remain), remain);
i = read(data_fd, job->plane_c + (job->plane_len - remain), remain);
if (i < 0)
return CUPS_BACKEND_CANCEL;
remain -= i;
@ -843,22 +829,34 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
if (ctx->printer->foot_length) {
remain = ctx->printer->foot_length;
while (remain > 0) {
i = read(data_fd, ctx->footer + (ctx->printer->foot_length - remain), remain);
i = read(data_fd, job->footer + (ctx->printer->foot_length - remain), remain);
if (i < 0)
return CUPS_BACKEND_CANCEL;
remain -= i;
}
}
*vjob = job;
return CUPS_BACKEND_OK;
}
static int canonselphy_main_loop(void *vctx, int copies) {
static int canonselphy_main_loop(void *vctx, const void *vjob) {
struct canonselphy_ctx *ctx = vctx;
uint8_t rdbuf[READBACK_LEN], rdbuf2[READBACK_LEN];
int last_state = -1, state = S_IDLE;
int ret, num;
int copies;
const struct canonselphy_printjob *job = vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
copies = job->copies;
/* Read in the printer status to clear last state */
ret = read_data(ctx->dev, ctx->endp_up,
@ -910,10 +908,10 @@ top:
break;
/* Make sure paper/ribbon is correct */
if (ctx->paper_code != -1) {
if (job->paper_code != -1) {
if (ctx->type == P_CP_XXX) {
uint8_t pc = rdbuf[ctx->printer->paper_code_offset];
if (((pc >> 4) & 0xf) != (ctx->paper_code & 0x0f)) {
if (((pc >> 4) & 0xf) != (job->paper_code & 0x0f)) {
if (pc & 0xf0) {
ERROR("Incorrect paper tray loaded, aborting job!\n");
@ -923,7 +921,7 @@ top:
return CUPS_BACKEND_STOP;
}
}
if ((pc & 0xf) != (ctx->paper_code & 0xf)) {
if ((pc & 0xf) != (job->paper_code & 0xf)) {
if (pc & 0x0f) {
ERROR("Incorrect ribbon loaded, aborting job!\n");
return CUPS_BACKEND_HOLD;
@ -935,9 +933,9 @@ top:
}
} else {
if (rdbuf[ctx->printer->paper_code_offset] !=
ctx->paper_code) {
job->paper_code) {
ERROR("Incorrect media/ribbon loaded (%02x vs %02x), aborting job!\n",
ctx->paper_code,
job->paper_code,
rdbuf[ctx->printer->paper_code_offset]);
return CUPS_BACKEND_HOLD; /* Hold this job, don't stop queue */
}
@ -949,14 +947,14 @@ top:
if (ribbon == 0xf) {
ERROR("No ribbon loaded, aborting!\n");
return CUPS_BACKEND_STOP;
} else if (ribbon != ctx->paper_code) {
} else if (ribbon != job->paper_code) {
ERROR("Incorrect ribbon loaded, aborting job!\n");
return CUPS_BACKEND_HOLD;
}
if (paper == 0xf) {
ERROR("No paper tray loaded, aborting!\n");
return CUPS_BACKEND_STOP;
} else if (paper != ctx->paper_code) {
} else if (paper != job->paper_code) {
ERROR("Incorrect paper loaded, aborting job!\n");
return CUPS_BACKEND_HOLD;
}
@ -967,7 +965,7 @@ top:
case S_PRINTER_READY:
INFO("Printing started; Sending init sequence\n");
/* Send printer init */
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->header, ctx->printer->init_length)))
if ((ret = send_data(ctx->dev, ctx->endp_down, job->header, ctx->printer->init_length)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_INIT_SENT;
@ -978,19 +976,19 @@ top:
}
break;
case S_PRINTER_READY_Y:
if (ctx->bw_mode)
if (job->bw_mode)
INFO("Sending BLACK plane\n");
else
INFO("Sending YELLOW plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_y, ctx->plane_len)))
if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_y, job->plane_len)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_Y_SENT;
break;
case S_PRINTER_Y_SENT:
if (!fancy_memcmp(rdbuf, ctx->printer->ready_m_readback, READBACK_LEN)) {
if (ctx->bw_mode)
if (job->bw_mode)
state = S_PRINTER_DONE;
else
state = S_PRINTER_READY_M;
@ -999,7 +997,7 @@ top:
case S_PRINTER_READY_M:
INFO("Sending MAGENTA plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_m, ctx->plane_len)))
if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_m, job->plane_len)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_M_SENT;
@ -1012,7 +1010,7 @@ top:
case S_PRINTER_READY_C:
INFO("Sending CYAN plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_c, ctx->plane_len)))
if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_c, job->plane_len)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_C_SENT;
@ -1040,7 +1038,7 @@ top:
if (ctx->printer->foot_length) {
INFO("Cleaning up\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->footer, ctx->printer->foot_length)))
if ((ret = send_data(ctx->dev, ctx->endp_down, job->footer, ctx->printer->foot_length)))
return CUPS_BACKEND_FAILED;
}
state = S_FINISHED;
@ -1141,7 +1139,7 @@ static const char *canonselphy_prefixes[] = {
struct dyesub_backend canonselphy_backend = {
.name = "Canon SELPHY CP/ES (legacy)",
.version = "0.101",
.version = "0.102",
.uri_prefixes = canonselphy_prefixes,
.cmdline_usage = canonselphy_cmdline,
.cmdline_arg = canonselphy_cmdline_arg,
@ -1149,6 +1147,7 @@ struct dyesub_backend canonselphy_backend = {
.attach = canonselphy_attach,
.teardown = canonselphy_teardown,
.read_parse = canonselphy_read_parse,
.cleanup_job = canonselphy_cleanup_job,
.main_loop = canonselphy_main_loop,
.query_markers = canonselphy_query_markers,
.devices = {

View file

@ -62,15 +62,19 @@ struct selphyneo_readback {
} __attribute((packed));
/* Private data structure */
struct selphyneo_printjob {
uint8_t *databuf;
uint32_t datalen;
int copies;
};
struct selphyneo_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
uint8_t *databuf;
uint32_t datalen;
struct marker marker;
};
@ -237,27 +241,43 @@ static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev, int ty
return CUPS_BACKEND_OK;
}
static void selphyneo_cleanup_job(const void *vjob) {
const struct selphyneo_printjob *job = vjob;
if (job->databuf)
free(job->databuf);
free((void*)job);
}
static void selphyneo_teardown(void *vctx) {
struct selphyneo_ctx *ctx = vctx;
if (!ctx)
return;
if (ctx->databuf)
free(ctx->databuf);
free(ctx);
}
static int selphyneo_read_parse(void *vctx, int data_fd)
static int selphyneo_read_parse(void *vctx, const void **vjob, int data_fd, int copies)
{
struct selphyneo_ctx *ctx = vctx;
struct selphyneo_hdr hdr;
int i, remain;
struct selphyneo_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;
/* Read the header.. */
i = read(data_fd, &hdr, sizeof(hdr));
if (i != sizeof(hdr)) {
@ -283,34 +303,46 @@ static int selphyneo_read_parse(void *vctx, int data_fd)
}
/* Allocate a buffer */
ctx->datalen = 0;
ctx->databuf = malloc(remain + sizeof(hdr));
if (!ctx->databuf) {
job->datalen = 0;
job->databuf = malloc(remain + sizeof(hdr));
if (!job->databuf) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
/* Store the read-in header */
memcpy(ctx->databuf, &hdr, sizeof(hdr));
ctx->datalen += sizeof(hdr);
memcpy(job->databuf, &hdr, sizeof(hdr));
job->datalen += sizeof(hdr);
/* Read in data */
while (remain > 0) {
i = read(data_fd, ctx->databuf + ctx->datalen, remain);
i = read(data_fd, job->databuf + job->datalen, remain);
if (i < 0)
return CUPS_BACKEND_CANCEL;
remain -= i;
ctx->datalen += i;
job->datalen += i;
}
*vjob = job;
return CUPS_BACKEND_OK;
}
static int selphyneo_main_loop(void *vctx, int copies) {
static int selphyneo_main_loop(void *vctx, const void *vjob) {
struct selphyneo_ctx *ctx = vctx;
struct selphyneo_readback rdback;
int ret, num;
int copies;
const struct selphyneo_printjob *job = vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
copies = job->copies;
/* Read in the printer status to clear last state */
ret = read_data(ctx->dev, ctx->endp_up,
@ -361,10 +393,10 @@ top:
int sent = 0;
while (chunk > 0) {
if ((ret = send_data(ctx->dev, ctx->endp_down,
ctx->databuf + sent, chunk)))
job->databuf + sent, chunk)))
return CUPS_BACKEND_FAILED;
sent += chunk;
chunk = ctx->datalen - sent;
chunk = job->datalen - sent;
if (chunk > 256*1024)
chunk = 256*1024;
}
@ -496,12 +528,13 @@ static const char *canonselphyneo_prefixes[] = {
struct dyesub_backend canonselphyneo_backend = {
.name = "Canon SELPHY CP (new)",
.version = "0.17",
.version = "0.18",
.uri_prefixes = canonselphyneo_prefixes,
.cmdline_usage = selphyneo_cmdline,
.cmdline_arg = selphyneo_cmdline_arg,
.init = selphyneo_init,
.attach = selphyneo_attach,
.cleanup_job = selphyneo_cleanup_job,
.teardown = selphyneo_teardown,
.read_parse = selphyneo_read_parse,
.main_loop = selphyneo_main_loop,

View file

@ -29,7 +29,7 @@
#include "backend_common.h"
#define BACKEND_VERSION "0.86"
#define BACKEND_VERSION "0.87"
#ifndef URI_PREFIX
#error "Must Define URI_PREFIX"
#endif
@ -268,7 +268,7 @@ done:
}
int send_data(struct libusb_device_handle *dev, uint8_t endp,
uint8_t *buf, int len)
const uint8_t *buf, int len)
{
int num = 0;
@ -279,7 +279,7 @@ int send_data(struct libusb_device_handle *dev, uint8_t endp,
while (len) {
int len2 = (len > max_xfer_size) ? max_xfer_size: len;
int ret = libusb_bulk_transfer(dev, endp,
buf, len2,
(uint8_t*) buf, len2,
&num, xfer_timeout);
if ((dyesub_debug > 1 && len < 4096) ||
@ -942,6 +942,8 @@ int main (int argc, char **argv)
int data_fd = fileno(stdin);
const void *job = NULL;
int i;
int ret = CUPS_BACKEND_OK;
@ -1235,7 +1237,7 @@ bypass:
newpage:
/* Read in data */
if ((ret = backend->read_parse(backend_ctx, data_fd))) {
if ((ret = backend->read_parse(backend_ctx, &job, data_fd, copies))) {
if (current_page)
goto done_multiple;
else
@ -1252,7 +1254,9 @@ newpage:
if (test_mode >= TEST_MODE_NOPRINT ) {
WARNING("**** TEST MODE, bypassing printing!\n");
} else {
ret = backend->main_loop(backend_ctx, copies);
ret = backend->main_loop(backend_ctx, job);
if (backend->cleanup_job)
backend->cleanup_job(job);
if (ret)
goto done_claimed;
}

View file

@ -162,8 +162,9 @@ struct dyesub_backend {
uint8_t endp_up, uint8_t endp_down, uint8_t jobid);
void (*teardown)(void *ctx);
int (*cmdline_arg)(void *ctx, int argc, char **argv);
int (*read_parse)(void *ctx, int data_fd);
int (*main_loop)(void *ctx, int copies);
int (*read_parse)(void *ctx, const void **job, int data_fd, int copies);
void (*cleanup_job)(const void *job);
int (*main_loop)(void *ctx, const void *job);
int (*query_serno)(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len); /* Optional */
int (*query_markers)(void *ctx, struct marker **markers, int *count);
const struct device_id devices[];
@ -171,7 +172,7 @@ struct dyesub_backend {
/* Exported functions */
int send_data(struct libusb_device_handle *dev, uint8_t endp,
uint8_t *buf, int len);
const uint8_t *buf, int len);
int read_data(struct libusb_device_handle *dev, uint8_t endp,
uint8_t *buf, int buflen, int *readlen);

File diff suppressed because it is too large Load diff

View file

@ -77,21 +77,26 @@ struct kodak1400_hdr {
/* Private data structure */
struct kodak1400_printjob {
struct kodak1400_hdr hdr;
uint8_t *plane_r;
uint8_t *plane_g;
uint8_t *plane_b;
int copies;
};
struct kodak1400_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
struct kodak1400_hdr hdr;
uint8_t *plane_r;
uint8_t *plane_g;
uint8_t *plane_b;
struct marker marker;
};
static int send_plane(struct kodak1400_ctx *ctx,
const struct kodak1400_printjob *job,
uint8_t planeno, uint8_t *planedata,
uint8_t *cmdbuf)
{
@ -117,9 +122,9 @@ static int send_plane(struct kodak1400_ctx *ctx,
cmdbuf[3] = planeno;
if (planedata) {
temp16 = htons(ctx->hdr.columns);
temp16 = htons(job->hdr.columns);
memcpy(cmdbuf+7, &temp16, 2);
temp16 = htons(ctx->hdr.rows);
temp16 = htons(job->hdr.rows);
memcpy(cmdbuf+9, &temp16, 2);
}
@ -129,10 +134,10 @@ static int send_plane(struct kodak1400_ctx *ctx,
if (planedata) {
int i;
for (i = 0 ; i < ctx->hdr.rows ; i++) {
for (i = 0 ; i < job->hdr.rows ; i++) {
if ((ret = send_data(ctx->dev, ctx->endp_down,
planedata + i * ctx->hdr.columns,
ctx->hdr.columns)))
planedata + i * job->hdr.columns,
job->hdr.columns)))
return ret;
}
}
@ -316,91 +321,96 @@ static int kodak1400_attach(void *vctx, struct libusb_device_handle *dev, int ty
return CUPS_BACKEND_OK;
}
static void kodak1400_cleanup_job(const void *vjob)
{
const struct kodak1400_printjob *job = vjob;
if (job->plane_r)
free(job->plane_r);
if (job->plane_g)
free(job->plane_g);
if (job->plane_b)
free(job->plane_b);
free((void*)job);
}
static void kodak1400_teardown(void *vctx) {
struct kodak1400_ctx *ctx = vctx;
if (!ctx)
return;
if (ctx->plane_r)
free(ctx->plane_r);
if (ctx->plane_g)
free(ctx->plane_g);
if (ctx->plane_b)
free(ctx->plane_b);
free(ctx);
}
static int kodak1400_read_parse(void *vctx, int data_fd) {
static int kodak1400_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
struct kodak1400_ctx *ctx = vctx;
int i, ret;
struct kodak1400_printjob *job = NULL;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (ctx->plane_r) {
free(ctx->plane_r);
ctx->plane_r = NULL;
}
if (ctx->plane_g) {
free(ctx->plane_g);
ctx->plane_g = NULL;
}
if (ctx->plane_b) {
free(ctx->plane_b);
ctx->plane_b = NULL;
}
/* Read in then validate header */
ret = read(data_fd, &ctx->hdr, sizeof(ctx->hdr));
if (ret < 0 || ret != sizeof(ctx->hdr)) {
if (ret == 0)
return CUPS_BACKEND_CANCEL;
ERROR("Read failed (%d/%d/%d)\n",
ret, 0, (int)sizeof(ctx->hdr));
perror("ERROR: Read failed");
return CUPS_BACKEND_CANCEL;
}
if (ctx->hdr.hdr[0] != 'P' ||
ctx->hdr.hdr[1] != 'G' ||
ctx->hdr.hdr[2] != 'H' ||
ctx->hdr.hdr[3] != 'D') {
ERROR("Unrecognized data format!\n");
return CUPS_BACKEND_CANCEL;
}
ctx->hdr.planesize = le32_to_cpu(ctx->hdr.planesize);
ctx->hdr.rows = le16_to_cpu(ctx->hdr.rows);
ctx->hdr.columns = le16_to_cpu(ctx->hdr.columns);
/* Set up plane data */
ctx->plane_r = malloc(ctx->hdr.planesize);
ctx->plane_g = malloc(ctx->hdr.planesize);
ctx->plane_b = malloc(ctx->hdr.planesize);
if (!ctx->plane_r || !ctx->plane_g || !ctx->plane_b) {
job = malloc(sizeof(*job));
if (!job) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
for (i = 0 ; i < ctx->hdr.rows ; i++) {
memset(job, 0, sizeof(*job));
job->copies = 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 CUPS_BACKEND_CANCEL;
}
if (job->hdr.hdr[0] != 'P' ||
job->hdr.hdr[1] != 'G' ||
job->hdr.hdr[2] != 'H' ||
job->hdr.hdr[3] != 'D') {
ERROR("Unrecognized data format!\n");
return CUPS_BACKEND_CANCEL;
}
job->hdr.planesize = le32_to_cpu(job->hdr.planesize);
job->hdr.rows = le16_to_cpu(job->hdr.rows);
job->hdr.columns = le16_to_cpu(job->hdr.columns);
/* Set up plane data */
job->plane_r = malloc(job->hdr.planesize);
job->plane_g = malloc(job->hdr.planesize);
job->plane_b = malloc(job->hdr.planesize);
if (!job->plane_r || !job->plane_g || !job->plane_b) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
for (i = 0 ; i < job->hdr.rows ; i++) {
int j;
uint8_t *ptr;
for (j = 0 ; j < 3 ; j++) {
int remain;
if (j == 0)
ptr = ctx->plane_r + i * ctx->hdr.columns;
ptr = job->plane_r + i * job->hdr.columns;
else if (j == 1)
ptr = ctx->plane_g + i * ctx->hdr.columns;
ptr = job->plane_g + i * job->hdr.columns;
else if (j == 2)
ptr = ctx->plane_b + i * ctx->hdr.columns;
ptr = job->plane_b + i * job->hdr.columns;
else
ptr = NULL;
remain = ctx->hdr.columns;
remain = job->hdr.columns;
do {
ret = read(data_fd, ptr, remain);
if (ret < 0) {
ERROR("Read failed (%d/%d/%u) (%d/%u @ %d)\n",
ret, remain, ctx->hdr.columns,
i, ctx->hdr.rows, j);
ret, remain, job->hdr.columns,
i, job->hdr.rows, j);
perror("ERROR: Read failed");
return CUPS_BACKEND_CANCEL;
}
@ -410,13 +420,15 @@ static int kodak1400_read_parse(void *vctx, int data_fd) {
}
}
*vjob = job;
return CUPS_BACKEND_OK;
}
static uint8_t idle_data[READBACK_LEN] = { 0xe4, 0x72, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static int kodak1400_main_loop(void *vctx, int copies) {
static int kodak1400_main_loop(void *vctx, const void *vjob) {
struct kodak1400_ctx *ctx = vctx;
uint8_t rdbuf[READBACK_LEN], rdbuf2[READBACK_LEN];
@ -424,6 +436,16 @@ static int kodak1400_main_loop(void *vctx, int copies) {
int last_state = -1, state = S_IDLE;
int num, ret;
uint16_t temp16;
int copies;
const struct kodak1400_printjob *job = vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
copies = job->copies;
top:
if (state != last_state) {
@ -479,9 +501,9 @@ top:
cmdbuf[0] = 0x1b;
cmdbuf[1] = 0x5a;
cmdbuf[2] = 0x53;
temp16 = be16_to_cpu(ctx->hdr.columns);
temp16 = be16_to_cpu(job->hdr.columns);
memcpy(cmdbuf+3, &temp16, 2);
temp16 = be16_to_cpu(ctx->hdr.rows);
temp16 = be16_to_cpu(job->hdr.rows);
memcpy(cmdbuf+5, &temp16, 2);
if ((ret = send_data(ctx->dev, ctx->endp_down,
@ -492,7 +514,7 @@ top:
memset(cmdbuf, 0, CMDBUF_LEN);
cmdbuf[0] = 0x1b;
cmdbuf[1] = 0x59;
cmdbuf[2] = ctx->hdr.matte; // ???
cmdbuf[2] = job->hdr.matte; // ???
if ((ret = send_data(ctx->dev, ctx->endp_down,
cmdbuf, CMDBUF_LEN)))
@ -502,7 +524,7 @@ top:
memset(cmdbuf, 0, CMDBUF_LEN);
cmdbuf[0] = 0x1b;
cmdbuf[1] = 0x60;
cmdbuf[2] = ctx->hdr.laminate;
cmdbuf[2] = job->hdr.laminate;
if (send_data(ctx->dev, ctx->endp_down,
cmdbuf, CMDBUF_LEN))
@ -512,7 +534,7 @@ top:
memset(cmdbuf, 0, CMDBUF_LEN);
cmdbuf[0] = 0x1b;
cmdbuf[1] = 0x62;
cmdbuf[2] = ctx->hdr.lam_strength;
cmdbuf[2] = job->hdr.lam_strength;
if ((ret = send_data(ctx->dev, ctx->endp_down,
cmdbuf, CMDBUF_LEN)))
@ -522,7 +544,7 @@ top:
memset(cmdbuf, 0, CMDBUF_LEN);
cmdbuf[0] = 0x1b;
cmdbuf[1] = 0x61;
cmdbuf[2] = ctx->hdr.unk1; // ???
cmdbuf[2] = job->hdr.unk1; // ???
if ((ret = send_data(ctx->dev, ctx->endp_down,
cmdbuf, CMDBUF_LEN)))
@ -532,7 +554,7 @@ top:
break;
case S_PRINTER_READY_Y:
INFO("Sending YELLOW plane\n");
if ((ret = send_plane(ctx, 1, ctx->plane_b, cmdbuf)))
if ((ret = send_plane(ctx, job, 1, job->plane_b, cmdbuf)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_SENT_Y;
break;
@ -542,7 +564,7 @@ top:
break;
case S_PRINTER_READY_M:
INFO("Sending MAGENTA plane\n");
if ((ret = send_plane(ctx, 2, ctx->plane_g, cmdbuf)))
if ((ret = send_plane(ctx, job, 2, job->plane_g, cmdbuf)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_SENT_M;
break;
@ -552,13 +574,13 @@ top:
break;
case S_PRINTER_READY_C:
INFO("Sending CYAN plane\n");
if ((ret = send_plane(ctx, 3, ctx->plane_r, cmdbuf)))
if ((ret = send_plane(ctx, job, 3, job->plane_r, cmdbuf)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_SENT_C;
break;
case S_PRINTER_SENT_C:
if (!memcmp(rdbuf, idle_data, READBACK_LEN)) {
if (ctx->hdr.laminate)
if (job->hdr.laminate)
state = S_PRINTER_READY_L;
else
state = S_PRINTER_DONE;
@ -566,7 +588,7 @@ top:
break;
case S_PRINTER_READY_L:
INFO("Laminating page\n");
if ((ret = send_plane(ctx, 4, NULL, cmdbuf)))
if ((ret = send_plane(ctx, job, 4, NULL, cmdbuf)))
return CUPS_BACKEND_FAILED;
state = S_PRINTER_SENT_L;
break;
@ -635,13 +657,14 @@ static const char *kodak1400_prefixes[] = {
struct dyesub_backend kodak1400_backend = {
.name = "Kodak 1400/805",
.version = "0.37",
.version = "0.38",
.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,
.query_markers = kodak1400_query_markers,

View file

@ -167,6 +167,12 @@ static const char *kodak68xx_mediatypes(int type)
#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;
@ -174,14 +180,10 @@ struct kodak605_ctx {
int type;
uint8_t jobid;
struct kodak605_hdr hdr;
struct kodak605_media_list *media;
struct marker marker;
uint8_t *databuf;
int datalen;
};
static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media)
@ -299,63 +301,75 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, int typ
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;
if (ctx->databuf)
free(ctx->databuf);
free(ctx);
}
static int kodak605_read_parse(void *vctx, int data_fd) {
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;
if (!ctx)
return CUPS_BACKEND_CANCEL;
if (ctx->databuf) {
free(ctx->databuf);
ctx->databuf = NULL;
job = malloc(sizeof(*job));
if (!job) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
memset(job, 0, sizeof(*job));
/* Read in then validate header */
ret = read(data_fd, &ctx->hdr, sizeof(ctx->hdr));
if (ret < 0 || ret != sizeof(ctx->hdr)) {
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(ctx->hdr));
ret, 0, (int)sizeof(job->hdr));
perror("ERROR: Read failed");
return CUPS_BACKEND_CANCEL;
}
if (ctx->hdr.hdr[0] != 0x01 ||
ctx->hdr.hdr[1] != 0x40 ||
ctx->hdr.hdr[2] != 0x0a ||
ctx->hdr.hdr[3] != 0x00) {
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;
}
ctx->datalen = le16_to_cpu(ctx->hdr.rows) * le16_to_cpu(ctx->hdr.columns) * 3;
ctx->databuf = malloc(ctx->datalen);
if (!ctx->databuf) {
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 = ctx->datalen;
uint8_t *ptr = ctx->databuf;
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, ctx->datalen);
ret, remain, job->datalen);
perror("ERROR: Read failed");
return CUPS_BACKEND_CANCEL;
}
@ -364,27 +378,36 @@ static int kodak605_read_parse(void *vctx, int data_fd) {
} while (remain);
}
/* Printer handles generating copies.. */
if (le16_to_cpu(job->hdr.copies) < copies)
job->hdr.copies = cpu_to_le16(copies);
*vjob = job;
return CUPS_BACKEND_OK;
}
static int kodak605_main_loop(void *vctx, int copies) {
static int kodak605_main_loop(void *vctx, const void *vjob) {
struct kodak605_ctx *ctx = vctx;
struct kodak605_status sts;
int num, ret;
const struct kodak605_printjob *job = vjob;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (!job)
return CUPS_BACKEND_FAILED;
/* Printer handles generating copies.. */
if (le16_to_cpu(ctx->hdr.copies) < copies)
ctx->hdr.copies = cpu_to_le16(copies);
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 == ctx->hdr.rows &&
ctx->media->entries[num].cols == ctx->hdr.columns)
if (ctx->media->entries[num].rows == hdr.rows &&
ctx->media->entries[num].cols == hdr.columns)
break;
}
if (num == ctx->media->count) {
@ -425,12 +448,12 @@ static int kodak605_main_loop(void *vctx, int copies) {
}
/* Use specified jobid */
ctx->hdr.jobid = ctx->jobid;
hdr.jobid = ctx->jobid;
{
INFO("Sending image header (internal id %u)\n", ctx->jobid);
if ((ret = send_data(ctx->dev, ctx->endp_down,
(uint8_t*)&ctx->hdr, sizeof(ctx->hdr))))
(uint8_t*)&hdr, sizeof(hdr))))
return CUPS_BACKEND_FAILED;
struct kodak605_sts_hdr resp;
@ -448,7 +471,7 @@ static int kodak605_main_loop(void *vctx, int copies) {
INFO("Sending image data\n");
if ((ret = send_data(ctx->dev, ctx->endp_down,
ctx->databuf, ctx->datalen)))
job->databuf, job->datalen)))
return CUPS_BACKEND_FAILED;
INFO("Image data sent\n");
@ -690,13 +713,14 @@ static const char *kodak605_prefixes[] = {
/* Exported */
struct dyesub_backend kodak605_backend = {
.name = "Kodak 605",
.version = "0.30",
.version = "0.31",
.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,
.read_parse = kodak605_read_parse,
.main_loop = kodak605_main_loop,
.query_markers = kodak605_query_markers,

View file

@ -224,6 +224,13 @@ struct kodak68x0_media_readback {
#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;
@ -235,10 +242,6 @@ struct kodak6800_ctx {
struct kodak68x0_media_readback *media;
struct kodak6800_hdr hdr;
uint8_t *databuf;
int datalen;
struct marker marker;
};
@ -1041,63 +1044,75 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev, int ty
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;
if (ctx->databuf)
free(ctx->databuf);
free(ctx);
}
static int kodak6800_read_parse(void *vctx, int data_fd) {
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;
if (!ctx)
return CUPS_BACKEND_FAILED;
if (ctx->databuf) {
free(ctx->databuf);
ctx->databuf = NULL;
job = malloc(sizeof(*job));
if (!job) {
ERROR("Memory allocation failure!\n");
return CUPS_BACKEND_RETRY_CURRENT;
}
memset(job, 0, sizeof(*job));
/* Read in then validate header */
ret = read(data_fd, &ctx->hdr, sizeof(ctx->hdr));
if (ret < 0 || ret != sizeof(ctx->hdr)) {
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",