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.
This commit is contained in:
Solomon Peachy 2022-06-26 00:47:06 -04:00
parent da2a15df6a
commit a809283189
2 changed files with 177 additions and 70 deletions

View File

@ -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,6 +1359,56 @@ static int hiti_cvd(struct hiti_ctx *ctx, uint8_t *buf, uint32_t buf_len)
return ret;
}
static const char* hiti_get_heat_file(struct hiti_ctx *ctx, uint8_t mode)
{
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) {
case P_HITI_51X:
if (!mediatype) { /* DNP media */
if (mode) {
return "P51x_heatqhra.bin";
} else {
return "P51x_heatthra.bin";
}
} else { /* CHC media */
if (mode) {
switch(mediaver) {
case 0:
return "P51x_hea0qcra.bin";
case 1:
return "P51x_hea1qcra.bin";
case 2:
return "P51x_hea2qcra.bin";
case 3:
default:
return "P51x_hea3qcra.bin";
}
} else {
switch(mediaver) {
case 0:
return "P51x_hea0tcra.bin";
case 1:
return "P51x_hea1tcra.bin";
case 2:
return "P51x_hea2tcra.bin";
case 3:
default:
return "P51x_hea3tcra.bin";
}
}
}
break;
case P_HITI_52X:
case P_HITI_720:
default:
return NULL;
}
}
static int hiti_send_heat_data(struct hiti_ctx *ctx, uint8_t mode, uint8_t matte)
{
const char *fname = NULL;
@ -1347,64 +1420,8 @@ static int hiti_send_heat_data(struct hiti_ctx *ctx, uint8_t mode, uint8_t matte
int ret, len;
int mediaver = ctx->ribbonvendor & 0x3f;
int mediatype = ((ctx->ribbonvendor & 0xf000) == 0x1000);
fname = hiti_get_heat_file(ctx, mode);
// XXX if field_0x70 != 100) send blank/empty tables..
// no idea what sets this field.
switch (ctx->conn->type)
{
case P_HITI_51X:
if (!mediatype) { /* DNP media */
if (mode) {
fname = "P51x_heatqhra.bin";
break;
} else {
fname = "P51x_heatthra.bin";
break;
}
} else { /* CHC media */
if (mode) {
switch(mediaver) {
case 0:
fname = "P51x_hea0qcra.bin";
break;
case 1:
fname = "P51x_hea1qcra.bin";
break;
case 2:
fname = "P51x_hea2qcra.bin";
break;
case 3:
default:
fname = "P51x_hea3qcra.bin";
break;
}
} else {
switch(mediaver) {
case 0:
fname = "P51x_hea0tcra.bin";
break;
case 1:
fname = "P51x_hea1tcra.bin";
break;
case 2:
fname = "P51x_hea2tcra.bin";
break;
case 3:
default:
fname = "P51x_hea3tcra.bin";
break;
}
}
}
break;
case P_HITI_52X:
case P_HITI_720:
default:
fname = NULL;
break;
}
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

View File

@ -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