From 3764319eb2a88bf75a037dac50a98e9028478c27 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 29 Jan 2014 10:22:20 -0500 Subject: [PATCH] canonselphy: Rewrite the error detection code. Now instead of a dumb offset/flag, we parse the whole response from the printer and holistically figure out what's wrong. On a per-printer type basis. This was needed because the ES40 and CP790 share a single "backend" but have radically different error reporting. --- backend_canonselphy.c | 175 +++++++++++++++++++++++++++++++++++------- 1 file changed, 149 insertions(+), 26 deletions(-) diff --git a/backend_canonselphy.c b/backend_canonselphy.c index 6aeedbe..812d177 100644 --- a/backend_canonselphy.c +++ b/backend_canonselphy.c @@ -53,9 +53,131 @@ struct printer_data { int16_t paper_codes[256]; int16_t pgcode_offset; /* Offset into printjob for paper type */ int16_t paper_code_offset; /* Offset in readback for paper type */ - int16_t error_offset; + int (*error_detect)(uint8_t *rdbuf); }; +static int es1_error_detect(uint8_t *rdbuf) +{ + if (!rdbuf[1]) + return 0; + + if (rdbuf[9] == 0x80) + ERROR("No media loaded!\n"); + else if (rdbuf[9] == 0x00) + ERROR("Cover open!\n"); + else + ERROR("Unknown error - %02x\n", + rdbuf[9]); + return 1; +} + +static int es2_error_detect(uint8_t *rdbuf) +{ + if (rdbuf[0] == 0x16 && + rdbuf[1] == 0x01) { + ERROR("Cover open!\n"); + return 1; + } + + if (rdbuf[0] == 0x02 && + rdbuf[4] == 0x05 && + rdbuf[5] == 0x05 && + rdbuf[6] == 0x02) { + ERROR("No media loaded!\n"); + return 1; + } + + return 0; +} + +static int es3_error_detect(uint8_t *rdbuf) +{ + if (rdbuf[8] == 0x01) { + if (rdbuf[10] == 0x0f) { + ERROR("Communications Error\n"); + } else if (rdbuf[10] == 0x01) { + ERROR("No media/ribbon loaded!\n"); + } else { + ERROR("Unknown error - %02x + %02x\n", + rdbuf[8], rdbuf[10]); + } + return 1; + } else if (rdbuf[8] == 0x03 && + rdbuf[10] == 0x02) { + ERROR("No media!\n"); + return 1; + } else if (rdbuf[8] == 0x08 && + rdbuf[10] == 0x04) { + ERROR("Cover open!\n"); + return 1; + } + + if (rdbuf[8] || rdbuf[10]) { + ERROR("Unknown error - %02x + %02x\n", + rdbuf[8], rdbuf[10]); + } + + return 0; +} + +static int es40_error_detect(uint8_t *rdbuf) +{ + if (!rdbuf[4] && !rdbuf[5]) { + /* ES40 */ + if (!rdbuf[3]) + return 0; + + if (rdbuf[3] == 0x01) + ERROR("Generic communication error\n"); + else if (rdbuf[3] == 0x32) + ERROR("Cover open or media empty!\n"); + else + ERROR("Unknown error - %02x\n", rdbuf[3]); + return 1; + } + + /* CP790 */ + if (rdbuf[4] == 0x10 && rdbuf[5] == 0xff) { + ERROR("No ribbon!\n"); + return 1; + } else if (rdbuf[4] == 0xff && rdbuf[5] == 0x01) { + ERROR("No media loaded!\n"); + return 1; + } + + return 0; +} + +static int cp10_error_detect(uint8_t *rdbuf) +{ + if (!rdbuf[2]) + return 0; + + if (rdbuf[2] == 0x80) + ERROR("No ribbon\n"); + else if (rdbuf[2] == 0x01) + ERROR("No media!\n"); + else + ERROR("Unknown error - %02x\n", rdbuf[2]); + return 1; +} + +static int cpxxx_error_detect(uint8_t *rdbuf) +{ + if (!rdbuf[2]) + return 0; + + if (rdbuf[2] == 0x01) + ERROR("Out of paper!\n"); + else if (rdbuf[2] == 0x04) + ERROR("Ribbon problem!\n"); + else if (rdbuf[2] == 0x08) + ERROR("Ribbon depleted!\n"); + else + ERROR("Unknown error - %02x\n", rdbuf[2]); + return 1; +} + static struct printer_data selphy_printers[] = { { .type = P_ES1, .model = "SELPHY ES1", @@ -70,7 +192,7 @@ static struct printer_data selphy_printers[] = { // .paper_codes .pgcode_offset = 3, .paper_code_offset = 6, - .error_offset = 1, + .error_detect = es1_error_detect, }, { .type = P_ES2_20, .model = "SELPHY ES2/ES20", @@ -85,7 +207,7 @@ static struct printer_data selphy_printers[] = { // .paper_codes .pgcode_offset = 2, .paper_code_offset = 4, - .error_offset = 1, // XXX insufficient + .error_detect = es2_error_detect, }, { .type = P_ES3_30, .model = "SELPHY ES3/ES30", @@ -100,7 +222,7 @@ static struct printer_data selphy_printers[] = { // .paper_codes .pgcode_offset = 2, .paper_code_offset = -1, - .error_offset = 8, // or 10 + .error_detect = es3_error_detect, }, { .type = P_ES40_CP790, .model = "SELPHY ES40/CP790", @@ -115,7 +237,7 @@ static struct printer_data selphy_printers[] = { // .paper_codes .pgcode_offset = 2, .paper_code_offset = 11, - .error_offset = 3, + .error_detect = es40_error_detect, }, { .type = P_CP_XXX, .model = "SELPHY CP Series (!CP-10/CP790)", @@ -130,7 +252,7 @@ static struct printer_data selphy_printers[] = { // .paper_codes .pgcode_offset = 3, .paper_code_offset = 6, - .error_offset = 2, + .error_detect = cpxxx_error_detect, }, { .type = P_CP10, .model = "SELPHY CP-10", @@ -145,7 +267,7 @@ static struct printer_data selphy_printers[] = { // .clear_error .pgcode_offset = -1, .paper_code_offset = -1, - .error_offset = 2, + .error_detect = cp10_error_detect, }, { .type = -1 }, }; @@ -215,17 +337,12 @@ enum { S_FINISHED, }; -static int fancy_memcmp(const uint8_t *buf_a, const int16_t *buf_b, uint len, int16_t papercode_offset, int16_t papercode_val) +static int fancy_memcmp(const uint8_t *buf_a, const int16_t *buf_b, uint len) { uint i; for (i = 0 ; i < len ; i++) { - if (papercode_offset != -1 && i == (uint) papercode_offset) { - if (papercode_val == -1) - continue; - else if ((buf_a[i] & 0xf) != (papercode_val & 0xf)) - return INCORRECT_PAPER; - } else if (buf_b[i] == -1) + if (buf_b[i] == -1) continue; else if (buf_a[i] > buf_b[i]) return 1; @@ -530,18 +647,25 @@ top: fflush(stderr); /* Error detection */ - if (ctx->printer->error_offset != -1 && - rdbuf[ctx->printer->error_offset]) { - ERROR("Printer reported error condition %02x; aborting. (Out of ribbon/paper?)\n", rdbuf[ctx->printer->error_offset]); + if (ctx->printer->error_detect(rdbuf)) return 4; - } switch(state) { case S_IDLE: INFO("Waiting for printer idle\n"); - if (!fancy_memcmp(rdbuf, ctx->printer->init_readback, READBACK_LEN, ctx->printer->paper_code_offset, ctx->paper_code)) { - state = S_PRINTER_READY; + if (fancy_memcmp(rdbuf, ctx->printer->init_readback, READBACK_LEN)) + break; + + /* Make sure paper is correct */ + if (ctx->printer->paper_code_offset != -1) { + if ((rdbuf[ctx->printer->paper_code_offset] & 0x0f) != + (ctx->paper_code & 0x0f)) { + ERROR("Incorrect paper loaded, aborting job!\n"); + return 3; /* Hold this job, don't stop queue */ + } } + + state = S_PRINTER_READY; break; case S_PRINTER_READY: INFO("Printing started; Sending init sequence\n"); @@ -552,7 +676,7 @@ top: state = S_PRINTER_INIT_SENT; break; case S_PRINTER_INIT_SENT: - if (!fancy_memcmp(rdbuf, ctx->printer->ready_y_readback, READBACK_LEN, ctx->printer->paper_code_offset, ctx->paper_code)) { + if (!fancy_memcmp(rdbuf, ctx->printer->ready_y_readback, READBACK_LEN)) { state = S_PRINTER_READY_Y; } break; @@ -568,7 +692,7 @@ top: state = S_PRINTER_Y_SENT; break; case S_PRINTER_Y_SENT: - if (!fancy_memcmp(rdbuf, ctx->printer->ready_m_readback, READBACK_LEN, ctx->printer->paper_code_offset, ctx->paper_code)) { + if (!fancy_memcmp(rdbuf, ctx->printer->ready_m_readback, READBACK_LEN)) { if (ctx->bw_mode) state = S_PRINTER_DONE; else @@ -584,7 +708,7 @@ top: state = S_PRINTER_M_SENT; break; case S_PRINTER_M_SENT: - if (!fancy_memcmp(rdbuf, ctx->printer->ready_c_readback, READBACK_LEN, ctx->printer->paper_code_offset, ctx->paper_code)) { + if (!fancy_memcmp(rdbuf, ctx->printer->ready_c_readback, READBACK_LEN)) { state = S_PRINTER_READY_C; } break; @@ -597,7 +721,7 @@ top: state = S_PRINTER_C_SENT; break; case S_PRINTER_C_SENT: - if (!fancy_memcmp(rdbuf, ctx->printer->done_c_readback, READBACK_LEN, ctx->printer->paper_code_offset, ctx->paper_code)) { + if (!fancy_memcmp(rdbuf, ctx->printer->done_c_readback, READBACK_LEN)) { state = S_PRINTER_DONE; } break; @@ -666,7 +790,7 @@ top: struct dyesub_backend canonselphy_backend = { .name = "Canon SELPHY CP/ES", - .version = "0.68", + .version = "0.69", .multipage_capable = 1, .uri_prefix = "canonselphy", .init = canonselphy_init, @@ -834,7 +958,6 @@ struct dyesub_backend canonselphy_backend = { 00 ff 10 00 ff ff ff ff 00 00 00 00 [ready for footer] 01 ff 10 00 ff ff ff ff 01 00 0f 00 [communication error] - 00 ff 00 00 ff ff ff ff 00 00 00 00 [cover open, no media] 00 ff 01 00 ff ff ff ff 01 00 01 00 [error, no media/ink] 00 ff 01 00 ff ff ff ff 03 00 02 00 [attempt to print with no media] 00 ff 01 00 ff ff ff ff 08 00 04 00 [attempt to print with cover open]