From 5669fb3552157c60e9fdc4d7c4828cc4a2095bd2 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 27 Apr 2018 15:40:09 -0400 Subject: [PATCH] all: add new marker query support to backends and rejigger as needed. --- README | 8 + backend_canonselphy.c | 127 +++++++----- backend_canonselphyneo.c | 85 ++++++-- backend_dnpds40.c | 142 +++++++------ backend_kodak605.c | 130 ++++++------ backend_kodak6800.c | 57 ++++-- backend_magicard.c | 2 +- backend_mitsu70x.c | 112 ++++++----- backend_mitsu9550.c | 103 +++++----- backend_shinkos1245.c | 64 +++--- backend_shinkos2145.c | 201 ++++++++++--------- backend_shinkos6145.c | 183 +++++++++-------- backend_shinkos6245.c | 421 +++++++++++++++++++-------------------- 13 files changed, 912 insertions(+), 723 deletions(-) diff --git a/README b/README index df18de1..f2913c0 100644 --- a/README +++ b/README @@ -299,6 +299,8 @@ Notes: + This backend does not support reporting marker levels. + [1] Format of curvedata file: 256 entries each of Yellow, Magenta, Cyan mappings: @@ -598,6 +600,8 @@ This backend does not support additional commands. + This backend does not support reporting marker levels. + *************************************************************************** BACKEND=mitsu70x @@ -725,6 +729,8 @@ -s Query printer status + This backend does not support reporting marker levels. + *************************************************************************** BACKEND=dnpds40 @@ -807,4 +813,6 @@ Notes: -E Eject card in printer -R Reset printer + This backend does not support reporting marker levels. + *************************************************************************** diff --git a/backend_canonselphy.c b/backend_canonselphy.c index 24fc4b2..768f749 100644 --- a/backend_canonselphy.c +++ b/backend_canonselphy.c @@ -78,8 +78,6 @@ #define READBACK_LEN 12 -struct printer_data; /* Forward declaration */ - struct printer_data { int type; /* P_??? */ char *model; /* eg "SELPHY ES1" */ @@ -122,19 +120,16 @@ static char *generic_pgcode_names(uint8_t *rdbuf, struct printer_data *printer) static uint8_t es1_error_detect(uint8_t *rdbuf) { if (rdbuf[1] == 0x01) { - if (rdbuf[9] == 0x00) { + if (rdbuf[9] == 0x00) ERROR("Cover open!\n"); - } else { + else ERROR("Unknown error %02x\n", rdbuf[9]); - } 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; } @@ -154,13 +149,11 @@ static uint8_t 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; } @@ -171,19 +164,16 @@ static uint8_t es2_error_detect(uint8_t *rdbuf) static uint8_t es3_error_detect(uint8_t *rdbuf) { if (rdbuf[8] == 0x01) { - if (rdbuf[10] == 0x0f) { + if (rdbuf[10] == 0x0f) ERROR("Communications Error\n"); - } else if (rdbuf[10] == 0x01) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[10] == 0x01) ERROR("No media loaded!\n"); - } else { + else ERROR("Unknown error - %02x + %02x\n", rdbuf[8], rdbuf[10]); - } 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 && @@ -213,13 +203,11 @@ static uint8_t es40_error_detect(uint8_t *rdbuf) if (rdbuf[3] == 0x01) ERROR("Generic communication error\n"); - else if (rdbuf[3] == 0x32) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[3] == 0x32) ERROR("Cover open or media empty!\n"); - } else + else ERROR("Unknown error - %02x\n", rdbuf[3]); - return 1; } @@ -233,18 +221,15 @@ static uint8_t 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 - ATTR("marker-levels=%d\n", 0); + if ((rdbuf[3] & 0xf) == 0x02) // 0x12 0x22 ERROR("No paper tray loaded!\n"); - } else if ((rdbuf[3] & 0xf) == 0x03) { // 0x13 0x23 - ATTR("marker-levels=%d\n", 0); + else if ((rdbuf[3] & 0xf) == 0x03) // 0x13 0x23 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) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[3] == 0x21) ERROR("Ribbon depleted!\n"); - } else + else ERROR("Unknown error - %02x\n", rdbuf[3]); return 1; } @@ -265,16 +250,13 @@ static uint8_t cp10_error_detect(uint8_t *rdbuf) if (!rdbuf[2]) return 0; - if (rdbuf[2] == 0x80) { - ATTR("marker-levels=%d\n", 0); + if (rdbuf[2] == 0x80) ERROR("No ribbon loaded\n"); - } else if (rdbuf[2] == 0x08) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[2] == 0x08) ERROR("Ribbon depleted!\n"); - } else if (rdbuf[2] == 0x01) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[2] == 0x01) ERROR("No paper loaded!\n"); - } else + else ERROR("Unknown error - %02x\n", rdbuf[2]); return 1; } @@ -284,15 +266,13 @@ static uint8_t cpxxx_error_detect(uint8_t *rdbuf) if (!rdbuf[2]) return 0; - if (rdbuf[2] == 0x01) { - ATTR("marker-levels=%d\n", 0); + if (rdbuf[2] == 0x01) ERROR("Paper feed problem!\n"); - } else if (rdbuf[2] == 0x04) + else if (rdbuf[2] == 0x04) ERROR("Ribbon problem!\n"); - else if (rdbuf[2] == 0x08) { - ATTR("marker-levels=%d\n", 0); + else if (rdbuf[2] == 0x08) ERROR("Ribbon depleted!\n"); - } else + else ERROR("Unknown error - %02x\n", rdbuf[2]); return 1; } @@ -563,6 +543,7 @@ struct canonselphy_ctx { int type; struct printer_data *printer; + struct marker marker; uint8_t bw_mode; @@ -648,7 +629,8 @@ static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev, struct canonselphy_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; - int i; + int i, num; + uint8_t rdbuf[READBACK_LEN]; UNUSED(jobid); @@ -675,7 +657,27 @@ static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev, return CUPS_BACKEND_FAILED; } - /* TODO: Query & Update Marker */ + /* Read printer status. Twice. */ + i = read_data(ctx->dev, ctx->endp_up, + rdbuf, READBACK_LEN, &num); + if (i < 0) + return CUPS_BACKEND_FAILED; + + i = read_data(ctx->dev, ctx->endp_up, + rdbuf, READBACK_LEN, &num); + if (i < 0) + return CUPS_BACKEND_FAILED; + + /* Fill out marker structure */ + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf, ctx->printer) : "Unknown"; + ctx->marker.levelmax = -1; /* Unknown */ + + if (ctx->printer->error_detect(rdbuf)) + ctx->marker.levelnow = 0; /* Out of media */ + else + ctx->marker.levelnow = -3; /* Unknown but OK */ + return CUPS_BACKEND_OK; } @@ -866,14 +868,6 @@ 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) : "Unknown"); - ATTR("marker-types=ribbonWax\n"); - ATTR("marker-levels=%d\n", -3); /* ie Unknown but OK */ - top: if (state != last_state) { @@ -894,6 +888,7 @@ top: /* Error detection */ if (ctx->printer->error_detect(rdbuf)) { + dump_markers(&ctx->marker, 1, 0); if (ctx->printer->clear_error_len) /* Try to clear error state */ if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->printer->clear_error, ctx->printer->clear_error_len))) @@ -1104,6 +1099,35 @@ static void canonselphy_cmdline(void) DEBUG("\t\t[ -s ] # Query printer status\n"); } +static int canonselphy_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct canonselphy_ctx *ctx = vctx; + uint8_t rdbuf[READBACK_LEN]; + int ret, num; + + /* Read in the printer status, twice. */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) rdbuf, READBACK_LEN, &num); + if (ret < 0) + return CUPS_BACKEND_FAILED; + + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) rdbuf, READBACK_LEN, &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; + + if (ctx->printer->error_detect(rdbuf)) + ctx->marker.levelnow = 0; + else + ctx->marker.levelnow = -3; + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + static const char *canonselphy_prefixes[] = { "canonselphy", "selphycp10", "selphycp100", "selphycp200", "selphycp220", @@ -1119,7 +1143,7 @@ static const char *canonselphy_prefixes[] = { struct dyesub_backend canonselphy_backend = { .name = "Canon SELPHY CP/ES (legacy)", - .version = "0.99", + .version = "0.100", .uri_prefixes = canonselphy_prefixes, .cmdline_usage = canonselphy_cmdline, .cmdline_arg = canonselphy_cmdline_arg, @@ -1128,6 +1152,7 @@ struct dyesub_backend canonselphy_backend = { .teardown = canonselphy_teardown, .read_parse = canonselphy_read_parse, .main_loop = canonselphy_main_loop, + .query_markers = canonselphy_query_markers, .devices = { { USB_VID_CANON, USB_PID_CANON_CP10, P_CP10, NULL, "selphycp10"}, { USB_VID_CANON, USB_PID_CANON_CP100, P_CP_XXX, NULL, "selphycp100"}, diff --git a/backend_canonselphyneo.c b/backend_canonselphyneo.c index 9152e0b..431919a 100644 --- a/backend_canonselphyneo.c +++ b/backend_canonselphyneo.c @@ -69,6 +69,8 @@ struct selphyneo_ctx { uint8_t *databuf; uint32_t datalen; + + struct marker marker; }; static char *selphyneo_statuses(uint8_t sts) @@ -195,6 +197,8 @@ static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev, struct selphyneo_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct selphyneo_readback rdback; + int ret, num; UNUSED(jobid); @@ -205,7 +209,24 @@ static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev, device = libusb_get_device(dev); libusb_get_device_descriptor(device, &desc); - // TODO: Query & Update Marker + /* Read in the printer status to clear last state */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) &rdback, sizeof(rdback), &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; + + /* And again, for the markers */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) &rdback, sizeof(rdback), &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = selphynew_pgcodes(rdback.data[6]); + ctx->marker.levelmax = -1; + ctx->marker.levelnow = -3; return CUPS_BACKEND_OK; } @@ -292,20 +313,6 @@ static int selphyneo_main_loop(void *vctx, int copies) { if (ret < 0) return CUPS_BACKEND_FAILED; - /* And again, for the markers */ - ret = read_data(ctx->dev, ctx->endp_up, - (uint8_t*) &rdback, sizeof(rdback), &num); - - 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", selphynew_pgcodes(rdback.data[6])); - - ATTR("marker-types=ribbonWax\n"); - top: INFO("Waiting for printer idle\n"); @@ -326,18 +333,20 @@ top: break; case 0x0A: ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]); - ATTR("marker-levels=%d\n", 0); + ctx->marker.levelnow = 0; + dump_markers(&ctx->marker, 1, 0); return CUPS_BACKEND_CANCEL; default: ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]); - ATTR("marker-levels=%d\n", 0); + ctx->marker.levelnow = 0; + dump_markers(&ctx->marker, 1, 0); return CUPS_BACKEND_STOP; } sleep(1); } while(1); - ATTR("marker-levels=%d\n", -3); /* ie Unknown but OK */ + dump_markers(&ctx->marker, 1, 0); INFO("Sending spool data\n"); /* Send the data over in 256K chunks */ @@ -380,11 +389,13 @@ top: break; case 0x0A: ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]); - ATTR("marker-levels=%d\n", 0); + ctx->marker.levelnow = 0; + dump_markers(&ctx->marker, 1, 0); return CUPS_BACKEND_CANCEL; default: ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]); - ATTR("marker-levels=%d\n", 0); + ctx->marker.levelnow = 0; + dump_markers(&ctx->marker, 1, 0); return CUPS_BACKEND_STOP; } @@ -440,6 +451,37 @@ static void selphyneo_cmdline(void) DEBUG("\t\t[ -s ] # Query printer status\n"); } +static int selphyneo_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct selphyneo_ctx *ctx = vctx; + struct selphyneo_readback rdback; + int ret, num; + + /* Read in the printer status to clear last state */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) &rdback, sizeof(rdback), &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; + + /* And again, for the markers */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) &rdback, sizeof(rdback), &num); + + if (ret < 0) + return CUPS_BACKEND_FAILED; + + if (rdback.data[2]) + ctx->marker.levelnow = 0; + else + ctx->marker.levelnow = -3; + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + static const char *canonselphyneo_prefixes[] = { "canonselphyneo", "selphycp820", "selphycp910", "selphycp1000", "selphycp1200", "selphycp1300", @@ -448,7 +490,7 @@ static const char *canonselphyneo_prefixes[] = { struct dyesub_backend canonselphyneo_backend = { .name = "Canon SELPHY CP (new)", - .version = "0.15", + .version = "0.16", .uri_prefixes = canonselphyneo_prefixes, .cmdline_usage = selphyneo_cmdline, .cmdline_arg = selphyneo_cmdline_arg, @@ -457,6 +499,7 @@ struct dyesub_backend canonselphyneo_backend = { .teardown = selphyneo_teardown, .read_parse = selphyneo_read_parse, .main_loop = selphyneo_main_loop, + .query_markers = selphyneo_query_markers, .devices = { { USB_VID_CANON, USB_PID_CANON_CP820, P_CP910, NULL, "selphycp820"}, { USB_VID_CANON, USB_PID_CANON_CP910, P_CP910, NULL, "selphycp910"}, diff --git a/backend_dnpds40.c b/backend_dnpds40.c index 3d8ff90..f0707b6 100644 --- a/backend_dnpds40.c +++ b/backend_dnpds40.c @@ -91,6 +91,8 @@ struct dnpds40_ctx { int correct_count; int needs_mlot; + struct marker marker; + uint32_t native_width; int supports_6x9; int supports_2x6; @@ -548,6 +550,35 @@ static void *dnpds40_init(void) ((ctx->ver_major > (__major)) || \ (ctx->ver_major == (__major) && ctx->ver_minor >= (__minor))) +static int dnpds40_query_mqty(struct dnpds40_ctx *ctx) +{ + struct dnpds40_cmd cmd; + uint8_t *resp; + int len = 0, count; + + /* Get Media remaining */ + dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0); + + resp = dnpds40_resp_cmd(ctx, &cmd, &len); + if (!resp) + return -1; + + dnpds40_cleanup_string((char*)resp, len); + + count = atoi((char*)resp+4); + free(resp); + + if (count) { + /* Old-sk00l models report one less than they should */ + if (!ctx->correct_count) + count++; + + count -= ctx->mediaoffset; + } + + return count; +} + static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, uint8_t jobid) { @@ -588,6 +619,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ptr = strtok(NULL, "."); ctx->ver_minor = atoi(ptr); free(resp); + } else { + return CUPS_BACKEND_FAILED; } /* Get Serial Number */ @@ -598,6 +631,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, dnpds40_cleanup_string((char*)resp, len); ctx->serno = (char*) resp; /* Do NOT free resp! */ + } else { + return CUPS_BACKEND_FAILED; } /* Query Media Info */ @@ -619,6 +654,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media--; free(resp); + } else { + return CUPS_BACKEND_FAILED; } } @@ -667,6 +704,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->duplex_media -= (ctx->duplex_media & 3); free(resp); + } else { + return CUPS_BACKEND_FAILED; } } @@ -809,6 +848,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, if (resp) { ctx->mediaoffset = atoi((char*)resp+4); free(resp); + } else { + return CUPS_BACKEND_FAILED; } } else if (!ctx->correct_count) { ctx->mediaoffset = 50; @@ -827,6 +868,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = atoi((char*)resp+4); free(resp); ctx->media_count_new -= ctx->mediaoffset; + } else { + return CUPS_BACKEND_FAILED; } } else { /* Look it up for legacy models & FW */ @@ -849,7 +892,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = 180; break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } break; @@ -865,7 +908,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = 350; break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } break; @@ -884,7 +927,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = 280; break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } break; @@ -900,7 +943,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = 280; break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } break; @@ -914,18 +957,25 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev, ctx->media_count_new = 110; break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } break; default: - ctx->media_count_new = 999; // non-zero + ctx->media_count_new = 0; break; } } - // TODO: fail out on other errors - // TODO: Update Marker + /* Fill out marker structure */ + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = dnpds40_media_types(ctx->media); + ctx->marker.levelmax = ctx->media_count_new; + ctx->marker.levelnow = dnpds40_query_mqty(ctx); + + if (ctx->marker.levelnow < 0) + return CUPS_BACKEND_FAILED; + return CUPS_BACKEND_OK; } @@ -1484,14 +1534,6 @@ static int dnpds40_main_loop(void *vctx, int copies) { if (!!ctx->matte != ctx->last_matte) buf_needed = 2; - if (ctx->media_count_new) { - ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n"); - ATTR("marker-high-levels=100\n"); - ATTR("marker-low-levels=10\n"); - ATTR("marker-names='%s'\n", dnpds40_media_types(ctx->media)); - ATTR("marker-types=ribbonWax\n"); - } - /* RX1HS requires HS media, but the only way to tell is that the HS media reports a lot code, while the non-HS media does not. */ if (ctx->needs_mlot) { @@ -1579,29 +1621,12 @@ top: { /* Figure out remaining native prints */ - dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0); - - resp = dnpds40_resp_cmd(ctx, &cmd, &len); - if (!resp) + ctx->marker.levelnow = dnpds40_query_mqty(ctx); + if (ctx->marker.levelnow < 0) return CUPS_BACKEND_FAILED; + dump_markers(&ctx->marker, 1, 0); - dnpds40_cleanup_string((char*)resp, len); - - count = atoi((char*)resp+4); - free(resp); - - if (count) { - /* Old-sk00l models report one less than they should */ - if (!ctx->correct_count) - count++; - - count -= ctx->mediaoffset; - } - - if (ctx->media_count_new) { - ATTR("marker-levels=%d\n", count * 100 / ctx->media_count_new); - ATTR("marker-message=\"%d native prints remaining on '%s' ribbon\"\n", count, dnpds40_media_types(ctx->media)); - } + count = ctx->marker.levelnow; // For logic below. /* See if we can rewind to save media */ if (ctx->can_rewind && ctx->supports_rewind) { @@ -1648,7 +1673,6 @@ top: return CUPS_BACKEND_STOP; } #endif - if (count < copies) { WARNING("Printer does not have sufficient remaining media (%d) to complete job (%d)\n", copies, count); } @@ -1771,11 +1795,8 @@ top: count -= ctx->mediaoffset; } - - if (ctx->media_count_new) { - ATTR("marker-levels=%d\n", count * 100 / ctx->media_count_new); - ATTR("marker-message=\"%d native prints remaining on '%s' ribbon\"\n", count, dnpds40_media_types(ctx->media)); - } + ctx->marker.levelnow = count; + dump_markers(&ctx->marker, 1, 0); } /* Clean up */ @@ -2306,24 +2327,10 @@ static int dnpds40_get_status(struct dnpds40_ctx *ctx) INFO("Native Prints Available on New Media: %u\n", ctx->media_count_new); /* Get Media remaining */ - dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0); - - resp = dnpds40_resp_cmd(ctx, &cmd, &len); - if (!resp) + count = dnpds40_query_mqty(ctx); + if (count < 0) return CUPS_BACKEND_FAILED; - dnpds40_cleanup_string((char*)resp, len); - - count = atoi((char*)resp+4); - free(resp); - - if (count) { - /* Old-sk00l models report one less than they should */ - if (!ctx->correct_count) - count++; - - count -= ctx->mediaoffset; - } INFO("Native Prints Remaining on Media: %d\n", count); if (ctx->supports_rewind) { @@ -2699,6 +2706,20 @@ static int dnpds40_cmdline_arg(void *vctx, int argc, char **argv) return 0; } +static int dnpds40_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct dnpds40_ctx *ctx = vctx; + + *markers = &ctx->marker; + *count = 1; + + ctx->marker.levelnow = dnpds40_query_mqty(ctx); + if (ctx->marker.levelnow < 0) + return CUPS_BACKEND_FAILED; + + return CUPS_BACKEND_OK; +} + static const char *dnpds40_prefixes[] = { "dnp_citizen", "dnpds40", "dnpds80", "dnpds80dx", "dnpds620", "dnpds820", "dnprx1", @@ -2724,7 +2745,7 @@ static const char *dnpds40_prefixes[] = { /* Exported */ struct dyesub_backend dnpds40_backend = { .name = "DNP DS-series / Citizen C-series", - .version = "0.100", + .version = "0.101", .uri_prefixes = dnpds40_prefixes, .cmdline_usage = dnpds40_cmdline, .cmdline_arg = dnpds40_cmdline_arg, @@ -2734,6 +2755,7 @@ struct dyesub_backend dnpds40_backend = { .read_parse = dnpds40_read_parse, .main_loop = dnpds40_main_loop, .query_serno = dnpds40_query_serno, + .query_markers = dnpds40_query_markers, .devices = { { USB_VID_CITIZEN, USB_PID_DNP_DS40, P_DNP_DS40, NULL, "dnpds40"}, // Also Citizen CX { USB_VID_CITIZEN, USB_PID_DNP_DS80, P_DNP_DS80, NULL, "dnpds80"}, // Also Citizen CX-W and Mitsubishi CP-3800DW diff --git a/backend_kodak605.c b/backend_kodak605.c index 1afe93d..84f53c1 100644 --- a/backend_kodak605.c +++ b/backend_kodak605.c @@ -178,10 +178,10 @@ struct kodak605_ctx { struct kodak605_media_list *media; + struct marker marker; + uint8_t *databuf; int datalen; - - uint8_t last_donor; }; static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media) @@ -218,6 +218,40 @@ static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_li return 0; } +static int kodak605_get_status(struct kodak605_ctx *ctx, struct kodak605_status *sts) +{ + uint8_t cmdbuf[4]; + + int ret, num = 0; + + /* Send Status Query */ + cmdbuf[0] = 0x01; + cmdbuf[1] = 0x00; + cmdbuf[2] = 0x00; + cmdbuf[3] = 0x00; + if ((ret = send_data(ctx->dev, ctx->endp_down, + cmdbuf, sizeof(cmdbuf)))) + return ret; + + /* Read in the printer status */ + ret = read_data(ctx->dev, ctx->endp_up, + (uint8_t*) sts, sizeof(*sts), &num); + if (ret < 0) + return ret; + + if (num < (int)sizeof(*sts)) { + ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*sts)); + return CUPS_BACKEND_FAILED; + } + + if (sts->hdr.result != RESULT_SUCCESS) { + ERROR("Unexpected response from status query (%x)!\n", sts->hdr.result); + return CUPS_BACKEND_FAILED; + } + + return 0; +} + static void *kodak605_init(void) { struct kodak605_ctx *ctx = malloc(sizeof(struct kodak605_ctx)); @@ -240,6 +274,7 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, struct kodak605_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct kodak605_status sts; ctx->dev = dev; ctx->endp_up = endp_up; @@ -256,16 +291,23 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, if (!ctx->jobid) ctx->jobid++; - /* Init */ - ctx->last_donor = 255; - /* Query media info */ if (kodak605_get_media(ctx, ctx->media)) { ERROR("Can't query media\n"); return CUPS_BACKEND_FAILED; } - // TODO: Update Marker + /* Update status */ + if (kodak605_get_status(ctx, &sts)) { + ERROR("Can't query status\n"); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = kodak68xx_mediatypes(ctx->media->type); + ctx->marker.levelmax = 100; /* Ie percentage */ + ctx->marker.levelnow = sts.donor; + return CUPS_BACKEND_OK; } @@ -337,40 +379,6 @@ static int kodak605_read_parse(void *vctx, int data_fd) { return CUPS_BACKEND_OK; } -static int kodak605_get_status(struct kodak605_ctx *ctx, struct kodak605_status *sts) -{ - uint8_t cmdbuf[4]; - - int ret, num = 0; - - /* Send Status Query */ - cmdbuf[0] = 0x01; - cmdbuf[1] = 0x00; - cmdbuf[2] = 0x00; - cmdbuf[3] = 0x00; - if ((ret = send_data(ctx->dev, ctx->endp_down, - cmdbuf, sizeof(cmdbuf)))) - return ret; - - /* Read in the printer status */ - ret = read_data(ctx->dev, ctx->endp_up, - (uint8_t*) sts, sizeof(*sts), &num); - if (ret < 0) - return ret; - - if (num < (int)sizeof(*sts)) { - ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*sts)); - return CUPS_BACKEND_FAILED; - } - - if (sts->hdr.result != RESULT_SUCCESS) { - ERROR("Unexpected response from status query (%x)!\n", sts->hdr.result); - return CUPS_BACKEND_FAILED; - } - - return 0; -} - static int kodak605_main_loop(void *vctx, int copies) { struct kodak605_ctx *ctx = vctx; @@ -396,22 +404,15 @@ static int kodak605_main_loop(void *vctx, int copies) { return CUPS_BACKEND_HOLD; } - /* 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='%s'\n", kodak68xx_mediatypes(ctx->media->type)); - ATTR("marker-types=ribbonWax\n"); - INFO("Waiting for printer idle\n"); while(1) { if ((ret = kodak605_get_status(ctx, &sts))) return CUPS_BACKEND_FAILED; - if (ctx->last_donor != sts.donor) { - ctx->last_donor = sts.donor; - ATTR("marker-levels=%u\n", sts.donor); + if (ctx->marker.levelnow != sts.donor) { + ctx->marker.levelnow = sts.donor; + dump_markers(&ctx->marker, 1, 0); } // XXX check for errors @@ -470,13 +471,12 @@ static int kodak605_main_loop(void *vctx, int copies) { if ((kodak605_get_status(ctx, &sts)) != 0) return CUPS_BACKEND_FAILED; + if (ctx->marker.levelnow != sts.donor) { + ctx->marker.levelnow = sts.donor; + dump_markers(&ctx->marker, 1, 0); + } // XXX check for errors - if (ctx->last_donor != sts.donor) { - ctx->last_donor = sts.donor; - ATTR("marker-levels=%u\n", sts.donor); - } // XXX check for errors ? - /* Wait for completion */ if (sts.b1_id == ctx->jobid && sts.b1_complete == sts.b1_total) break; @@ -677,6 +677,23 @@ static int kodak605_cmdline_arg(void *vctx, int argc, char **argv) return 0; } +static int kodak605_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct kodak605_ctx *ctx = vctx; + struct kodak605_status sts; + + /* Query printer status */ + if (kodak605_get_status(ctx, &sts)) + return CUPS_BACKEND_FAILED; + + ctx->marker.levelnow = sts.donor; + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + static const char *kodak605_prefixes[] = { "kodak605", NULL, @@ -685,7 +702,7 @@ static const char *kodak605_prefixes[] = { /* Exported */ struct dyesub_backend kodak605_backend = { .name = "Kodak 605", - .version = "0.28", + .version = "0.29", .uri_prefixes = kodak605_prefixes, .cmdline_usage = kodak605_cmdline, .cmdline_arg = kodak605_cmdline_arg, @@ -694,6 +711,7 @@ struct dyesub_backend kodak605_backend = { .teardown = kodak605_teardown, .read_parse = kodak605_read_parse, .main_loop = kodak605_main_loop, + .query_markers = kodak605_query_markers, .devices = { { USB_VID_KODAK, USB_PID_KODAK_605, P_KODAK_605, "Kodak", "kodaka605"}, { 0, 0, 0, NULL, NULL} diff --git a/backend_kodak6800.c b/backend_kodak6800.c index a1c48a9..110cc30 100644 --- a/backend_kodak6800.c +++ b/backend_kodak6800.c @@ -239,7 +239,7 @@ struct kodak6800_ctx { uint8_t *databuf; int datalen; - uint8_t last_donor; + struct marker marker; }; static const char *kodak68xx_mediatypes(int type) @@ -278,8 +278,6 @@ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx, return 0; } - - static void kodak68x0_dump_mediainfo(struct kodak68x0_media_readback *media) { int i; @@ -1018,6 +1016,7 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev, struct kodak6800_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct kodak68x0_status_readback status; ctx->dev = dev; ctx->endp_up = endp_up; @@ -1034,16 +1033,21 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev, if (!ctx->jobid) ctx->jobid++; - /* Init */ - ctx->last_donor = 255; - /* Query media info */ if (kodak6800_get_mediainfo(ctx, ctx->media)) { ERROR("Can't query media\n"); return CUPS_BACKEND_FAILED; } - // TODO: Update Marker + /* Query printer status */ + if (kodak6800_get_status(ctx, &status)) + return CUPS_BACKEND_FAILED; + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = kodak68xx_mediatypes(ctx->media->type); + ctx->marker.levelmax = 100; /* Ie percentage */ + ctx->marker.levelnow = status.donor; + return CUPS_BACKEND_OK; } @@ -1143,22 +1147,15 @@ static int kodak6800_main_loop(void *vctx, int copies) { return CUPS_BACKEND_HOLD; } - /* 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='%s'\n", kodak68xx_mediatypes(ctx->media->type)); - ATTR("marker-types=ribbonWax\n"); - INFO("Waiting for printer idle\n"); while(1) { if (kodak6800_get_status(ctx, &status)) return CUPS_BACKEND_FAILED; - if (ctx->last_donor != status.donor) { - ctx->last_donor = status.donor; - ATTR("marker-levels=%u\n", status.donor); + if (ctx->marker.levelnow != status.donor) { + ctx->marker.levelnow = status.donor; + dump_markers(&ctx->marker, 1, 0); } if (status.status1 == STATE_STATUS1_ERROR) { @@ -1231,9 +1228,9 @@ static int kodak6800_main_loop(void *vctx, int copies) { if (kodak6800_get_status(ctx, &status)) return CUPS_BACKEND_FAILED; - if (ctx->last_donor != status.donor) { - ctx->last_donor = status.donor; - ATTR("marker-levels=%u\n", status.donor); + if (ctx->marker.levelnow != status.donor) { + ctx->marker.levelnow = status.donor; + dump_markers(&ctx->marker, 1, 0); } if (status.status1 == STATE_STATUS1_ERROR) { @@ -1261,6 +1258,23 @@ static int kodak6800_main_loop(void *vctx, int copies) { return CUPS_BACKEND_OK; } +static int kodak6800_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct kodak6800_ctx *ctx = vctx; + struct kodak68x0_status_readback status; + + /* Query printer status */ + if (kodak6800_get_status(ctx, &status)) + return CUPS_BACKEND_FAILED; + + ctx->marker.levelnow = status.donor; + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + static const char *kodak6800_prefixes[] = { "kodak68x0", "kodak6800", "kodak6850", @@ -1270,7 +1284,7 @@ static const char *kodak6800_prefixes[] = { /* Exported */ struct dyesub_backend kodak6800_backend = { .name = "Kodak 6800/6850", - .version = "0.60", + .version = "0.61", .uri_prefixes = kodak6800_prefixes, .cmdline_usage = kodak6800_cmdline, .cmdline_arg = kodak6800_cmdline_arg, @@ -1280,6 +1294,7 @@ struct dyesub_backend kodak6800_backend = { .read_parse = kodak6800_read_parse, .main_loop = kodak6800_main_loop, .query_serno = kodak6800_query_serno, + .query_markers = kodak6800_query_markers, .devices = { { USB_VID_KODAK, USB_PID_KODAK_6800, P_KODAK_6800, "Kodak", "kodak6800"}, { USB_VID_KODAK, USB_PID_KODAK_6850, P_KODAK_6850, "Kodak", "kodak6850"}, diff --git a/backend_magicard.c b/backend_magicard.c index 4cd97d8..e48260b 100644 --- a/backend_magicard.c +++ b/backend_magicard.c @@ -909,7 +909,7 @@ struct dyesub_backend magicard_backend = { .main_loop = magicard_main_loop, .devices = { { USB_VID_MAGICARD, USB_PID_MAGICARD_TANGO2E, P_MAGICARD, NULL, "tango2e"}, - { USB_VID_MAGICARD, USB_PID_MAGICARD_ENDURO, P_MAGICARD, NULL, "enduro"}, + { USB_VID_MAGICARD, USB_PID_MAGICARD_ENDURO, P_MAGICARD, NULL, "enduro"}, { USB_VID_MAGICARD, USB_PID_MAGICARD_ENDUROPLUS, P_MAGICARD, NULL, "enduroplus"}, { USB_VID_MAGICARD, 0xFFFF, P_MAGICARD, NULL, "magicard"}, { 0, 0, 0, NULL, "magicard"} diff --git a/backend_mitsu70x.c b/backend_mitsu70x.c index 9b59fa6..875ad53 100644 --- a/backend_mitsu70x.c +++ b/backend_mitsu70x.c @@ -136,14 +136,16 @@ struct mitsu70x_ctx { uint8_t *databuf; int datalen; + struct marker marker[2]; + uint32_t matte; uint16_t jobid; uint16_t rows; uint16_t cols; - uint16_t last_donor_l; - uint16_t last_donor_u; + uint16_t last_l; + uint16_t last_u; int num_decks; char *laminatefname; @@ -709,7 +711,7 @@ static int 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; + ctx->last_l = ctx->last_u = 65535; /* Attempt to open the library */ #if defined(WITH_DYNAMIC) @@ -788,7 +790,19 @@ static int mitsu70x_attach(void *vctx, struct libusb_device_handle *dev, else ctx->num_decks = 1; - // TODO: Update Marker + /* Set up markers */ + ctx->marker[0].color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker[0].name = mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type); + ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity); + ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain); + + if (ctx->num_decks == 2) { + ctx->marker[1].color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker[1].name = mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type); + ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity); + ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain); + } + return CUPS_BACKEND_OK; } @@ -1528,23 +1542,6 @@ top: if (ret) return CUPS_BACKEND_FAILED; - if (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"); - } - /* FW sanity checking */ if (ctx->type == P_KODAK_305) { /* Known versions: @@ -1685,37 +1682,23 @@ skip_status: INFO("Waiting for printer to acknowledge completion\n"); do { - uint16_t donor_u, donor_l; - sleep(1); 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); - + ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity); + ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain); if (ctx->num_decks == 2) { - 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); - ATTR("marker-message='\"%d native prints remaining on %s media\"','\"%d native prints remaining on %s media\"'\n", - be16_to_cpu(resp.lower.remain), - mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type), - be16_to_cpu(resp.upper.remain), - mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type)); - } - } else { - if (donor_l != ctx->last_donor_l) { - ctx->last_donor_l = donor_l; - ATTR("marker-levels=%d\n", donor_l); - ATTR("marker-message=\"%d native prints remaining on %s media\"\n", - be16_to_cpu(resp.lower.remain), - mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type)); - } + ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity); + ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain); + } + if (ctx->marker[0].levelnow != ctx->last_l || + ctx->marker[1].levelnow != ctx->last_u) { + dump_markers(ctx->marker, ctx->num_decks, 0); + ctx->last_l = ctx->marker[0].levelnow; + ctx->last_u = ctx->marker[1].levelnow; } /* Query job status for our used jobid */ @@ -1916,7 +1899,7 @@ static int mitsu70x_query_status(struct mitsu70x_ctx *ctx) ret = mitsu70x_get_printerstatus(ctx, &resp); if (!ret) mitsu70x_dump_printerstatus(ctx, &resp); - + return ret; } @@ -1998,6 +1981,40 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv) return 0; } +static int mitsu70x_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct mitsu70x_ctx *ctx = vctx; + struct mitsu70x_printerstatus_resp resp; + int ret; + + *markers = ctx->marker; + *count = ctx->num_decks; + + /* Tell CUPS about the consumables we report */ + ret = mitsu70x_get_printerstatus(ctx, &resp); + if (ret) + return CUPS_BACKEND_FAILED; + + if (resp.power) { + ret = mitsu70x_wakeup(ctx, 1); + if (ret) + return CUPS_BACKEND_FAILED; + + ret = mitsu70x_get_printerstatus(ctx, &resp); + if (ret) + return CUPS_BACKEND_FAILED; + } + + ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity); + ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain); + if (ctx->num_decks == 2) { + ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity); + ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain); + } + + return CUPS_BACKEND_OK; +} + static const char *mitsu70x_prefixes[] = { "mitsu70x", "mitsud80", "mitsuk60", "kodak305", "fujiask300", @@ -2007,7 +2024,7 @@ static const char *mitsu70x_prefixes[] = { /* Exported */ struct dyesub_backend mitsu70x_backend = { .name = "Mitsubishi CP-D70 family", - .version = "0.77", + .version = "0.78", .uri_prefixes = mitsu70x_prefixes, .cmdline_usage = mitsu70x_cmdline, .cmdline_arg = mitsu70x_cmdline_arg, @@ -2017,6 +2034,7 @@ struct dyesub_backend mitsu70x_backend = { .read_parse = mitsu70x_read_parse, .main_loop = mitsu70x_main_loop, .query_serno = mitsu70x_query_serno, + .query_markers = mitsu70x_query_markers, .devices = { { USB_VID_MITSU, USB_PID_MITSU_D70X, P_MITSU_D70X, NULL, "mitsu70x"}, { USB_VID_MITSU, USB_PID_MITSU_K60, P_MITSU_K60, NULL, "mitsuk60"}, diff --git a/backend_mitsu9550.c b/backend_mitsu9550.c index 6b4ed9d..0277793 100644 --- a/backend_mitsu9550.c +++ b/backend_mitsu9550.c @@ -173,9 +173,7 @@ struct mitsu9550_ctx { uint16_t cols; uint32_t plane_len; - uint16_t last_donor; - uint16_t last_remain; - int marker_reported; + struct marker marker; /* Parse headers separately */ struct mitsu9550_hdr1 hdr1; @@ -235,39 +233,22 @@ struct mitsu9550_status2 { struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf;\ /* struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf; */ \ struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf; \ - uint16_t donor, remain; \ + uint16_t donor; \ /* media */ \ ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); \ 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, ctx->is_s)); \ - ATTR("marker-types=ribbonWax\n"); \ + donor = be16_to_cpu(media->remain); \ + if (donor != ctx->marker.levelnow) { \ + ctx->marker.levelnow = donor; \ + dump_markers(&ctx->marker, 1, 0); \ } \ - \ /* Sanity-check media response */ \ if (media->remain == 0 || media->max == 0) { \ ERROR("Printer out of media!\n"); \ - ATTR("marker-levels=%d\n", 0); \ return CUPS_BACKEND_HOLD; \ } \ - remain = be16_to_cpu(media->remain); \ - donor = be16_to_cpu(media->max); \ - donor = remain/donor; \ - if (donor != ctx->last_donor) { \ - ctx->last_donor = donor; \ - ATTR("marker-levels=%u\n", donor); \ - } \ - if (remain != ctx->last_remain) { \ - ctx->last_remain = remain; \ - ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s)); \ - } \ if (validate_media(ctx->type, media->type, ctx->cols, ctx->rows)) { \ ERROR("Incorrect media (%u) type for printjob (%ux%u)!\n", media->type, ctx->cols, ctx->rows); \ return CUPS_BACKEND_HOLD; \ @@ -527,6 +508,8 @@ void CColorConv3D_DoColorConv(struct CColorConv3D *this, uint8_t *data, uint16_t } } /* ---- end 3D LUT ---- */ +static int mitsu9550_get_status(struct mitsu9550_ctx *ctx, uint8_t *resp, int status, int status2, int media); +static char *mitsu9550_media_types(uint8_t type, uint8_t is_s); static void *mitsu9550_init(void) { @@ -546,6 +529,7 @@ static int mitsu9550_attach(void *vctx, struct libusb_device_handle *dev, struct mitsu9550_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct mitsu9550_media media; UNUSED(jobid); @@ -568,9 +552,14 @@ static int mitsu9550_attach(void *vctx, struct libusb_device_handle *dev, ctx->type == P_MITSU_9810) ctx->is_98xx = 1; - ctx->last_donor = ctx->last_remain = 65535; + if (mitsu9550_get_status(ctx, (uint8_t*) &media, 0, 0, 1)) + return CUPS_BACKEND_FAILED; + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = mitsu9550_media_types(media.type, ctx->is_s); + ctx->marker.levelmax = be16_to_cpu(media.max); + ctx->marker.levelnow = be16_to_cpu(media.remain); - // TODO: Query & Update Marker return CUPS_BACKEND_OK; } @@ -836,7 +825,7 @@ hdr_done: } CColorConv3D_DoColorConv(lut, ctx->databuf + sizeof(struct mitsu9550_plane), ctx->cols, ctx->rows, ctx->cols * 3, COLORCONV_BGR); - CColorConv3D_Destroy3DColorTable(lut); + CColorConv3D_Destroy3DColorTable(lut); ctx->hdr2.unkc[9] = 0; } @@ -1313,29 +1302,22 @@ top: struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf; // struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf; struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf; - uint16_t donor, remain; + uint16_t donor; ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); // media if (ret < 0) return CUPS_BACKEND_FAILED; + donor = be16_to_cpu(media->remain); + if (donor != ctx->marker.levelnow) { + ctx->marker.levelnow = donor; + dump_markers(&ctx->marker, 1, 0); + } /* Sanity-check media response */ if (media->remain == 0 || media->max == 0) { ERROR("Printer out of media!\n"); - ATTR("marker-levels=%d\n", 0); return CUPS_BACKEND_HOLD; } - remain = be16_to_cpu(media->remain); - donor = be16_to_cpu(media->max); - donor = remain/donor; - if (donor != ctx->last_donor) { - ctx->last_donor = donor; - ATTR("marker-levels=%u\n", donor); - } - if (remain != ctx->last_remain) { - ctx->last_remain = remain; - ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s)); - } ret = mitsu9550_get_status(ctx, rdbuf, 0, 1, 0); // status2 if (ret < 0) return CUPS_BACKEND_FAILED; @@ -1417,29 +1399,22 @@ top: struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf; // struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf; struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf; - uint16_t donor, remain; + uint16_t donor; ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); // media if (ret < 0) return CUPS_BACKEND_FAILED; + donor = be16_to_cpu(media->remain); + if (donor != ctx->marker.levelnow) { + ctx->marker.levelnow = donor; + dump_markers(&ctx->marker, 1, 0); + } /* Sanity-check media response */ if (media->remain == 0 || media->max == 0) { ERROR("Printer out of media!\n"); - ATTR("marker-levels=%d\n", 0); return CUPS_BACKEND_HOLD; } - remain = be16_to_cpu(media->remain); - donor = be16_to_cpu(media->max); - donor = remain/donor; - if (donor != ctx->last_donor) { - ctx->last_donor = donor; - ATTR("marker-levels=%u\n", donor); - } - if (remain != ctx->last_remain) { - ctx->last_remain = remain; - ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s)); - } ret = mitsu9550_get_status(ctx, rdbuf, 0, 1, 0); // status2 if (ret < 0) return CUPS_BACKEND_FAILED; @@ -1641,6 +1616,23 @@ static int mitsu9550_cmdline_arg(void *vctx, int argc, char **argv) return 0; } +static int mitsu9550_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct mitsu9550_ctx *ctx = vctx; + struct mitsu9550_media media; + + /* Query printer status */ + if (mitsu9550_get_status(ctx, (uint8_t*) &media, 0, 0, 1)) + return CUPS_BACKEND_FAILED; + + ctx->marker.levelnow = be16_to_cpu(media.remain); + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + static const char *mitsu9550_prefixes[] = { "mitsu9xxx", "mitsu9000", "mitsu9500", "mitsu9550", "mitsi9600", "mitsu9800", "mitsu9810", @@ -1650,7 +1642,7 @@ static const char *mitsu9550_prefixes[] = { /* Exported */ struct dyesub_backend mitsu9550_backend = { .name = "Mitsubishi CP9xxx family", - .version = "0.33", + .version = "0.34", .uri_prefixes = mitsu9550_prefixes, .cmdline_usage = mitsu9550_cmdline, .cmdline_arg = mitsu9550_cmdline_arg, @@ -1660,6 +1652,7 @@ struct dyesub_backend mitsu9550_backend = { .read_parse = mitsu9550_read_parse, .main_loop = mitsu9550_main_loop, .query_serno = mitsu9550_query_serno, + .query_markers = mitsu9550_query_markers, .devices = { { USB_VID_MITSU, USB_PID_MITSU_9000AM, P_MITSU_9550, NULL, "mitsu9000"}, { USB_VID_MITSU, USB_PID_MITSU_9000D, P_MITSU_9550, NULL, "mitsu9000"}, diff --git a/backend_shinkos1245.c b/backend_shinkos1245.c index 85991dc..d5ca49b 100644 --- a/backend_shinkos1245.c +++ b/backend_shinkos1245.c @@ -417,6 +417,8 @@ struct shinkos1245_ctx { int num_medias; int media_8x12; + struct marker marker; + uint8_t *databuf; int datalen; int tonecurve; @@ -1280,6 +1282,7 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, struct shinkos1245_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct shinkos1245_resp_status status; ctx->dev = dev; ctx->endp_up = endp_up; @@ -1296,7 +1299,23 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, if (!ctx->jobid) ctx->jobid++; - /* TODO: Query & Update Marker */ + /* Query Media */ + if (shinkos1245_get_media(ctx)) + return CUPS_BACKEND_FAILED; + if (!ctx->num_medias) { + ERROR("Media Query Error\n"); + return CUPS_BACKEND_FAILED; + } + + /* Query status */ + if (shinkos1245_get_status(ctx, &status)) + return CUPS_BACKEND_FAILED; + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = ctx->media_8x12 ? "8x12" : "8x10"; + ctx->marker.levelmax = ctx->media_8x12 ? 230 : 280; + ctx->marker.levelnow = ctx->marker.levelmax - be32_to_cpu(status.counters.media); + return CUPS_BACKEND_OK; } @@ -1405,13 +1424,6 @@ static int shinkos1245_main_loop(void *vctx, int copies) { int i, num, last_state = -1, state = S_IDLE; struct shinkos1245_resp_status status1, status2; - /* Query Media information if necessary */ - if (!ctx->num_medias) - shinkos1245_get_media(ctx); - if (!ctx->num_medias) { - ERROR("Media Query Error\n"); - return CUPS_BACKEND_FAILED; - } /* Make sure print size is supported */ for (i = 0 ; i < ctx->num_medias ; i++) { if (ctx->hdr.media == ctx->medias[i].code && @@ -1429,13 +1441,6 @@ static int shinkos1245_main_loop(void *vctx, int copies) { if (copies > 9999) // XXX test against remaining media? copies = 9999; - /* 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='%s'\n", ctx->media_8x12? "8x12" : "8x10"); - ATTR("marker-types=ribbonWax\n"); - top: if (state != last_state) { if (dyesub_debug) @@ -1459,15 +1464,6 @@ top: if (status1.state.status1 == STATE_STATUS1_ERROR) goto printer_error; - /* Work out the remaining media percentage */ - { - int total = ctx->media_8x12 ? 230 : 280; - int remain = total - be32_to_cpu(status1.counters.media); - - ATTR("marker-levels=%d\n", remain * 100 / total); - ATTR("marker-message=\"%d prints remaining on ribbon\"\n", remain); - } - last_state = state; fflush(stderr); @@ -1642,6 +1638,23 @@ static int shinkos1245_query_serno(struct libusb_device_handle *dev, uint8_t end return CUPS_BACKEND_OK; } +static int shinkos1245_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct shinkos1245_ctx *ctx = vctx; + struct shinkos1245_resp_status status; + + /* Query status */ + if (shinkos1245_get_status(ctx, &status)) + return CUPS_BACKEND_FAILED; + + ctx->marker.levelnow = ctx->marker.levelmax - be32_to_cpu(status.counters.media); + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + /* Exported */ #define USB_VID_SHINKO 0x10CE #define USB_PID_SHINKO_S1245 0x0007 @@ -1653,7 +1666,7 @@ static const char *shinkos1245_prefixes[] = { struct dyesub_backend shinkos1245_backend = { .name = "Shinko/Sinfonia CHC-S1245/E1", - .version = "0.20", + .version = "0.21", .uri_prefixes = shinkos1245_prefixes, .cmdline_usage = shinkos1245_cmdline, .cmdline_arg = shinkos1245_cmdline_arg, @@ -1663,6 +1676,7 @@ struct dyesub_backend shinkos1245_backend = { .read_parse = shinkos1245_read_parse, .main_loop = shinkos1245_main_loop, .query_serno = shinkos1245_query_serno, + .query_markers = shinkos1245_query_markers, .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S1245, P_SHINKO_S1245, NULL, "shinkos1245"}, { 0, 0, 0, NULL, NULL} diff --git a/backend_shinkos2145.c b/backend_shinkos2145.c index c070d67..c152705 100644 --- a/backend_shinkos2145.c +++ b/backend_shinkos2145.c @@ -92,24 +92,6 @@ struct s2145_printjob_hdr { uint32_t unk21; } __attribute__((packed)); -/* Private data structure */ -struct shinkos2145_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - - uint8_t jobid; - - struct s2145_printjob_hdr hdr; - - uint8_t *databuf; - int datalen; - - uint16_t last_donor; - uint16_t last_remain; - uint16_t media_prints; -}; - /* Structs for printer */ struct s2145_cmd_hdr { uint16_t cmd; @@ -803,6 +785,24 @@ struct s2145_getunique_resp { uint8_t data[24]; /* Not necessarily all used. */ } __attribute__((packed)); +/* Private data structure */ +struct shinkos2145_ctx { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + + uint8_t jobid; + + struct s2145_printjob_hdr hdr; + + uint8_t *databuf; + int datalen; + + struct s2145_mediainfo_resp media; + struct marker marker; + int media_code; +}; + #define READBACK_LEN 128 /* Needs to be larger than largest response hdr */ #define CMDBUF_LEN sizeof(struct s2145_print_cmd) @@ -973,27 +973,10 @@ static int get_errorlog(struct shinkos2145_ctx *ctx) return 0; } -static int get_mediainfo(struct shinkos2145_ctx *ctx) +static void dump_mediainfo(struct s2145_mediainfo_resp *resp) { - struct s2145_cmd_hdr cmd; - struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf; - int ret, num = 0; int i; - cmd.cmd = cpu_to_le16(S2145_CMD_MEDIAINFO); - cmd.len = cpu_to_le16(0); - - if ((ret = s2145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - 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: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { INFO(" %02d: C 0x%02x (%s), %04ux%04u, M 0x%02x (%s), P 0x%02x (%s)\n", i, @@ -1003,7 +986,6 @@ static int get_mediainfo(struct shinkos2145_ctx *ctx) 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) @@ -1357,7 +1339,7 @@ int shinkos2145_cmdline_arg(void *vctx, int argc, char **argv) j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg); break; case 'm': - j = get_mediainfo(ctx); + dump_mediainfo(&ctx->media); break; case 'r': j = reset_curve(ctx, RESET_USER_CURVE); @@ -1405,6 +1387,7 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, uint8_t jobid) { struct shinkos2145_ctx *ctx = vctx; + int i; ctx->dev = dev; ctx->endp_up = endp_up; @@ -1415,10 +1398,49 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, if (!ctx->jobid) ctx->jobid++; - /* Initialize donor */ - ctx->last_donor = ctx->last_remain = ctx->media_prints = 65535; + /* Query Media */ + struct s2145_cmd_hdr cmd; + struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf; + int num = 0; + + cmd.cmd = cpu_to_le16(S2145_CMD_MEDIAINFO); + cmd.len = cpu_to_le16(0); + + if (s2145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*resp), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + memcpy(&ctx->media, resp, sizeof(ctx->media)); + + /* Figure out the media type... */ + int media_prints = 65536; + for (i = 0 ; i < ctx->media.count ; i++) { + if (print_counts(ctx->media.items[i].code) < media_prints) { + media_prints = print_counts(ctx->media.items[i].code); + ctx->media_code = ctx->media.items[i].code; + } + } + + /* Query Status */ + struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; + cmd.cmd = cpu_to_le16(S2145_CMD_STATUS); + cmd.len = cpu_to_le16(0); + + if (s2145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*sts), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = print_sizes(ctx->media_code); + ctx->marker.levelmax = media_prints; + ctx->marker.levelnow = le32_to_cpu(sts->count_ribbon_left); - // TODO: Query & Update Marker return CUPS_BACKEND_OK; } @@ -1525,49 +1547,20 @@ static int shinkos2145_main_loop(void *vctx, int copies) { struct s2145_cmd_hdr *cmd = (struct s2145_cmd_hdr *) cmdbuf;; struct s2145_print_cmd *print = (struct s2145_print_cmd *) cmdbuf; struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; - struct s2145_mediainfo_resp *media = (struct s2145_mediainfo_resp *) rdbuf; - - /* Send Media Query */ - memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S2145_CMD_MEDIAINFO); - cmd->len = cpu_to_le16(0); - - if ((ret = s2145_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(*media), - &num)) < 0) { - 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 s2145_mediainfo_resp) - sizeof(struct s2145_status_hdr))) - return CUPS_BACKEND_FAILED; /* Validate print sizes */ - for (i = 0; i < media->count ; i++) { - /* Figure out the media type... */ - int media_prints = print_counts(media->items[i].code); - if (media_prints < ctx->media_prints) - ctx->media_prints = media_prints; - + for (i = 0; i < ctx->media.count ; i++) { /* Look for matching media */ - if (le16_to_cpu(media->items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) && - le16_to_cpu(media->items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)) && - media->items[i].print_type == le32_to_cpu(ctx->hdr.method)) + if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) && + le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)) && + ctx->media.items[i].print_type == le32_to_cpu(ctx->hdr.method)) break; } - if (i == media->count) { + if (i == ctx->media.count) { ERROR("Incorrect media loaded for print!\n"); return CUPS_BACKEND_HOLD; } - /* 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='Color'\n"); - ATTR("marker-types=ribbonWax\n"); - // XXX check copies against remaining media! top: @@ -1590,23 +1583,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 / ctx->media_prints; - if (donor != ctx->last_donor) { - ctx->last_donor = donor; - ATTR("marker-levels=%d\n", donor); - } - remain = le32_to_cpu(sts->count_ribbon_left); - if (remain != ctx->last_remain) { - ctx->last_remain = remain; - ATTR("marker-message=\"%d prints remaining on ribbon\"\n", remain); + if (ctx->marker.levelnow != (int)sts->count_ribbon_left) { + ctx->marker.levelnow = sts->count_ribbon_left; + dump_markers(&ctx->marker, 1, 0); } if (sts->hdr.result != RESULT_SUCCESS) @@ -1689,7 +1673,8 @@ top: INFO("Fast return mode enabled.\n"); state = S_FINISHED; } else if (sts->hdr.status == STATUS_READY || - sts->hdr.status == STATUS_FINISHED) { + sts->hdr.status == STATUS_FINISHED || + sts->hdr.status == ERROR_PRINTER) { state = S_FINISHED; } break; @@ -1700,6 +1685,16 @@ top: if (state != S_FINISHED) goto top; + if (sts->hdr.status == ERROR_PRINTER) { + if(sts->hdr.error == ERROR_NONE) + sts->hdr.error = sts->hdr.status; + INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", + sts->hdr.error, + error_str(sts->hdr.error), + sts->hdr.printer_major, + sts->hdr.printer_minor, error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + } + INFO("Print complete\n"); return CUPS_BACKEND_OK; @@ -1749,6 +1744,33 @@ static int shinkos2145_query_serno(struct libusb_device_handle *dev, uint8_t end return CUPS_BACKEND_OK; } +static int shinkos2145_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct shinkos2145_ctx *ctx = vctx; + struct s2145_cmd_hdr cmd; + struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf; + int num; + + /* Query Status */ + cmd.cmd = cpu_to_le16(S2145_CMD_STATUS); + cmd.len = cpu_to_le16(0); + + if (s2145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*sts), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts->count_ribbon_left); + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + /* Exported */ #define USB_VID_SHINKO 0x10CE #define USB_PID_SHINKO_S2145 0x000E @@ -1760,7 +1782,7 @@ static const char *shinkos2145_prefixes[] = { struct dyesub_backend shinkos2145_backend = { .name = "Shinko/Sinfonia CHC-S2145/S2", - .version = "0.50", + .version = "0.51", .uri_prefixes = shinkos2145_prefixes, .cmdline_usage = shinkos2145_cmdline, .cmdline_arg = shinkos2145_cmdline_arg, @@ -1770,6 +1792,7 @@ struct dyesub_backend shinkos2145_backend = { .read_parse = shinkos2145_read_parse, .main_loop = shinkos2145_main_loop, .query_serno = shinkos2145_query_serno, + .query_markers = shinkos2145_query_markers, .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S2145, P_SHINKO_S2145, NULL, "shinkos2145"}, { 0, 0, 0, NULL, NULL} diff --git a/backend_shinkos6145.c b/backend_shinkos6145.c index 064b472..8447c40 100644 --- a/backend_shinkos6145.c +++ b/backend_shinkos6145.c @@ -261,43 +261,6 @@ struct shinkos6145_correctionparam { uint8_t pad[3948]; // @12436, null. } __attribute__((packed)); /* 16384 bytes */ -/* Private data structure */ -struct shinkos6145_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; - - uint8_t jobid; - - struct s6145_printjob_hdr hdr; - - uint8_t image_avg[3]; /* CMY */ - - uint8_t *databuf; - size_t datalen; - - uint8_t ribbon_type; - uint8_t input_ymc; - - uint16_t last_donor; - uint16_t last_remain; - uint16_t last_ribbon; - - uint8_t *eeprom; - size_t eepromlen; - - void *dl_handle; - ImageProcessingFN ImageProcessing; - ImageAvrCalcFN ImageAvrCalc; - - struct shinkos6145_correctionparam *corrdata; - size_t corrdatalen; -}; - -static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx); -static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx); - /* Structs for printer */ struct s6145_cmd_hdr { uint16_t cmd; @@ -1117,6 +1080,41 @@ struct s6145_imagecorr_data { uint8_t data[16]; } __attribute__((packed)); +/* Private data structure */ +struct shinkos6145_ctx { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + int type; + + uint8_t jobid; + + struct s6145_printjob_hdr hdr; + + uint8_t image_avg[3]; /* CMY */ + + uint8_t *databuf; + size_t datalen; + + uint8_t input_ymc; + + struct marker marker; + + struct s6145_mediainfo_resp media; + + uint8_t *eeprom; + size_t eepromlen; + + void *dl_handle; + ImageProcessingFN ImageProcessing; + ImageAvrCalcFN ImageAvrCalc; + + struct shinkos6145_correctionparam *corrdata; + size_t corrdatalen; +}; + +static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx); +static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx); static int get_param(struct shinkos6145_ctx *ctx, int target, uint32_t *param); #define READBACK_LEN 512 /* Needs to be larger than largest response hdr */ @@ -1357,27 +1355,10 @@ static int get_errorlog(struct shinkos6145_ctx *ctx) return 0; } -static int get_mediainfo(struct shinkos6145_ctx *ctx) +static void dump_mediainfo(struct s6145_mediainfo_resp *resp) { - struct s6145_cmd_hdr cmd; - struct s6145_mediainfo_resp *resp = (struct s6145_mediainfo_resp *) rdbuf; - int ret, num = 0; int i; - cmd.cmd = cpu_to_le16(S6145_CMD_MEDIAINFO); - cmd.len = cpu_to_le16(0); - - if ((ret = s6145_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - 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; - INFO("Loaded Media Type: %s\n", print_ribbons(resp->ribbon)); INFO("Supported Print Sizes: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { @@ -1387,7 +1368,6 @@ static int get_mediainfo(struct shinkos6145_ctx *ctx) le16_to_cpu(resp->items[i].rows), resp->items[i].print_method, print_methods(resp->items[i].print_method)); } - return 0; } static int cancel_job(struct shinkos6145_ctx *ctx, char *str) @@ -1867,7 +1847,7 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv) j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg); break; case 'm': - j = get_mediainfo(ctx); + dump_mediainfo(&ctx->media); break; case 'q': j = shinkos6145_dump_eeprom(ctx, optarg); @@ -1954,10 +1934,38 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, /* Ensure jobid is sane */ ctx->jobid = (jobid & 0x7f) + 1; - /* Initialize donor */ - ctx->last_donor = ctx->last_remain = 65535; + /* Query Media */ + struct s6145_mediainfo_resp *resp = (struct s6145_mediainfo_resp *) rdbuf; + struct s6145_cmd_hdr cmd; + int num; + + if (s6145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*resp), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + memcpy(&ctx->media, resp, sizeof(*resp)); + + /* Query Status */ + struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf; + cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); + + if (s6145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*sts), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = print_ribbons(ctx->media.ribbon); + ctx->marker.levelmax = ribbon_sizes(ctx->media.ribbon); + ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts->count_ribbon_left); - // TODO: Query & Update Marker return CUPS_BACKEND_OK; } @@ -2207,16 +2215,6 @@ static int shinkos6145_main_loop(void *vctx, int copies) { return CUPS_BACKEND_HOLD; } - ctx->last_ribbon = media->ribbon; - - /* 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='%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 */ @@ -2246,23 +2244,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 / ribbon_sizes(ctx->ribbon_type); - if (donor != ctx->last_donor) { - ctx->last_donor = donor; - ATTR("marker-levels=%d\n", donor); - } - remain = le32_to_cpu(sts->count_ribbon_left); - if (remain != ctx->last_remain) { - ctx->last_remain = remain; - ATTR("marker-message=\"%d prints remaining on '%s' ribbon\"\n", remain, print_ribbons(media->ribbon)); + if (ctx->marker.levelnow != (int)sts->count_ribbon_left) { + ctx->marker.levelnow = sts->count_ribbon_left; + dump_markers(&ctx->marker, 1, 0); } if (sts->hdr.result != RESULT_SUCCESS) @@ -2492,6 +2481,33 @@ static int shinkos6145_query_serno(struct libusb_device_handle *dev, uint8_t end return CUPS_BACKEND_OK; } +static int shinkos6145_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct shinkos6145_ctx *ctx = vctx; + struct s6145_cmd_hdr cmd; + struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf; + int num; + + /* Query Status */ + cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); + + if (s6145_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(*sts), + &num)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.levelnow = le32_to_cpu(sts->count_ribbon_left); + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + /* Exported */ #define USB_VID_SHINKO 0x10CE #define USB_PID_SHINKO_S6145 0x0019 @@ -2504,7 +2520,7 @@ static const char *shinkos6145_prefixes[] = { struct dyesub_backend shinkos6145_backend = { .name = "Shinko/Sinfonia CHC-S6145/CS2", - .version = "0.24", + .version = "0.25", .uri_prefixes = shinkos6145_prefixes, .cmdline_usage = shinkos6145_cmdline, .cmdline_arg = shinkos6145_cmdline_arg, @@ -2514,6 +2530,7 @@ struct dyesub_backend shinkos6145_backend = { .read_parse = shinkos6145_read_parse, .main_loop = shinkos6145_main_loop, .query_serno = shinkos6145_query_serno, + .query_markers = shinkos6145_query_markers, .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S6145, P_SHINKO_S6145, NULL, "shinkos6145"}, { USB_VID_SHINKO, USB_PID_SHINKO_S6145D, P_SHINKO_S6145D, NULL, "brava21"}, diff --git a/backend_shinkos6245.c b/backend_shinkos6245.c index 0a7af9a..e331c87 100644 --- a/backend_shinkos6245.c +++ b/backend_shinkos6245.c @@ -92,25 +92,6 @@ struct s6245_printjob_hdr { uint32_t unk21; } __attribute__((packed)); -/* Private data structure */ -struct shinkos6245_ctx { - struct libusb_device_handle *dev; - uint8_t endp_up; - uint8_t endp_down; - int type; - - uint8_t jobid; - - struct s6245_printjob_hdr hdr; - - uint8_t *databuf; - int datalen; - - uint16_t last_donor; - uint16_t last_remain; - uint8_t ribbon_code; -}; - /* Structs for printer */ struct s6245_cmd_hdr { uint16_t cmd; @@ -926,37 +907,47 @@ struct s6245_fwinfo_resp { uint16_t checksum; } __attribute__((packed)); +/* Private data structure */ +struct shinkos6245_ctx { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + int type; + uint8_t jobid; + + struct s6245_printjob_hdr hdr; + + struct marker marker; + + uint8_t *databuf; + int datalen; + + struct s6245_mediainfo_resp media; +}; #define READBACK_LEN 512 /* Needs to be larger than largest response hdr */ #define CMDBUF_LEN sizeof(struct s6245_print_cmd) -static uint8_t rdbuf[READBACK_LEN]; - static int s6245_do_cmd(struct shinkos6245_ctx *ctx, uint8_t *cmd, int cmdlen, - int minlen, int *num) + int buflen, + int *num, struct s6245_status_hdr *resp) { - int ret; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; - libusb_device_handle *dev = ctx->dev; uint8_t endp_up = ctx->endp_up; uint8_t endp_down = ctx->endp_down; + int ret; if ((ret = send_data(dev, endp_down, cmd, cmdlen))) return (ret < 0) ? ret : -99; ret = read_data(dev, endp_up, - rdbuf, READBACK_LEN, num); + (uint8_t *)resp, buflen, num); if (ret < 0) return ret; - if (*num < minlen) { - ERROR("Short read! (%d/%d))\n", *num, minlen); - return -99; - } if (resp->result != RESULT_SUCCESS) { INFO("Printer Status: %02x (%s)\n", resp->status, @@ -973,8 +964,8 @@ static int s6245_do_cmd(struct shinkos6245_ctx *ctx, static int get_status(struct shinkos6245_ctx *ctx) { struct s6245_cmd_hdr cmd; - struct s6245_status_resp *resp = (struct s6245_status_resp *) rdbuf; - struct s6245_getextcounter_resp *resp2 = (struct s6245_getextcounter_resp *) rdbuf; + struct s6245_status_resp resp; + struct s6245_getextcounter_resp resp2; int ret, num = 0; cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS); @@ -982,48 +973,48 @@ static int get_status(struct shinkos6245_ctx *ctx) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } - INFO("Printer Status: 0x%02x (%s)\n", resp->hdr.status, - status_str(resp->hdr.status)); - if (resp->hdr.status == ERROR_PRINTER) { - if(resp->hdr.error == ERROR_NONE) - resp->hdr.error = resp->hdr.status; + INFO("Printer Status: 0x%02x (%s)\n", resp.hdr.status, + status_str(resp.hdr.status)); + if (resp.hdr.status == ERROR_PRINTER) { + if(resp.hdr.error == ERROR_NONE) + resp.hdr.error = resp.hdr.status; INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n", - resp->hdr.error, - error_str(resp->hdr.error), - resp->hdr.printer_major, - resp->hdr.printer_minor, error_codes(resp->hdr.printer_major, resp->hdr.printer_minor)); + resp.hdr.error, + error_str(resp.hdr.error), + resp.hdr.printer_major, + resp.hdr.printer_minor, error_codes(resp.hdr.printer_major, resp.hdr.printer_minor)); } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct s6245_status_hdr))) return 0; INFO(" Print Counts:\n"); - INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp->count_paper)); - INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp->count_lifetime)); - INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp->count_maint)); - INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp->count_head)); - INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp->count_cutter)); - INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp->count_ribbon_left)); + INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp.count_paper)); + INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp.count_lifetime)); + INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp.count_maint)); + INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp.count_head)); + INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp.count_cutter)); + INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp.count_ribbon_left)); INFO("Bank 1: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank1_status, bank_statuses(resp->bank1_status), - resp->bank1_printid, - le16_to_cpu(resp->bank1_finished), - le16_to_cpu(resp->bank1_specified), - le16_to_cpu(resp->bank1_remaining)); + resp.bank1_status, bank_statuses(resp.bank1_status), + resp.bank1_printid, + le16_to_cpu(resp.bank1_finished), + le16_to_cpu(resp.bank1_specified), + le16_to_cpu(resp.bank1_remaining)); INFO("Bank 2: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n", - resp->bank2_status, bank_statuses(resp->bank1_status), - resp->bank2_printid, - le16_to_cpu(resp->bank2_finished), - le16_to_cpu(resp->bank2_specified), - le16_to_cpu(resp->bank2_remaining)); + resp.bank2_status, bank_statuses(resp.bank1_status), + resp.bank2_printid, + le16_to_cpu(resp.bank2_finished), + le16_to_cpu(resp.bank2_specified), + le16_to_cpu(resp.bank2_remaining)); - INFO("Tonecurve Status: 0x%02x (%s)\n", resp->tonecurve_status, tonecurve_statuses(resp->tonecurve_status)); + INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, tonecurve_statuses(resp.tonecurve_status)); /* Query Extended counters */ cmd.cmd = cpu_to_le16(S6245_CMD_EXTCOUNTER); @@ -1031,17 +1022,17 @@ static int get_status(struct shinkos6245_ctx *ctx) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp2), - &num)) < 0) { + sizeof(resp2), + &num, (void*)&resp2)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } - if (le16_to_cpu(resp2->hdr.payload_len) != (sizeof(struct s6245_getextcounter_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp2.hdr.payload_len) != (sizeof(struct s6245_getextcounter_resp) - sizeof(struct s6245_status_hdr))) return 0; - INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2->lifetime_distance)); - INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2->maint_distance)); - INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2->head_distance)); + INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2.lifetime_distance)); + INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2.maint_distance)); + INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2.head_distance)); return 0; } @@ -1049,7 +1040,7 @@ static int get_status(struct shinkos6245_ctx *ctx) static int get_fwinfo(struct shinkos6245_ctx *ctx) { struct s6245_fwinfo_cmd cmd; - struct s6245_fwinfo_resp *resp = (struct s6245_fwinfo_resp *)rdbuf; + struct s6245_fwinfo_resp resp; int num = 0; int i; @@ -1064,23 +1055,23 @@ static int get_fwinfo(struct shinkos6245_ctx *ctx) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); continue; } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_fwinfo_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_fwinfo_resp) - sizeof(struct s6245_status_hdr))) continue; INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i), - resp->major, resp->minor); + resp.major, resp.minor); #if 0 - INFO(" name: '%s'\n", resp->name); - INFO(" type: '%s'\n", resp->type); - INFO(" date: '%s'\n", resp->date); - INFO(" version: %02x.%02x (CRC %04x)\n", resp->major, resp->minor, - le16_to_cpu(resp->checksum)); + INFO(" name: '%s'\n", resp.name); + INFO(" type: '%s'\n", resp.type); + INFO(" date: '%s'\n", resp.date); + INFO(" version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor, + le16_to_cpu(resp.checksum)); #endif } return 0; @@ -1089,7 +1080,7 @@ static int get_fwinfo(struct shinkos6245_ctx *ctx) static int get_errorlog(struct shinkos6245_ctx *ctx) { struct s6245_errorlog_cmd cmd; - struct s6245_errorlog_resp *resp = (struct s6245_errorlog_resp *) rdbuf; + struct s6245_errorlog_resp resp; int num = 0; int i = 0; @@ -1102,50 +1093,33 @@ static int get_errorlog(struct shinkos6245_ctx *ctx) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); return ret; } - if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct s6245_status_hdr))) + if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct s6245_status_hdr))) return -2; INFO("Stored Error ID %d:\n", i); INFO(" %04d-%02u-%02u %02u:%02u:%02u @ %08u prints : 0x%02x/0x%02x (%s)\n", - resp->time_year + 2000, resp->time_month, resp->time_day, - resp->time_hour, resp->time_min, resp->time_sec, - le32_to_cpu(resp->print_counter), - resp->error_major, resp->error_minor, - error_codes(resp->error_major, resp->error_minor)); + resp.time_year + 2000, resp.time_month, resp.time_day, + resp.time_hour, resp.time_min, resp.time_sec, + le32_to_cpu(resp.print_counter), + resp.error_major, resp.error_minor, + error_codes(resp.error_major, resp.error_minor)); INFO(" Temp: %02u/%02u Hum: %02u\n", - resp->printer_thermistor, resp->head_thermistor, resp->printer_humidity); - } while (++i < le16_to_cpu(resp->error_count)); + resp.printer_thermistor, resp.head_thermistor, resp.printer_humidity); + } while (++i < le16_to_cpu(resp.error_count)); return 0; } -static int get_mediainfo(struct shinkos6245_ctx *ctx) +static void dump_mediainfo(struct s6245_mediainfo_resp *resp) { - struct s6245_cmd_hdr cmd; - struct s6245_mediainfo_resp *resp = (struct s6245_mediainfo_resp *) rdbuf; - int ret, num = 0; int i; - cmd.cmd = cpu_to_le16(S6245_CMD_MEDIAINFO); - cmd.len = cpu_to_le16(0); - - if ((ret = s6245_do_cmd(ctx, - (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { - 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: %u entries:\n", resp->count); for (i = 0 ; i < resp->count ; i++) { @@ -1155,13 +1129,12 @@ static int get_mediainfo(struct shinkos6245_ctx *ctx) le16_to_cpu(resp->items[i].rows), resp->items[i].print_method, print_methods(resp->items[i].print_method)); } - return 0; } static int cancel_job(struct shinkos6245_ctx *ctx, char *str) { struct s6245_cancel_cmd cmd; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; + struct s6245_status_hdr resp; int ret, num = 0; if (!str) @@ -1174,8 +1147,8 @@ static int cancel_job(struct shinkos6245_ctx *ctx, char *str) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } @@ -1186,7 +1159,7 @@ static int cancel_job(struct shinkos6245_ctx *ctx, char *str) static int flash_led(struct shinkos6245_ctx *ctx) { struct s6245_cmd_hdr cmd; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; + struct s6245_status_hdr resp; int ret, num = 0; cmd.cmd = cpu_to_le16(S6245_CMD_FLASHLED); @@ -1194,8 +1167,8 @@ static int flash_led(struct shinkos6245_ctx *ctx) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } @@ -1207,7 +1180,7 @@ static int flash_led(struct shinkos6245_ctx *ctx) static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param) { struct s6245_setparam_cmd cmd; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; + struct s6245_status_hdr resp; int ret, num = 0; /* Set up command */ @@ -1219,8 +1192,8 @@ static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret); } @@ -1230,7 +1203,7 @@ static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param) static int reset_curve(struct shinkos6245_ctx *ctx, int target) { struct s6245_reset_cmd cmd; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; + struct s6245_status_hdr resp; int ret, num = 0; cmd.target = target; @@ -1240,8 +1213,8 @@ static int reset_curve(struct shinkos6245_ctx *ctx, int target) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } @@ -1251,8 +1224,8 @@ static int reset_curve(struct shinkos6245_ctx *ctx, int target) static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname) { - struct s6245_readtone_cmd cmd; - struct s6245_readtone_resp *resp = (struct s6245_readtone_resp *) rdbuf; + struct s6245_readtone_cmd cmd; + struct s6245_readtone_resp resp; int ret, num = 0; uint8_t *data; @@ -1270,25 +1243,25 @@ static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); return ret; } - resp->total_size = le16_to_cpu(resp->total_size); + resp.total_size = le16_to_cpu(resp.total_size); - data = malloc(resp->total_size * 2); + data = malloc(resp.total_size * 2); if (!data) { ERROR("Memory Allocation Failure!\n"); return -1; } i = 0; - while (i < resp->total_size) { + while (i < resp.total_size) { ret = read_data(ctx->dev, ctx->endp_up, data + i, - resp->total_size * 2 - i, + resp.total_size * 2 - i, &num); if (ret < 0) goto done; @@ -1296,7 +1269,7 @@ static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname) } i = j = 0; - while (i < resp->total_size) { + while (i < resp.total_size) { memcpy(curves + j, data + i+2, data[i+1]); j += data[i+1] / 2; i += data[i+1] + 2; @@ -1326,7 +1299,7 @@ done: static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname) { struct s6245_update_cmd cmd; - struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf; + struct s6245_status_hdr resp; int ret, num = 0; INFO("Set %s Tone Curve from '%s'\n", update_targets(target), fname); @@ -1369,8 +1342,8 @@ static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname) if ((ret = s6245_do_cmd(ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd)); goto done; } @@ -1457,7 +1430,7 @@ int shinkos6245_cmdline_arg(void *vctx, int argc, char **argv) j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg); break; case 'm': - j = get_mediainfo(ctx); + dump_mediainfo(&ctx->media); break; case 'r': j = reset_curve(ctx, RESET_TONE_CURVE); @@ -1499,6 +1472,10 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, struct shinkos6245_ctx *ctx = vctx; struct libusb_device *device; struct libusb_device_descriptor desc; + struct s6245_cmd_hdr cmd; + struct s6245_status_resp status; + + int num; ctx->dev = dev; ctx->endp_up = endp_up; @@ -1515,10 +1492,32 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, if (!ctx->jobid) ctx->jobid++; - /* Initialize donor */ - ctx->last_donor = ctx->last_remain = 65535; + /* Query Media */ + cmd.cmd = cpu_to_le16(S6245_CMD_MEDIAINFO); + cmd.len = cpu_to_le16(0); + + if (s6245_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(ctx->media), + &num, (void*)&ctx->media)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + /* Query Status */ + if (s6245_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(status), + &num, (void*)&status)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; + ctx->marker.name = ribbon_sizes(ctx->media.ribbon_code); + ctx->marker.levelmax = ribbon_counts(ctx->media.ribbon_code); + ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(status.count_ribbon_left); - // TODO: Query & Update Marker return CUPS_BACKEND_OK; } @@ -1618,15 +1617,14 @@ static int shinkos6245_main_loop(void *vctx, int copies) { int ret, num; uint8_t cmdbuf[CMDBUF_LEN]; - uint8_t rdbuf2[READBACK_LEN]; int i, last_state = -1, state = S_IDLE; uint8_t mcut; struct s6245_cmd_hdr *cmd = (struct s6245_cmd_hdr *) cmdbuf;; struct s6245_print_cmd *print = (struct s6245_print_cmd *) cmdbuf; - struct s6245_status_resp *sts = (struct s6245_status_resp *) rdbuf; - struct s6245_mediainfo_resp *media = (struct s6245_mediainfo_resp *) rdbuf; + struct s6245_status_resp sts, sts2; + struct s6245_status_hdr resp; /* Cap copies */ // XXX 120 for 8x10 media, 100 for 8x12 media (S6245) @@ -1649,34 +1647,17 @@ static int shinkos6245_main_loop(void *vctx, int copies) { } // XXX what about mcut |= PRINT_METHOD_DISABLE_ERR; - /* Send Media Query */ - memset(cmdbuf, 0, CMDBUF_LEN); - cmd->cmd = cpu_to_le16(S6245_CMD_MEDIAINFO); - cmd->len = cpu_to_le16(0); - - if ((ret = s6245_do_cmd(ctx, - cmdbuf, sizeof(*cmd), - sizeof(*media), - &num)) < 0) { - 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 s6245_mediainfo_resp) - sizeof(struct s6245_status_hdr))) - return CUPS_BACKEND_FAILED; - /* Validate print sizes */ - for (i = 0; i < media->count ; i++) { + for (i = 0; i < ctx->media.count ; i++) { /* Look for matching media */ - if (le16_to_cpu(media->items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) && - le16_to_cpu(media->items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows))) + if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) && + le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows))) break; } - if (i == media->count) { + if (i == ctx->media.count) { ERROR("Incorrect media loaded for print!\n"); return CUPS_BACKEND_HOLD; } - ctx->ribbon_code = media->ribbon_code; /* Send Set Time */ { @@ -1698,21 +1679,14 @@ static int shinkos6245_main_loop(void *vctx, int copies) { if ((ret = s6245_do_cmd(ctx, cmdbuf, sizeof(*stime), sizeof(struct s6245_status_hdr), - &num)) < 0) { + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(stime->hdr.cmd)); return CUPS_BACKEND_FAILED; } - if (sts->hdr.result != RESULT_SUCCESS) + if (resp.result != RESULT_SUCCESS) goto printer_error; } - /* 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='%s'\n", ribbon_sizes(ctx->ribbon_code)); - ATTR("marker-types=ribbonWax\n"); - // XXX check copies against remaining media! top: @@ -1728,35 +1702,26 @@ top: if ((ret = s6245_do_cmd(ctx, cmdbuf, sizeof(*cmd), - sizeof(struct s6245_status_hdr), - &num)) < 0) { + sizeof(sts), + &num, (void*)&sts)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd)); return CUPS_BACKEND_FAILED; } - if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) { - uint16_t donor, remain; - - memcpy(rdbuf2, rdbuf, READBACK_LEN); + if (memcmp(&sts2, &sts, sizeof(sts))) { + memcpy(&sts2, &sts, sizeof(sts)); INFO("Printer Status: 0x%02x (%s)\n", - sts->hdr.status, status_str(sts->hdr.status)); + sts.hdr.status, status_str(sts.hdr.status)); - /* Guessimate a percentage for the remaining media */ - donor = le32_to_cpu(sts->count_ribbon_left) * 100 / ribbon_counts(ctx->ribbon_code); - if (donor != ctx->last_donor) { - ctx->last_donor = donor; - ATTR("marker-levels=%d\n", donor); - } - remain = le32_to_cpu(sts->count_ribbon_left); - if (remain != ctx->last_remain) { - ctx->last_remain = remain; - ATTR("marker-message=\"%d prints remaining on '%s' ribbon\"\n", remain, ribbon_sizes(ctx->ribbon_code)); + if (ctx->marker.levelnow != (int)sts.count_ribbon_left) { + ctx->marker.levelnow = sts.count_ribbon_left; + dump_markers(&ctx->marker, 1, 0); } - if (sts->hdr.result != RESULT_SUCCESS) + if (sts.hdr.result != RESULT_SUCCESS) goto printer_error; - if (sts->hdr.error == ERROR_PRINTER) + if (sts.hdr.error == ERROR_PRINTER) goto printer_error; } else if (state == last_state) { sleep(1); @@ -1772,8 +1737,8 @@ top: /* make sure we're not colliding with an existing jobid */ - while (ctx->jobid == sts->bank1_printid || - ctx->jobid == sts->bank2_printid) { + while (ctx->jobid == sts.bank1_printid || + ctx->jobid == sts.bank2_printid) { ctx->jobid++; ctx->jobid &= 0x7f; if (!ctx->jobid) @@ -1781,8 +1746,8 @@ top: } /* If either bank is free, continue */ - if (sts->bank1_status == BANK_STATUS_FREE || - sts->bank2_status == BANK_STATUS_FREE) + if (sts.bank1_status == BANK_STATUS_FREE || + sts.bank2_status == BANK_STATUS_FREE) state = S_PRINTER_READY_CMD; break; @@ -1804,20 +1769,20 @@ top: if ((ret = s6245_do_cmd(ctx, cmdbuf, sizeof(*print), - sizeof(struct s6245_status_hdr), - &num)) < 0) { + sizeof(resp), + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd)); return ret; } - if (sts->hdr.result != RESULT_SUCCESS) { - if (sts->hdr.error == ERROR_BUFFER_FULL) { + if (resp.result != RESULT_SUCCESS) { + if (resp.error == ERROR_BUFFER_FULL) { INFO("Printer Buffers full, retrying\n"); break; - } else if ((sts->hdr.status & 0xf0) == 0x30 || sts->hdr.status == 0x21) { - INFO("Printer busy (%s), retrying\n", status_str(sts->hdr.status)); + } else if ((resp.status & 0xf0) == 0x30 || sts.hdr.status == 0x21) { + INFO("Printer busy (%s), retrying\n", status_str(sts.hdr.status)); break; - } else if (sts->hdr.status != ERROR_NONE) + } else if (resp.status != ERROR_NONE) goto printer_error; } @@ -1834,7 +1799,7 @@ top: if (fast_return) { INFO("Fast return mode enabled.\n"); state = S_FINISHED; - } else if (sts->hdr.status == STATUS_READY) { + } else if (sts.hdr.status == STATUS_READY) { state = S_FINISHED; } break; @@ -1851,19 +1816,19 @@ top: printer_error: ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n", - sts->hdr.error, - error_str(sts->hdr.error), - sts->hdr.status, - status_str(sts->hdr.status), - sts->hdr.printer_major, sts->hdr.printer_minor, - error_codes(sts->hdr.printer_major, sts->hdr.printer_minor)); + sts.hdr.error, + error_str(sts.hdr.error), + sts.hdr.status, + status_str(sts.hdr.status), + sts.hdr.printer_major, sts.hdr.printer_minor, + error_codes(sts.hdr.printer_major, sts.hdr.printer_minor)); return CUPS_BACKEND_FAILED; } static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len) { struct s6245_cmd_hdr cmd; - struct s6245_getserial_resp *resp = (struct s6245_getserial_resp*) rdbuf; + struct s6245_getserial_resp resp; int ret, num = 0; struct shinkos6245_ctx ctx = { @@ -1877,23 +1842,50 @@ static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t end if ((ret = s6245_do_cmd(&ctx, (uint8_t*)&cmd, sizeof(cmd), - sizeof(*resp) - 1, - &num)) < 0) { + sizeof(resp) - 1, + &num, (void*)&resp)) < 0) { ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); return ret; } /* Null-terminate */ - resp->hdr.payload_len = le16_to_cpu(resp->hdr.payload_len); - if (resp->hdr.payload_len > 23) - resp->hdr.payload_len = 23; - resp->data[resp->hdr.payload_len] = 0; - strncpy(buf, (char*)resp->data, buf_len); + resp.hdr.payload_len = le16_to_cpu(resp.hdr.payload_len); + if (resp.hdr.payload_len > 23) + resp.hdr.payload_len = 23; + resp.data[resp.hdr.payload_len] = 0; + strncpy(buf, (char*)resp.data, buf_len); buf[buf_len-1] = 0; /* ensure it's null terminated */ return CUPS_BACKEND_OK; } +static int shinkos6245_query_markers(void *vctx, struct marker **markers, int *count) +{ + struct shinkos6245_ctx *ctx = vctx; + struct s6245_cmd_hdr cmd; + struct s6245_status_resp status; + int num; + + /* Query Status */ + cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS); + cmd.len = cpu_to_le16(0); + + if (s6245_do_cmd(ctx, + (uint8_t*)&cmd, sizeof(cmd), + sizeof(status), + &num, (void*)&status)) { + ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd)); + return CUPS_BACKEND_FAILED; + } + + ctx->marker.levelnow = le32_to_cpu(status.count_ribbon_left); + + *markers = &ctx->marker; + *count = 1; + + return CUPS_BACKEND_OK; +} + /* Exported */ #define USB_VID_SHINKO 0x10CE #define USB_PID_SHINKO_S6245 0x001D @@ -1907,7 +1899,7 @@ static const char *shinkos6245_prefixes[] = { struct dyesub_backend shinkos6245_backend = { .name = "Shinko/Sinfonia CHC-S6245", - .version = "0.09WIP", + .version = "0.10WIP", .uri_prefixes = shinkos6245_prefixes, .cmdline_usage = shinkos6245_cmdline, .cmdline_arg = shinkos6245_cmdline_arg, @@ -1917,6 +1909,7 @@ struct dyesub_backend shinkos6245_backend = { .read_parse = shinkos6245_read_parse, .main_loop = shinkos6245_main_loop, .query_serno = shinkos6245_query_serno, + .query_markers = shinkos6245_query_markers, .devices = { { USB_VID_SHINKO, USB_PID_SHINKO_S6245, P_SHINKO_S6245, NULL, "shinkos6245"}, { USB_VID_HITI, USB_PID_HITI_P910L, P_SHINKO_S6245, NULL, "hitip910"},