all: Major updates to CUPS marker reporting

* use 'ribbonWax' instead of 'ink-ribbon'  (as per RFC)
 * return media type as the 'marker' name, if known or inferrable
 * Selphy CP series gained support
 * Mitsu D70 family gained support for uppper and lower decks
This commit is contained in:
Solomon Peachy 2016-08-19 17:40:12 -04:00
parent d6b2ae3d3a
commit b210c5a5c0
10 changed files with 363 additions and 192 deletions

4
README
View File

@ -114,6 +114,10 @@
DEVICE_URI=someuri \
gutenprint52+usb job-id user title num-copies options [ filename ]
The backend generates output for CUPS to parse, including logging
print counts, and if the printer supports it, reporting media type and
remaining media counts.
***************************************************************************
Standalone usage:

View File

@ -91,9 +91,22 @@ 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 */
int (*error_detect)(uint8_t *rdbuf);
int (*error_detect)(uint8_t *rdbuf);
char *(*pgcode_names)(uint8_t pgcode);
};
static char *generic_pgcode_names(uint8_t pgcode)
{
switch(pgcode & 0xf) {
case 0x01: return "P";
case 0x02: return "L";
case 0x03: return "C";
case 0x04: return "W";
case 0x0f: return "None";
default: return "Unknown";
}
}
static int es1_error_detect(uint8_t *rdbuf)
{
if (rdbuf[1] == 0x01) {
@ -105,9 +118,11 @@ static int es1_error_detect(uint8_t *rdbuf)
return 1;
} else if (rdbuf[4] == 0x01 && rdbuf[5] == 0xff &&
rdbuf[6] == 0xff && rdbuf[7] == 0xff) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
} else if (rdbuf[0] == 0x0f) {
ATTR("marker-levels=%d\n", 0);
ERROR("Out of media!\n");
return 1;
}
@ -127,11 +142,13 @@ static int es2_error_detect(uint8_t *rdbuf)
rdbuf[4] == 0x05 &&
rdbuf[5] == 0x05 &&
rdbuf[6] == 0x02) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
}
if (rdbuf[0] == 0x14) {
ATTR("marker-levels=%d\n", 0);
ERROR("Out of media!\n");
return 1;
}
@ -145,6 +162,7 @@ static int es3_error_detect(uint8_t *rdbuf)
if (rdbuf[10] == 0x0f) {
ERROR("Communications Error\n");
} else if (rdbuf[10] == 0x01) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
} else {
ERROR("Unknown error - %02x + %02x\n",
@ -153,6 +171,7 @@ static int es3_error_detect(uint8_t *rdbuf)
return 1;
} else if (rdbuf[8] == 0x03 &&
rdbuf[10] == 0x02) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
} else if (rdbuf[8] == 0x08 &&
@ -182,10 +201,12 @@ static int es40_error_detect(uint8_t *rdbuf)
if (rdbuf[3] == 0x01)
ERROR("Generic communication error\n");
else if (rdbuf[3] == 0x32)
else if (rdbuf[3] == 0x32) {
ATTR("marker-levels=%d\n", 0);
ERROR("Cover open or media empty!\n");
else
} else
ERROR("Unknown error - %02x\n", rdbuf[3]);
return 1;
}
@ -200,15 +221,18 @@ static int cp790_error_detect(uint8_t *rdbuf)
ERROR("No paper tray loaded!\n");
return 1;
} else if (rdbuf[3]) {
if ((rdbuf[3] & 0xf) == 0x02) // 0x12 0x22
if ((rdbuf[3] & 0xf) == 0x02) { // 0x12 0x22
ATTR("marker-levels=%d\n", 0);
ERROR("No paper tray loaded!\n");
else if ((rdbuf[3] & 0xf) == 0x03) // 0x13 0x23
} else if ((rdbuf[3] & 0xf) == 0x03) { // 0x13 0x23
ATTR("marker-levels=%d\n", 0);
ERROR("Empty paper tray or feed error!\n");
else if (rdbuf[3] == 0x11)
} else if (rdbuf[3] == 0x11)
ERROR("Paper feed error!\n");
else if (rdbuf[3] == 0x21)
else if (rdbuf[3] == 0x21) {
ATTR("marker-levels=%d\n", 0);
ERROR("Ribbon depleted!\n");
else
} else
ERROR("Unknown error - %02x\n", rdbuf[3]);
return 1;
}
@ -216,19 +240,28 @@ static int cp790_error_detect(uint8_t *rdbuf)
return 0;
}
static char *cp10_pgcode_names(uint8_t pgcode)
{
switch (pgcode) {
default: return "C";
};
}
static int cp10_error_detect(uint8_t *rdbuf)
{
if (!rdbuf[2])
return 0;
if (rdbuf[2] == 0x80)
if (rdbuf[2] == 0x80) {
ATTR("marker-levels=%d\n", 0);
ERROR("No ribbon loaded\n");
else if (rdbuf[2] == 0x08)
} else if (rdbuf[2] == 0x08) {
ATTR("marker-levels=%d\n", 0);
ERROR("Ribbon depleted!\n");
else if (rdbuf[2] == 0x01)
} else if (rdbuf[2] == 0x01) {
ATTR("marker-levels=%d\n", 0);
ERROR("No paper loaded!\n");
else
} else
ERROR("Unknown error - %02x\n", rdbuf[2]);
return 1;
}
@ -238,13 +271,15 @@ static int cpxxx_error_detect(uint8_t *rdbuf)
if (!rdbuf[2])
return 0;
if (rdbuf[2] == 0x01)
if (rdbuf[2] == 0x01) {
ATTR("marker-levels=%d\n", 0);
ERROR("Paper feed problem!\n");
else if (rdbuf[2] == 0x04)
} else if (rdbuf[2] == 0x04)
ERROR("Ribbon problem!\n");
else if (rdbuf[2] == 0x08)
else if (rdbuf[2] == 0x08) {
ATTR("marker-levels=%d\n", 0);
ERROR("Ribbon depleted!\n");
else
} else
ERROR("Unknown error - %02x\n", rdbuf[2]);
return 1;
}
@ -264,6 +299,7 @@ static struct printer_data selphy_printers[] = {
.pgcode_offset = 3,
.paper_code_offset = 6,
.error_detect = es1_error_detect,
.pgcode_names = generic_pgcode_names,
},
{ .type = P_ES2_20,
.model = "SELPHY ES2/ES20",
@ -279,6 +315,7 @@ static struct printer_data selphy_printers[] = {
.pgcode_offset = 2,
.paper_code_offset = 4,
.error_detect = es2_error_detect,
.pgcode_names = generic_pgcode_names,
},
{ .type = P_ES3_30,
.model = "SELPHY ES3/ES30",
@ -294,6 +331,7 @@ static struct printer_data selphy_printers[] = {
.pgcode_offset = 2,
.paper_code_offset = -1,
.error_detect = es3_error_detect,
.pgcode_names = NULL,
},
{ .type = P_ES40,
.model = "SELPHY ES40",
@ -309,6 +347,7 @@ static struct printer_data selphy_printers[] = {
.pgcode_offset = 2,
.paper_code_offset = 11,
.error_detect = es40_error_detect,
.pgcode_names = generic_pgcode_names,
},
{ .type = P_CP790,
.model = "SELPHY CP790",
@ -321,10 +360,10 @@ static struct printer_data selphy_printers[] = {
.done_c_readback = { 0x00, 0x00, 0x10, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
.clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.clear_error_len = 12,
// .paper_codes
.pgcode_offset = 2,
.paper_code_offset = -1, /* Uses a different technique */
.error_detect = cp790_error_detect,
.pgcode_names = generic_pgcode_names,
},
{ .type = P_CP_XXX,
.model = "SELPHY CP Series (!CP-10/CP790)",
@ -337,10 +376,10 @@ static struct printer_data selphy_printers[] = {
.done_c_readback = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, -1, 0x00, 0x00, 0x00, 0x00, -1 },
.clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.clear_error_len = 12,
// .paper_codes
.pgcode_offset = 3,
.paper_code_offset = 6,
.error_detect = cpxxx_error_detect,
.pgcode_names = generic_pgcode_names,
},
{ .type = P_CP10,
.model = "SELPHY CP-10",
@ -353,10 +392,10 @@ static struct printer_data selphy_printers[] = {
.done_c_readback = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.clear_error_len = 12,
// .paper_codes
.pgcode_offset = -1,
.pgcode_offset = 2,
.paper_code_offset = -1,
.error_detect = cp10_error_detect,
.pgcode_names = cp10_pgcode_names,
},
{ .type = -1 },
};
@ -763,6 +802,13 @@ static int canonselphy_main_loop(void *vctx, int copies) {
if (ret < 0)
return CUPS_BACKEND_FAILED;
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf[ctx->printer->paper_code_offset]) : "Unknown");
ATTR("marker-types=ribbonWax\n");
ATTR("marker-levels=%d\n", -3); /* ie Unknown but OK */
top:
if (state != last_state) {
@ -983,7 +1029,7 @@ static int canonselphy_cmdline_arg(void *vctx, int argc, char **argv)
struct dyesub_backend canonselphy_backend = {
.name = "Canon SELPHY CP/ES",
.version = "0.90",
.version = "0.91",
.uri_prefix = "canonselphy",
.cmdline_arg = canonselphy_cmdline_arg,
.init = canonselphy_init,

View File

@ -1195,8 +1195,8 @@ static int dnpds40_main_loop(void *vctx, int copies) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
ATTR("marker-names='%s'\n", dnpds40_media_types(ctx->media));
ATTR("marker-types=ribbonWax\n");
}
top:

View File

@ -148,6 +148,20 @@ static char *bank_statuses(uint8_t v)
}
}
static const char *kodak68xx_mediatypes(int type)
{
switch(type) {
case KODAK68x0_MEDIA_NONE:
return "No media";
case KODAK68x0_MEDIA_6R:
case KODAK68x0_MEDIA_6TR2:
return "Kodak 6R";
default:
return "Unknown";
}
return "Unknown";
}
#define CMDBUF_LEN 4
/* Private data stucture */
@ -380,8 +394,8 @@ static int kodak605_main_loop(void *vctx, int copies) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
ATTR("marker-names='%s'\n", kodak68xx_mediatypes(ctx->media->type));
ATTR("marker-types=ribbonWax\n");
INFO("Waiting for printer idle\n");
@ -506,7 +520,7 @@ static void kodak605_dump_status(struct kodak605_ctx *ctx, struct kodak605_statu
INFO("\t Remaining : Unknown\n");
}
}
INFO("Donor : %d%%\n", sts->donor);
}

View File

@ -240,6 +240,20 @@ struct kodak6800_ctx {
uint8_t last_donor;
};
static const char *kodak68xx_mediatypes(int type)
{
switch(type) {
case KODAK68x0_MEDIA_NONE:
return "No media";
case KODAK68x0_MEDIA_6R:
case KODAK68x0_MEDIA_6TR2:
return "Kodak 6R";
default:
return "Unknown";
}
return "Unknown";
}
/* Baseline commands */
static int kodak6800_do_cmd(struct kodak6800_ctx *ctx,
void *cmd, int cmd_len,
@ -262,6 +276,8 @@ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx,
return 0;
}
static void kodak68x0_dump_mediainfo(struct kodak68x0_media_readback *media)
{
int i;
@ -1124,8 +1140,8 @@ static int kodak6800_main_loop(void *vctx, int copies) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
ATTR("marker-names='%s'\n", kodak68xx_mediatypes(ctx->media->type));
ATTR("marker-types=ribbonWax\n");
INFO("Waiting for printer idle\n");

View File

@ -62,14 +62,19 @@ struct mitsu70x_ctx {
int matte;
uint16_t jobid;
uint16_t jobid;
uint16_t rows;
uint16_t cols;
uint16_t last_donor_l;
uint16_t last_donor_u;
int num_decks;
#ifdef ENABLE_CORRTABLES
struct mitsu70x_corrdata *corrdata;
struct mitsu70x_corrdatalens *corrdatalens;
char *laminatefname;
#endif
#endif
};
/* Printer data structures */
@ -197,7 +202,7 @@ struct mitsu70x_status_deck {
uint8_t temperature;
uint8_t error_status[3];
uint8_t rsvd_a[10];
uint8_t media_brand;
uint8_t media_type;
uint8_t rsvd_b[2];
@ -245,7 +250,7 @@ struct mitsu70x_hdr {
uint8_t speed;
uint8_t zero1[7];
uint8_t deck;
uint8_t deck; /* 0 = default, 1 = lower, 2 = upper */
uint8_t zero2[7];
uint8_t laminate; /* 00 == on, 01 == off */
uint8_t laminate_mode;
@ -548,6 +553,20 @@ static char *mitsu70x_errors(uint8_t *err)
return "Unknown error";
}
static const char *mitsu70x_media_types(uint8_t brand, uint8_t type)
{
if (brand == 0xff && type == 0x02)
return "CKD746 (4x6)";
else if (brand == 0xff && type == 0x0f)
return "CKD768 (6x8)";
else if (brand == 0x61 && type == 0x8f)
return "CKK76R (6x8)";
else if (brand == 0x6c && type == 0x8f)
return "CKK76R (6x8)";
else
return "Unknown";
}
#define CMDBUF_LEN 512
#define READBACK_LEN 256
@ -583,7 +602,8 @@ static void mitsu70x_attach(void *vctx, struct libusb_device_handle *dev,
ctx->type = lookup_printer_type(&mitsu70x_backend,
desc.idVendor, desc.idProduct);
}
ctx->last_donor_l = ctx->last_donor_u = 65535;}
static void mitsu70x_teardown(void *vctx) {
struct mitsu70x_ctx *ctx = vctx;
@ -639,7 +659,7 @@ repeat:
return CUPS_BACKEND_CANCEL;
}
#ifdef ENABLE_CORRTABLES
#ifdef ENABLE_CORRTABLES
/* Figure out the correction data table to use */
if (ctx->type == P_MITSU_D70X) {
struct mitsu70x_hdr *print = (struct mitsu70x_hdr *) &hdr[512];
@ -774,7 +794,7 @@ static int mitsu70x_get_jobstatus(struct mitsu70x_ctx *ctx, struct mitsu70x_jobs
ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*resp));
return 4;
}
return 0;
}
@ -807,7 +827,7 @@ static int mitsu70x_get_jobs(struct mitsu70x_ctx *ctx, struct mitsu70x_jobs *res
ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*resp));
return 4;
}
return 0;
}
@ -928,9 +948,10 @@ static int mitsu70x_set_sleeptime(struct mitsu70x_ctx *ctx, uint8_t time)
static int mitsu70x_main_loop(void *vctx, int copies) {
struct mitsu70x_ctx *ctx = vctx;
struct mitsu70x_jobstatus jobstatus;
struct mitsu70x_printerstatus_resp resp;
struct mitsu70x_jobs jobs;
struct mitsu70x_hdr *hdr = (struct mitsu70x_hdr*) (ctx->databuf + sizeof(struct mitsu70x_hdr));
int ret;
if (!ctx)
@ -938,28 +959,6 @@ static int mitsu70x_main_loop(void *vctx, int copies) {
INFO("Waiting for printer idle...\n");
ret = mitsu70x_get_jobs(ctx, &jobs);
if (ret)
return CUPS_BACKEND_FAILED;
#if 0
/* Tell CUPS about the consumables we report */
if (ctx->type == P_MITSU_D70X &&
ctx->num_decks == 2) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00,#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100,100\n");
ATTR("marker-low-levels=10,10\n");
ATTR("marker-names=Ribbon,Ribbon\n");
ATTR("marker-types=ink-ribbon,ribbon\n");
} else {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
}
#endif
top:
/* Query job status for jobid 0 (global) */
ret = mitsu70x_get_jobstatus(ctx, &jobstatus, 0x0000);
@ -991,7 +990,7 @@ top:
sleep(1);
goto top;
}
/* See if we hit a printer error. */
if (jobstatus.error_status[0]) {
ERROR("%s/%s -> %s: %02x/%02x/%02x\n",
@ -1004,11 +1003,43 @@ top:
return CUPS_BACKEND_STOP;
}
if (ctx->num_decks)
goto skip_status;
/* Tell CUPS about the consumables we report */
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (ret)
return CUPS_BACKEND_FAILED;
if (resp.upper.mecha_status[0] != MECHA_STATUS_INIT)
ctx->num_decks = 2;
else
ctx->num_decks = 1;
if (ctx->type == P_MITSU_D70X &&
ctx->num_decks == 2) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00,#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100,100\n");
ATTR("marker-low-levels=10,10\n");
ATTR("marker-names='\"%s\"','\"%s\"'\n",
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type),
mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type));
ATTR("marker-types=ribbonWax,ribbonWax\n");
} else {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n",
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type));
ATTR("marker-types=ribbonWax\n");
}
skip_status:
/* Perform memory status query */
{
struct mitsu70x_memorystatus_resp memory;
INFO("Checking Memory availability\n");
ret = mitsu70x_get_memorystatus(ctx, &memory);
if (ret)
return CUPS_BACKEND_FAILED;
@ -1026,6 +1057,10 @@ top:
}
/* Make sure we don't have any jobid collisions */
ret = mitsu70x_get_jobs(ctx, &jobs);
if (ret)
return CUPS_BACKEND_FAILED;
while (ctx->jobid == be16_to_cpu(jobs.jobid_0) ||
ctx->jobid == be16_to_cpu(jobs.jobid_1)) {
ctx->jobid++;
@ -1039,7 +1074,7 @@ top:
/* Set deck */
if (ctx->type == P_MITSU_D70X) {
hdr->deck = 0; /* D70 use automatic deck selection */
// XXX alternatively route it based on state and media? */
/* XXX alternatively route it based on state and media? */
} else {
hdr->deck = 1; /* All others only have a "lower" deck. */
}
@ -1092,22 +1127,37 @@ top:
INFO("Waiting for printer to acknowledge completion\n");
do {
uint16_t donor_u, donor_l;
sleep(1);
#if 0
// XXXX query printerstatus and dump deck remain/capacity..
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (ret)
return CUPS_BACKEND_FAILED;
donor_l = be16_to_cpu(resp.lower.remain) * 100 / be16_to_cpu(resp.lower.capacity);
if (ctx->type == P_MITSU_D70X &&
ctx->num_decks == 2) {
ATTR("marker-levels=XXX,YYY\n");
donor_u = be16_to_cpu(resp.upper.remain) * 100 / be16_to_cpu(resp.upper.capacity);
if (donor_l != ctx->last_donor_l ||
donor_u != ctx->last_donor_u) {
ctx->last_donor_l = donor_l;
ctx->last_donor_u = donor_u;
ATTR("marker-levels=%d,%d\n", donor_l, donor_u);
}
} else {
ATTR("marker-levels=XXX\n");
if (donor_l != ctx->last_donor_l) {
ctx->last_donor_l = donor_l;
ATTR("marker-levels=%d\n", donor_l);
}
}
#endif
/* Query job status for our used jobid */
ret = mitsu70x_get_jobstatus(ctx, &jobstatus, ctx->jobid);
if (ret)
return CUPS_BACKEND_FAILED;
/* See if we hit a printer error. */
if (jobstatus.error_status[0]) {
ERROR("%s/%s -> %s: %02x/%02x/%02x\n",
@ -1181,49 +1231,38 @@ static void mitsu70x_dump_printerstatus(struct mitsu70x_printerstatus_resp *resp
buf[6] = 0;
INFO("Component #%d ID: %s (checksum %04x)\n",
i, buf, be16_to_cpu(resp->vers[i].checksum));
}
if (resp->upper.mecha_status[0] == MECHA_STATUS_INIT) { /* IOW, Not present */
INFO("Mechanical Status: %s\n",
mitsu70x_mechastatus(resp->lower.mecha_status));
if (resp->lower.error_status[0]) {
INFO("Error Status: %s/%s -> %s\n",
mitsu70x_errorclass(resp->lower.error_status),
mitsu70x_errors(resp->lower.error_status),
mitsu70x_errorrecovery(resp->lower.error_status));
}
INFO("Media type: %02x/%02x\n",
resp->lower.media_brand,
resp->lower.media_type);
INFO("Prints remaining: %03d/%03d\n",
be16_to_cpu(resp->lower.remain),
be16_to_cpu(resp->lower.capacity));
} else {
INFO("Mechanical Status: Upper: %s\n"
" Lower: %s\n",
mitsu70x_mechastatus(resp->upper.mecha_status),
mitsu70x_mechastatus(resp->lower.mecha_status));
}
INFO("Lower Mechanical Status: %s\n",
mitsu70x_mechastatus(resp->lower.mecha_status));
if (resp->lower.error_status[0]) {
INFO("Lower Error Status: %s/%s -> %s\n",
mitsu70x_errorclass(resp->lower.error_status),
mitsu70x_errors(resp->lower.error_status),
mitsu70x_errorrecovery(resp->lower.error_status));
}
INFO("Lower Media type: %s (%02x/%02x)\n",
mitsu70x_media_types(resp->lower.media_brand, resp->lower.media_type),
resp->lower.media_brand,
resp->lower.media_type);
INFO("Lower Prints remaining: %03d/%03d\n",
be16_to_cpu(resp->lower.remain),
be16_to_cpu(resp->lower.capacity));
if (resp->upper.mecha_status[0] != MECHA_STATUS_INIT) {
INFO("Upper Mechanical Status: %s\n",
mitsu70x_mechastatus(resp->upper.mecha_status));
if (resp->upper.error_status[0]) {
INFO("Upper Error Status: %s/%s -> %s\n",
mitsu70x_errorclass(resp->upper.error_status),
mitsu70x_errors(resp->upper.error_status),
mitsu70x_errorrecovery(resp->upper.error_status));
}
if (resp->lower.error_status[0]) {
INFO("Lower Error Status: %s/%s -> %s\n",
mitsu70x_errorclass(resp->lower.error_status),
mitsu70x_errors(resp->lower.error_status),
mitsu70x_errorrecovery(resp->lower.error_status));
}
INFO("Media type: Lower: %02x/%02x\n"
" Upper: %02x/%02x\n",
resp->lower.media_brand,
resp->lower.media_type,
}
INFO("Upper Media type: %s (%02x/%02x)\n",
mitsu70x_media_types(resp->upper.media_brand, resp->upper.media_type),
resp->upper.media_brand,
resp->upper.media_type);
INFO("Prints remaining: Lower: %03d/%03d\n"
" Upper: %03d/%03d\n",
be16_to_cpu(resp->lower.remain),
be16_to_cpu(resp->lower.capacity),
INFO("Upper Prints remaining: %03d/%03d\n",
be16_to_cpu(resp->upper.remain),
be16_to_cpu(resp->upper.capacity));
}
@ -1248,7 +1287,7 @@ static int mitsu70x_query_status(struct mitsu70x_ctx *ctx)
INFO("JOB1 status : %s\n", mitsu70x_jobstatuses(jobs.job1_status));
// XXX are there more?
}
return ret;
}
@ -1267,12 +1306,12 @@ static int mitsu70x_query_serno(struct libusb_device_handle *dev, uint8_t endp_u
if (buf_len > 6) /* Will we ever have a buffer under 6 bytes? */
buf_len = 6;
for (i = 0 ; i < buf_len ; i++) {
*buf++ = le16_to_cpu(resp.serno[i]) & 0x7f;
}
*buf = 0; /* Null-terminate the returned string */
return ret;
}
@ -1318,7 +1357,7 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv)
/* Exported */
struct dyesub_backend mitsu70x_backend = {
.name = "Mitsubishi CP-D70/D707/K60/D80",
.version = "0.39WIP",
.version = "0.40WIP",
.uri_prefix = "mitsu70x",
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,

View File

@ -60,6 +60,7 @@ struct mitsu9550_ctx {
uint16_t last_donor;
uint16_t last_remain;
int marker_reported;
};
/* Spool file structures */
@ -155,6 +156,16 @@ struct mitsu9550_status2 {
if (ret < 0) \
return CUPS_BACKEND_FAILED; \
\
/* Tell CUPS about the consumables we report */ \
if (!ctx->marker_reported) { \
ctx->marker_reported = 1; \
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n"); \
ATTR("marker-high-levels=100\n"); \
ATTR("marker-low-levels=10\n"); \
ATTR("marker-names='%s'\n", mitsu9550_media_types(media->type)); \
ATTR("marker-types=ribbonWax\n"); \
} \
\
/* Sanity-check media response */ \
if (media->remain == 0 || media->max == 0) { \
ERROR("Printer out of media!\n"); \
@ -334,6 +345,27 @@ static int mitsu9550_get_status(struct mitsu9550_ctx *ctx, uint8_t *resp, int st
return 0;
}
static char *mitsu9550_media_types(uint8_t type)
{
switch (type) {
case 0x01:
return "3.5x5";
case 0x02:
return "4x6";
case 0x03:
return "PC";
case 0x04:
return "5x7";
case 0x05:
return "6x9";
case 0x06:
return "V";
default:
return "Unknown";
}
return NULL;
}
static int validate_media(int type, int cols, int rows) {
switch(type) {
case 0x01: /* 3.5x5 */
@ -375,7 +407,7 @@ static int mitsu9550_main_loop(void *vctx, int copies) {
struct mitsu9550_cmd cmd;
uint8_t rdbuf[READBACK_LEN];
uint8_t *ptr;
int ret;
if (!ctx)
@ -387,17 +419,10 @@ static int mitsu9550_main_loop(void *vctx, int copies) {
ptr = ctx->databuf;
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
top:
if (ctx->type == P_MITSU_9550S) {
int num;
/* Send "unknown 1" command */
cmd.cmd[0] = 0x1b;
cmd.cmd[1] = 0x53;
@ -406,7 +431,7 @@ top:
if ((ret = send_data(ctx->dev, ctx->endp_down,
(uint8_t*) &cmd, sizeof(cmd))))
return CUPS_BACKEND_FAILED;
/* Send "unknown 2" command */
cmd.cmd[0] = 0x1b;
cmd.cmd[1] = 0x4b;
@ -415,7 +440,7 @@ top:
if ((ret = send_data(ctx->dev, ctx->endp_down,
(uint8_t*) &cmd, sizeof(cmd))))
return CUPS_BACKEND_FAILED;
ret = read_data(ctx->dev, ctx->endp_up,
rdbuf, READBACK_LEN, &num);
if (ret < 0)
@ -426,7 +451,7 @@ top:
QUERY_STATUS();
/* Now it's time for the actual print job! */
if (ctx->type == P_MITSU_9550S) {
cmd.cmd[0] = 0x1b;
cmd.cmd[1] = 0x44;
@ -595,7 +620,7 @@ top:
ret = mitsu9550_get_status(ctx, rdbuf, 0, 1, 0); // status2
if (ret < 0)
return CUPS_BACKEND_FAILED;
ret = mitsu9550_get_status(ctx, rdbuf, 1, 0, 0); // status
if (ret < 0)
return CUPS_BACKEND_FAILED;
@ -617,33 +642,12 @@ top:
sleep(1);
}
INFO("Print complete\n");
return CUPS_BACKEND_OK;
}
static char *mitsu9550_media_types(uint8_t type)
{
switch (type) {
case 0x01:
return "3.5x5";
case 0x02:
return "4x6";
case 0x03:
return "PC";
case 0x04:
return "5x7";
case 0x05:
return "6x9";
case 0x06:
return "V";
default:
return "Unknown";
}
return NULL;
}
static void mitsu9550_dump_media(struct mitsu9550_media *resp)
{
INFO("Media type : %02x (%s)\n",
@ -660,7 +664,6 @@ static void mitsu9550_dump_status(struct mitsu9550_status *resp)
be16_to_cpu(resp->copies));
INFO("Other status : %02x %02x %02x %02x %02x\n",
resp->sts3, resp->sts4, resp->sts5, resp->sts6, resp->sts7);
}
static int mitsu9550_query_media(struct mitsu9550_ctx *ctx)

View File

@ -182,7 +182,7 @@ struct s2145_print_cmd {
#define PRINT_MEDIA_6x8 0x06
#define PRINT_MEDIA_2x6 0x07
static char *print_medias (uint8_t v) {
static char *print_sizes (uint8_t v) {
switch (v) {
case PRINT_MEDIA_4x6:
return "4x6";
@ -909,7 +909,7 @@ static int get_fwinfo(struct shinkos2145_ctx *ctx)
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_fwinfo_resp) - sizeof(struct s2145_status_hdr)))
continue;
INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i),
resp->major, resp->minor);
#if 0
@ -940,7 +940,7 @@ static int get_errorlog(struct shinkos2145_ctx *ctx)
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_errorlog_resp) - sizeof(struct s2145_status_hdr)))
return -2;
@ -948,13 +948,13 @@ static int get_errorlog(struct shinkos2145_ctx *ctx)
for (i = 0 ; i < resp->count ; i++) {
INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i,
le32_to_cpu(resp->items[i].print_counter),
resp->items[i].major, resp->items[i].minor,
resp->items[i].major, resp->items[i].minor,
error_codes(resp->items[i].major, resp->items[i].minor));
}
return 0;
}
static int get_mediainfo(struct shinkos2145_ctx *ctx)
static int get_mediainfo(struct shinkos2145_ctx *ctx)
{
struct s2145_cmd_hdr cmd;
struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf;
@ -971,23 +971,23 @@ static int get_mediainfo(struct shinkos2145_ctx *ctx)
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_mediainfo_resp) - sizeof(struct s2145_status_hdr)))
return -2;
INFO("Supported Media Information: %d entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
INFO(" %02d: C 0x%02x (%s), %04dx%04d, M 0x%02x (%s), P 0x%02x (%s)\n", i,
resp->items[i].code, print_medias(resp->items[i].code),
resp->items[i].code, print_sizes(resp->items[i].code),
le16_to_cpu(resp->items[i].columns),
le16_to_cpu(resp->items[i].rows),
le16_to_cpu(resp->items[i].rows),
resp->items[i].media_type, media_types(resp->items[i].media_type),
resp->items[i].print_type, print_methods(resp->items[i].print_type));
}
return 0;
}
static int get_user_string(struct shinkos2145_ctx *ctx)
static int get_user_string(struct shinkos2145_ctx *ctx)
{
struct s2145_cmd_hdr cmd;
struct s2145_getunique_resp *resp = (struct s2145_getunique_resp*) rdbuf;
@ -1540,8 +1540,8 @@ static int shinkos2145_main_loop(void *vctx, int copies) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
ATTR("marker-names='Color'\n");
ATTR("marker-types=ribbonWax\n");
// XXX check copies against remaining media!

View File

@ -275,15 +275,17 @@ struct shinkos6145_ctx {
uint8_t *databuf;
size_t datalen;
uint8_t ribbon_type;
uint16_t last_donor;
uint16_t last_remain;
uint8_t *eeprom;
size_t eepromlen;
void *dl_handle;
ImageProcessingFN ImageProcessing;
ImageAvrCalcFN ImageAvrCalc;
ImageAvrCalcFN ImageAvrCalc;
struct shinkos6145_correctionparam *corrdata;
size_t corrdatalen;
@ -869,13 +871,13 @@ struct s6145_status_resp {
uint32_t count_head;
uint32_t count_ribbon_left;
uint32_t reserved;
uint8_t bank1_printid;
uint16_t bank1_remaining;
uint16_t bank1_finished;
uint16_t bank1_specified;
uint8_t bank1_status;
uint8_t bank2_printid;
uint16_t bank2_remaining;
uint16_t bank2_finished;
@ -884,7 +886,7 @@ struct s6145_status_resp {
uint8_t reserved2[16];
uint8_t tonecurve_status;
uint8_t reserved3[6];
uint8_t reserved3[6];
} __attribute__((packed));
#define BANK_STATUS_FREE 0x00
@ -953,7 +955,7 @@ struct s6145_mediainfo_item {
#define MEDIA_2x6 0x07
#define MEDIA_6x6 0x08
static char *print_medias (uint8_t v) {
static char *print_sizes (uint8_t v) {
switch (v) {
case MEDIA_4x6:
return "4x6";
@ -981,7 +983,24 @@ static char *print_medias (uint8_t v) {
#define RIBBON_6x8 0x04
#define RIBBON_6x9 0x05
static char *print_ribbons (uint8_t v) {
static int ribbon_sizes (uint8_t v) {
switch (v) {
case RIBBON_4x6:
return 300;
case RIBBON_3_5x5:
return 340;
case RIBBON_5x7:
return 170;
case RIBBON_6x8:
return 150;
case RIBBON_6x9:
return 130; // XXX guessed
default:
return 300; // don't want 0.
}
}
static const char *print_ribbons (uint8_t v) {
switch (v) {
case RIBBON_NONE:
return "None";
@ -1330,7 +1349,7 @@ static int get_mediainfo(struct shinkos6145_ctx *ctx)
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6145_mediainfo_resp) - sizeof(struct s6145_status_hdr)))
return -2;
@ -1338,9 +1357,9 @@ static int get_mediainfo(struct shinkos6145_ctx *ctx)
INFO("Supported Print Sizes: %d entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
INFO(" %02d: C 0x%02x (%s), %04dx%04d, P 0x%02x (%s)\n", i,
resp->items[i].media_code, print_medias(resp->items[i].media_code),
resp->items[i].media_code, print_sizes(resp->items[i].media_code),
le16_to_cpu(resp->items[i].columns),
le16_to_cpu(resp->items[i].rows),
le16_to_cpu(resp->items[i].rows),
resp->items[i].print_method, print_methods(resp->items[i].print_method));
}
return 0;
@ -2055,7 +2074,7 @@ static int shinkos6145_read_parse(void *vctx, int data_fd) {
return CUPS_BACKEND_CANCEL;
}
if (ctx->databuf) {
free(ctx->databuf);
ctx->databuf = NULL;
@ -2131,7 +2150,7 @@ static int shinkos6145_main_loop(void *vctx, int copies) {
ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
return CUPS_BACKEND_FAILED;
}
if (le16_to_cpu(media->hdr.payload_len) != (sizeof(struct s6145_mediainfo_resp) - sizeof(struct s6145_status_hdr)))
return CUPS_BACKEND_FAILED;
@ -2153,9 +2172,10 @@ static int shinkos6145_main_loop(void *vctx, int copies) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names=Ribbon\n");
ATTR("marker-types=ink-ribbon\n");
ATTR("marker-names='%s'\n", print_ribbons(media->ribbon));
ATTR("marker-types=ribbonWax\n");
ctx->ribbon_type = media->ribbon;
// XXX check copies against remaining media?
/* Query printer mode */
@ -2164,7 +2184,7 @@ static int shinkos6145_main_loop(void *vctx, int copies) {
ERROR("Failed to execute command\n");
return ret;
}
top:
if (state != last_state) {
if (dyesub_debug)
@ -2186,14 +2206,14 @@ top:
if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
uint16_t donor, remain;
memcpy(rdbuf2, rdbuf, READBACK_LEN);
INFO("Printer Status: 0x%02x (%s)\n",
sts->hdr.status, status_str(sts->hdr.status));
/* Guessimate a percentage for the remaining media */
donor = le32_to_cpu(sts->count_ribbon_left) * 100 / (le32_to_cpu(sts->count_ribbon_left)+le32_to_cpu(sts->count_paper));
donor = le32_to_cpu(sts->count_ribbon_left) * 100 / ribbon_sizes(ctx->ribbon_type);
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%d\n", donor);
@ -2207,14 +2227,14 @@ top:
if (sts->hdr.result != RESULT_SUCCESS)
goto printer_error;
if (sts->hdr.status == ERROR_PRINTER)
goto printer_error;
goto printer_error;
} else if (state == last_state) {
sleep(1);
goto top;
}
last_state = state;
fflush(stderr);
fflush(stderr);
switch (state) {
case S_IDLE:

View File

@ -106,6 +106,7 @@ struct shinkos6245_ctx {
uint16_t last_donor;
uint16_t last_remain;
uint8_t ribbon_code;
};
/* Structs for printer */
@ -520,7 +521,7 @@ static char *error_codes(uint8_t major, uint8_t minor)
return "Paper Jam: Precut Print Position Off";
case 0x20:
return "Paper Jam: Precut Print Position On";
case 0x29:
return "Paper Jam: Printing Paper Top On";
case 0x2A:
@ -703,13 +704,13 @@ struct s6245_status_resp {
uint32_t count_head;
uint32_t count_ribbon_left;
uint32_t reserved;
uint8_t bank1_printid;
uint16_t bank1_remaining;
uint16_t bank1_finished;
uint16_t bank1_specified;
uint8_t bank1_status;
uint8_t bank2_printid;
uint16_t bank2_remaining;
uint16_t bank2_finished;
@ -718,7 +719,7 @@ struct s6245_status_resp {
uint8_t reserved2[16];
uint8_t tonecurve_status;
uint8_t reserved3[6];
uint8_t reserved3[6];
} __attribute__((packed));
#define BANK_STATUS_FREE 0x00
@ -790,7 +791,7 @@ struct s6245_mediainfo_item {
#define MEDIA_8x6_2 0x32
#define MEDIA_8x4_3 0x40
static char *print_medias (uint8_t v) {
static const char *print_sizes (uint8_t v) {
switch (v) {
case MEDIA_8x10:
return "8x10";
@ -819,10 +820,36 @@ static char *print_medias (uint8_t v) {
struct s6245_mediainfo_resp {
struct s6245_status_hdr hdr;
uint8_t count;
uint8_t ribbon_code;
uint8_t reserved;
uint8_t count;
struct s6245_mediainfo_item items[10]; /* Not all necessarily used */
} __attribute__((packed));
static const char *ribbon_sizes (uint8_t v) {
switch (v) {
case 0x00:
return "None";
case 0x11:
return "8x10";
case 0x12:
return "8x12";
default:
return "Unknown";
}
}
static int ribbon_counts (uint8_t v) {
switch (v) {
case 0x11:
return 120;
case 0x12:
return 100;
default:
return 120;
}
}
struct s6245_errorlog_resp {
struct s6245_status_hdr hdr;
uint16_t error_count;
@ -1113,14 +1140,15 @@ static int get_mediainfo(struct shinkos6245_ctx *ctx)
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_mediainfo_resp) - sizeof(struct s6245_status_hdr)))
return -2;
INFO("Loaded Media Type: %s\n", ribbon_sizes(resp->ribbon_code));
INFO("Supported Media Information: %d entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
INFO(" %02d: C 0x%02x (%s), %04dx%04d, P 0x%02x (%s)\n", i,
resp->items[i].media_code, print_medias(resp->items[i].media_code),
resp->items[i].media_code, print_sizes(resp->items[i].media_code),
le16_to_cpu(resp->items[i].columns),
le16_to_cpu(resp->items[i].rows),
resp->items[i].print_method, print_methods(resp->items[i].print_method));
@ -1473,10 +1501,10 @@ static void shinkos6245_attach(void *vctx, struct libusb_device_handle *dev,
ctx->dev = dev;
ctx->endp_up = endp_up;
ctx->endp_down = endp_down;
device = libusb_get_device(dev);
libusb_get_device_descriptor(device, &desc);
ctx->type = lookup_printer_type(&shinkos6245_backend,