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.
This commit is contained in:
parent
0eef76d2b3
commit
3764319eb2
|
@ -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]
|
||||
|
|
Loading…
Reference in a new issue