From a80928318903105df63660374e2e63c3c111be14 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 26 Jun 2022 00:47:06 -0400 Subject: [PATCH] hiti: Parse v2 of the heatdata format The structure is known, and some guesses as to the individual data blocks. Don't know how this maps to actual printer commands just yet. --- backend_hiti.c | 145 +++++++++++++++++++++++++++---------- hiti_data/README-hiti-data | 56 +++++++++++--- 2 files changed, 154 insertions(+), 47 deletions(-) diff --git a/backend_hiti.c b/backend_hiti.c index fa4f61d..3374d4f 100644 --- a/backend_hiti.c +++ b/backend_hiti.c @@ -273,6 +273,21 @@ struct hiti_heattable_v1b { /* P51x (newer) */ STATIC_ASSERT(sizeof(struct hiti_heattable_v1b) == 12917); +/* All fields are little endian */ +struct hiti_heattable_entry_v2 { + uint16_t type; + uint8_t unknown; + uint16_t zero; + uint32_t offset; +} __attribute((packed)); + +struct hiti_heattable_hdr_v2 { + uint8_t num_headers; + struct hiti_heattable_entry_v2 entries[]; +} __attribute((packed)); + +#define HEATTABLE_V2_MAX_SIZE (1024*128) + /* All fields are LE */ struct hiti_gpjobhdr { uint32_t cookie; /* "GPHT" */ @@ -412,6 +427,14 @@ struct hiti_ctx { struct hiti_rpidm rpidm; uint16_t ribbonvendor; // low byte = media subtype, high byte = type. uint32_t media_remain; // XXX could be array? + + uint8_t *heattable_buf; + struct hiti_heattable_v2 { + uint16_t type; + uint8_t *data; + uint32_t len; + } *heattable_v2; + uint8_t num_heattable_entries; }; /* Prototypes */ @@ -1336,65 +1359,45 @@ static int hiti_cvd(struct hiti_ctx *ctx, uint8_t *buf, uint32_t buf_len) return ret; } -static int hiti_send_heat_data(struct hiti_ctx *ctx, uint8_t mode, uint8_t matte) +static const char* hiti_get_heat_file(struct hiti_ctx *ctx, uint8_t mode) { - const char *fname = NULL; - union { - struct hiti_heattable_v1a v1a; - struct hiti_heattable_v1a v1b; - } table; - uint8_t *y, *m, *c, *o, *om, *cvd; - - int ret, len; - int mediaver = ctx->ribbonvendor & 0x3f; int mediatype = ((ctx->ribbonvendor & 0xf000) == 0x1000); // XXX if field_0x70 != 100) send blank/empty tables.. // no idea what sets this field. - switch (ctx->conn->type) - { + switch (ctx->conn->type) { case P_HITI_51X: if (!mediatype) { /* DNP media */ if (mode) { - fname = "P51x_heatqhra.bin"; - break; + return "P51x_heatqhra.bin"; } else { - fname = "P51x_heatthra.bin"; - break; + return "P51x_heatthra.bin"; } } else { /* CHC media */ if (mode) { switch(mediaver) { case 0: - fname = "P51x_hea0qcra.bin"; - break; + return "P51x_hea0qcra.bin"; case 1: - fname = "P51x_hea1qcra.bin"; - break; + return "P51x_hea1qcra.bin"; case 2: - fname = "P51x_hea2qcra.bin"; - break; + return "P51x_hea2qcra.bin"; case 3: default: - fname = "P51x_hea3qcra.bin"; - break; + return "P51x_hea3qcra.bin"; } } else { switch(mediaver) { case 0: - fname = "P51x_hea0tcra.bin"; - break; + return "P51x_hea0tcra.bin"; case 1: - fname = "P51x_hea1tcra.bin"; - break; + return "P51x_hea1tcra.bin"; case 2: - fname = "P51x_hea2tcra.bin"; - break; + return "P51x_hea2tcra.bin"; case 3: default: - fname = "P51x_hea3tcra.bin"; - break; + return "P51x_hea3tcra.bin"; } } } @@ -1402,9 +1405,23 @@ static int hiti_send_heat_data(struct hiti_ctx *ctx, uint8_t mode, uint8_t matte case P_HITI_52X: case P_HITI_720: default: - fname = NULL; - break; + return NULL; } +} + +static int hiti_send_heat_data(struct hiti_ctx *ctx, uint8_t mode, uint8_t matte) +{ + const char *fname = NULL; + union { + struct hiti_heattable_v1a v1a; + struct hiti_heattable_v1a v1b; + } table; + uint8_t *y, *m, *c, *o, *om, *cvd; + + int ret, len; + + fname = hiti_get_heat_file(ctx, mode); + if (fname) { char full[2048]; snprintf(full, sizeof(full), "%s/%s", corrtable_path, fname); @@ -1990,7 +2007,7 @@ static int hiti_main_loop(void *vctx, const void *vjob, int wait_for_return) if (ret) return CUPS_BACKEND_FAILED; - // XXX msg 8011 sent here.. + // XXX msg 8011 sent here on P52x (and maybe others?) /* XXX startjob returns actual jobid */ jobid.lun = 0; @@ -2021,15 +2038,14 @@ static int hiti_main_loop(void *vctx, const void *vjob, int wait_for_return) ret = hiti_docmd(ctx, CMD_EFD_CHS, chs, sizeof(chs), &resplen); if (ret) return CUPS_BACKEND_FAILED; + + // XXX send CMD_ESD_SHTPC (Heating Parameters & Tone Curve, ~7KB payload) instead? } ret = hiti_docmd(ctx, CMD_EPC_SP, NULL, 0, &resplen); if (ret) return CUPS_BACKEND_FAILED; - // XXX send ESD_SHTPC w/ heat table. Unknown. - // CMD_ESD_SHPTC // Heating Parameters & Tone Curve (~7Kb, seen on windows..) - /* Send heat table data */ resend_y: INFO("Sending yellow plane\n"); @@ -2539,6 +2555,59 @@ static int hiti_query_stats(void *vctx, struct printerstats *stats) return CUPS_BACKEND_OK; } +static int hiti_read_heattable_v2(struct hiti_ctx *ctx, char* fname) { + int len = 0; + int ret; + char full[2048]; + int i; + struct hiti_heattable_hdr_v2 *hdr; + + ctx->num_heattable_entries = 0; + if (ctx->heattable_buf) { + free(ctx->heattable_buf); + ctx->heattable_buf = NULL; + } + if (ctx->heattable_v2) { + free(ctx->heattable_v2); + ctx->heattable_v2 = NULL; + } + + ctx->heattable_buf = malloc(HEATTABLE_V2_MAX_SIZE); + if (!ctx->heattable_buf) { + ERROR("Memory allocation failed!\n"); + return CUPS_BACKEND_FAILED; + } + snprintf(full, sizeof(full), "%s/%s", corrtable_path, fname); + ret = dyesub_read_file(full, ctx->heattable_buf, HEATTABLE_V2_MAX_SIZE, &len); + if (ret) { + return ret; + } + hdr = (struct hiti_heattable_hdr_v2 *) ctx->heattable_buf; + + ctx->heattable_v2 = malloc(hdr->num_headers * sizeof(struct hiti_heattable_v2)); + if (!ctx->heattable_buf) { + ERROR("Memory allocation failed!\n"); + return CUPS_BACKEND_FAILED; + } + + ctx->num_heattable_entries = hdr->num_headers; + + for (i = 0 ; i < hdr->num_headers ; i++) { + DEBUG("Found: %04x %02x @ %d\n", + le16_to_cpu(hdr->entries[i].type), + hdr->entries[i].unknown, + le32_to_cpu(hdr->entries[i].offset)); + + ctx->heattable_v2[i].type = le16_to_cpu(hdr->entries[i].type); + ctx->heattable_v2[i].data = ctx->heattable_buf + hdr->entries[i].offset; + if (i > 0) { + ctx->heattable_v2[i-1].len = le32_to_cpu(hdr->entries[i].offset) - le32_to_cpu(hdr->entries[i-1].offset); + } + } + ctx->heattable_v2[i-1].len = len - le32_to_cpu(hdr->entries[i-1].offset); + + return CUPS_BACKEND_OK; +}; static const char *hiti_prefixes[] = { "hiti", // Family name diff --git a/hiti_data/README-hiti-data b/hiti_data/README-hiti-data index 02cfae3..a82ae27 100644 --- a/hiti_data/README-hiti-data +++ b/hiti_data/README-hiti-data @@ -7,7 +7,7 @@ LUT filename Codes: C M Q P ? ra [ .bin ] -- model code, see below - media version, 0..n (if not present, interpret as 0) - - ?? (usually P, but also seen B, C, CL, I) + - ?? (usually P, but also seen B, C, CL, I, SO) - print quality, Q == fine, P == normal - media type, M == DNP, C == CHC (?) - ?? (usually C, also seen RC) @@ -29,15 +29,13 @@ Heat table codes: hea 0 q c ra [.bin] -- model code, see above - - media type, h == DNP, c == CHC (?) + - media type, h == DNP, c == CHC - print quality, q == fine, t == normal, (also seen p/r/o == ?) - media version, 0..n (or 't') --- always 'hea' Heat table types: - size - 11108 ra (older) SEHT2 * 5 (Y + M + C + Gloss + Matte) 256 doubles @@ -46,11 +44,6 @@ Heat table types: CVD 582 bytes 26 bytes pad - 12568 ?? rd(qc/qh/pc/ph) / rh(qc) /rk/ri/ri1 - these printers use ESD_SHPTC and ~7KB payload. - - 12603 ?? rd(qc) - 12753 ?? cd(ph) / cm cm(ph) 12917 ra (newer) SEHT2 * 6 (Y + M + C + OG + OM + UNK ?) 5 byte header @@ -59,6 +52,51 @@ Heat table types: CVD 5 byte header 582 bytes + + 12568 ?? rd(qc/qh/pc/ph) / rh(qc) /rk/ri/ri1 + these printers use ESD_SHPTC and ~7KB payload. + 12603 ?? rd(qc) 15732 ?? rd(th) / rh(pc/tc) + + 12753 ?? cd(ph) / cm cm(ph) 58170 ?? cd(oh/th) 77996 ?? cl / cm(oh/th) + +These are more complex. Data format: + +XX Number of data blobs, followed by XX headers: +NN NN MM ZZ ZZ OO OO OO OO +| | | \---------- 32-bit offset from file start (LE) +| | \---------------- Zero +| \------------------- Unknown +\------------------------- 16-bit Block type (LE) + + Observed block types, and guesses + + NNNN MM Length Meaning + + 0250 00 4 + 0251 00 4 + 0501 01 522 Y ? + 0502 01 522 M ? + 0503 01 522 C ? + 0520 01 522 O ? + 0522 01 522 OM ? + 2340 01 582 CVD data + 0180 05 2562 + 0181 05 2562 + 0182 05 2562 + 02af 03 1540 + 02ae 03 1540 + 02a7 03 1540 + 02a8 03 1540 + 0cbf 00 24 + 0cbe 00 24 + 0cb7 00 24 + 0cb8 00 24 + 0d90 00 26 + + 01f0 00 2 <- c? only + 18de 00 12732 <- c? only + 1900 2f 24114 <- c? only + 7520 42 34056 <- c? only