dnpds40: More granular detection of the number of buffers needed to

print a given job.

300dpi, only 1 buffer needed.
600dpi w/ DS80: if matte and >8x11 length, 2 needed
600dpi w/ DS40: if matte and 5x7, 2 needed.
                if >=6x8 length, 2 needed
This commit is contained in:
Solomon Peachy 2014-02-02 14:11:17 -05:00
parent 2886b6ecd7
commit 7914f95d9c
1 changed files with 58 additions and 20 deletions

View File

@ -60,9 +60,8 @@ struct dnpds40_ctx {
uint8_t endp_up; uint8_t endp_up;
uint8_t endp_down; uint8_t endp_down;
int type; int type;
int y_res;
int buf_needed; int buf_needed;
uint8_t *qty_offset; uint8_t *qty_offset;
@ -152,8 +151,8 @@ static char *dnpds40_statuses(char *str)
case 1010: return "No Scrap Box"; case 1010: return "No Scrap Box";
case 1100: return "Paper End"; case 1100: return "Paper End";
case 1200: return "Ribbon End"; case 1200: return "Ribbon End";
case 1300: return "Paper jam"; case 1300: return "Paper Jam";
case 1400: return "Ribbon error"; case 1400: return "Ribbon Error";
case 1500: return "Paper Definition Error"; case 1500: return "Paper Definition Error";
case 1600: return "Data Error"; case 1600: return "Data Error";
case 2000: return "Head Voltage Error"; case 2000: return "Head Voltage Error";
@ -171,7 +170,7 @@ static char *dnpds40_statuses(char *str)
break; break;
} }
return "Unkown type"; return "Unkown Error";
} }
static int dnpds40_do_cmd(struct dnpds40_ctx *ctx, static int dnpds40_do_cmd(struct dnpds40_ctx *ctx,
@ -321,6 +320,8 @@ static int dnpds40_read_parse(void *vctx, int data_fd) {
int i, j, run = 1; int i, j, run = 1;
char buf[9] = { 0 }; char buf[9] = { 0 };
uint32_t matte = 0, multicut = 0, dpi = 0;
if (!ctx) if (!ctx)
return 1; return 1;
@ -329,6 +330,15 @@ static int dnpds40_read_parse(void *vctx, int data_fd) {
ctx->databuf = NULL; ctx->databuf = NULL;
} }
/* There's no way to figure out the total job length in advance, we
have to parse the stream until we get to the image plane data,
and even then the stream can contain arbitrary commands later.
So instead, we allocate a buffer of the maximum possible length,
then parse the incoming stream until we hit the START command at
the end of the job.
*/
ctx->datalen = 0; ctx->datalen = 0;
ctx->databuf = malloc(MAX_PRINTJOB_LEN); ctx->databuf = malloc(MAX_PRINTJOB_LEN);
if (!ctx->databuf) { if (!ctx->databuf) {
@ -336,12 +346,9 @@ static int dnpds40_read_parse(void *vctx, int data_fd) {
return 2; return 2;
} }
// XXX no way to figure out print job length without parsing stream
// until we get to the plane data
/* Read in command header */
while (run) { while (run) {
int remain; int remain;
/* Read in command header */
i = read(data_fd, ctx->databuf + ctx->datalen, i = read(data_fd, ctx->databuf + ctx->datalen,
sizeof(struct dnpds40_cmd)); sizeof(struct dnpds40_cmd));
if (i < 0) if (i < 0)
@ -379,17 +386,47 @@ static int dnpds40_read_parse(void *vctx, int data_fd) {
if(!memcmp("CNTRL QTY", ctx->databuf + ctx->datalen+2, 9)) { if(!memcmp("CNTRL QTY", ctx->databuf + ctx->datalen+2, 9)) {
ctx->qty_offset = ctx->databuf + ctx->datalen + 32; ctx->qty_offset = ctx->databuf + ctx->datalen + 32;
} }
if(!memcmp("CNTRL OVERCOAT", ctx->databuf + ctx->datalen+2, 14)) {
memcpy(buf, ctx->databuf + ctx->datalen + 32, 8);
matte = atoi(buf);
matte = le32_to_cpu(matte);
}
if(!memcmp("CNTRL MULTICUT", ctx->databuf + ctx->datalen+2, 14)) {
memcpy(buf, ctx->databuf + ctx->datalen + 32, 8);
multicut = atoi(buf);
multicut = le32_to_cpu(multicut);
}
if(!memcmp("IMAGE YPLANE", ctx->databuf + ctx->datalen + 2, 12)) { if(!memcmp("IMAGE YPLANE", ctx->databuf + ctx->datalen + 2, 12)) {
uint32_t x; uint32_t x_ppm;
memcpy(&x, ctx->databuf + ctx->datalen + 32 + 42, sizeof(x)); memcpy(&x_ppm, ctx->databuf + ctx->datalen + 32 + 42, sizeof(x_ppm));
x = le32_to_cpu(x); x_ppm = le32_to_cpu(x_ppm);
if (x == 23615) { ctx->buf_needed = 1;
ctx->y_res = 600; dpi = 300;
ctx->buf_needed = 2; // XXX not always true.
} else { // x == 11808 or anything else.. if (x_ppm == 23615) { /* pixels per meter, aka 600dpi */
ctx->y_res = 300; dpi = 600;
ctx->buf_needed = 1; if (ctx->type == P_DNP_DS80) { /* DS80/CX-W */
if (matte && (multicut == 21 || // A4 length
multicut == 20 || // 8x4*3
multicut == 19 || // 8x8+8x4
multicut == 15 || // 8x6*2
multicut == 7)) // 8x12
ctx->buf_needed = 2;
} else { /* DS40/CX/CY/etc */
if (multicut == 4 || // 6x8
multicut == 5 || // 6x9
multicut == 12) // 6x4*2
ctx->buf_needed = 2;
else if (matte && multicut == 3) // 5x7
ctx->buf_needed = 2;
}
/* If we are missing a multicut command,
we can't parse this job so must assume
worst case size needing both buffers! */
if (!multicut)
ctx->buf_needed = 2;
} }
} }
@ -400,6 +437,7 @@ static int dnpds40_read_parse(void *vctx, int data_fd) {
/* Add in the size of this chunk */ /* Add in the size of this chunk */
ctx->datalen += sizeof(struct dnpds40_cmd) + j; ctx->datalen += sizeof(struct dnpds40_cmd) + j;
} }
DEBUG("dpi %d matte %d mcut %d bufs %d\n", dpi, matte, multicut, ctx->buf_needed);
if (!ctx->datalen) if (!ctx->datalen)
return 1; return 1;
@ -450,9 +488,9 @@ top:
return -1; return -1;
dnpds40_cleanup_string((char*)resp, len); dnpds40_cleanup_string((char*)resp, len);
/* Check to see if we have sufficient buffers */
if (!strcmp("FBP00", (char*)resp) || if (!strcmp("FBP00", (char*)resp) ||
(ctx->buf_needed == 1 && !strcmp("FBP01", (char*)resp))) { (ctx->buf_needed == 1 && !strcmp("FBP01", (char*)resp))) {
/* We don't have enough buffers */
INFO("Insufficient printer buffers, retrying...\n"); INFO("Insufficient printer buffers, retrying...\n");
sleep(1); sleep(1);
goto top; goto top;
@ -911,7 +949,7 @@ static int dnpds40_cmdline_arg(void *vctx, int run, char *arg1, char *arg2)
/* Exported */ /* Exported */
struct dyesub_backend dnpds40_backend = { struct dyesub_backend dnpds40_backend = {
.name = "DNP DS40/DS80", .name = "DNP DS40/DS80",
.version = "0.24", .version = "0.25",
.uri_prefix = "dnpds40", .uri_prefix = "dnpds40",
.cmdline_usage = dnpds40_cmdline, .cmdline_usage = dnpds40_cmdline,
.cmdline_arg = dnpds40_cmdline_arg, .cmdline_arg = dnpds40_cmdline_arg,