From f4ebf1ac62f52d4403cc534ad79c942c9e9a573c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 29 Aug 2024 10:38:19 -0400 Subject: [PATCH] lib2245: Basic handling of the Kodak 6900 IPP data. IPP data is now parsed and validated, and we can successfully complete an ip_imageProc() run. Unfortunately this is still insufficient: * Additional fields in IppConf header not yet handled (some are recognized/known) * Printer requires additonal data to be sent over: * 12 additional rows per plane (beyond the size in the print cmd) * 9856 bytes of additional info (partial IPP headers plus ???) * ip_getMemorySize() needs to take all of this into account * Panorama processing adds another layer of fun on top of that. --- lib2245/libS2245ImageReProcess.c | 199 +++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 50 deletions(-) diff --git a/lib2245/libS2245ImageReProcess.c b/lib2245/libS2245ImageReProcess.c index 102e88b..08a06dd 100644 --- a/lib2245/libS2245ImageReProcess.c +++ b/lib2245/libS2245ImageReProcess.c @@ -2,7 +2,7 @@ libS2245ImageReProcess -- Re-implemented Image Processing library for the Sinfonia CHC-S2245 printer family - Copyright (c) 2021 Solomon Peachy + Copyright (c) 2021-2024 Solomon Peachy ** ** ** ** Do NOT contact Sinfonia about this library! ** ** ** ** @@ -39,7 +39,7 @@ */ -#define LIB_VERSION "0.1.2" +#define LIB_VERSION "0.1.3" #include #include @@ -83,6 +83,8 @@ bool ip_getMemorySize(uint32_t *szMemory, //------------------------------------------------------------------------- // External data formats +#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed") + struct ippHeatCorr { int32_t tankDivisor[4]; int32_t tankRowInitVals[4]; @@ -118,6 +120,8 @@ struct SIppData { uint8_t sideEdgeCorrectionTable[256]; } __attribute__((packed)); +STATIC_ASSERT(sizeof(struct SIppData) == 2524); + struct ippHeader { char model[16]; char ipp[4]; @@ -125,6 +129,8 @@ struct ippHeader { uint8_t pad_0x15[43]; } __attribute__((packed)); +STATIC_ASSERT(sizeof(struct ippHeader) == 64); + struct ippConf { uint16_t width; /* Overridden at runtime */ uint16_t height; /* Overridden at runtime */ @@ -136,19 +142,58 @@ struct ippConf { uint8_t borderCapable; // 0x02 if we can do 5x7-on-6x8 uint8_t pad_0xb[21]; uint8_t planeOrder[16]; - uint8_t pad_0x30[16]; + uint8_t pad_0x20[16]; } __attribute__((packed)); +STATIC_ASSERT(sizeof(struct ippConf) == 64); + struct ippData { - struct ippHeader header; - struct ippConf conf; - struct SIppData plane_rc; +/*@00*/ struct ippHeader header; +/*@40*/ struct ippConf conf; +/*@80*/ struct SIppData plane_rc; struct SIppData plane_gm; struct SIppData plane_by; struct SIppData plane_oc; - // Can have up to 16 planes, think about this. } __attribute__((packed)); +STATIC_ASSERT(sizeof(struct ippData) == 10224); + +struct ippConfKA { + uint16_t width; /* Overridden at runtime */ + uint16_t height; /* Overridden at runtime */ + uint16_t headWidth; // Always 1920 + uint8_t planes; // 3 or 4, can be up to 16! + uint8_t printmode; // Corresponds to corrdata_req field 1 + uint8_t corrections1; // Corresponds to corrdata_req field 2 + uint8_t corrections2; // B0,B1,B2 + uint8_t borderCapable; // 0x02 if we can do 5x7-on-6x8 + uint8_t pad_0xb[21]; + uint8_t planeOrder[16]; + uint8_t num_panels; /* 0x01-0x03 ? */ + uint8_t unk_0x21; /* 0x06 in IPP, 0x00 or 0x01 in cmd */ + uint16_t unk_0x22; /* 0x0032 */ + uint16_t max_panel_overlap; /* 0x0258 == 600d */ + uint16_t panel_rows[3]; /* */ + uint16_t lam_rows[3]; /* */ + uint16_t unk_0x42[31]; +} __attribute__((packed)); + +STATIC_ASSERT(sizeof(struct ippConfKA) == 128); /* KA6900 */ + +struct ippDataKA { +/*@00*/ struct ippHeader header; +/*@40*/ struct ippConfKA conf; +/*@c0*/ struct SIppData plane_rc; + struct SIppData plane_gm; + struct SIppData plane_by; + struct SIppData plane_oc; + uint8_t pad[7680]; /* @ 10288 */ +} __attribute__((packed)); + +STATIC_ASSERT(sizeof(struct ippDataKA) == 17968); + +#undef STATIC_ASSERT + //------------------------------------------------------------------------- // Private Structures @@ -173,14 +218,15 @@ struct CHeatCorrProc { struct CIppMng { struct ippHeader header; - struct ippConf conf; + struct ippConfKA conf; struct SIppData *ippData; uint8_t initialized; + uint8_t ka6900; }; struct CImageProc { struct CIppMng *ippMng; - struct ippConf conf; + struct ippConfKA conf; struct SIppData planeIPPdata; uint32_t pixelsOCG; // width*height*3 uint32_t pixelsOCM; // width*height*4 @@ -228,13 +274,6 @@ struct pic_data { uint8_t bytes_pp; }; -// Data format Sanity checks -#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed") - -STATIC_ASSERT(sizeof(struct ippData) == 10224); - -#undef STATIC_ASSERT - //------------------------------------------------------------------------- // Private data declarations @@ -257,30 +296,47 @@ static void CIppMng_Cleanup(struct CIppMng *this) } static const char s2245HeaderModel[] = "CHC-S2245 "; -static const char s2245IppStr[] = "IPP="; +static const char ka6900HeaderModel[] = "KA6900 "; +static const char ippStr[] = "IPP="; -static bool CIppMng_CheckHeader(struct CIppMng *this, struct ippData *ippData) +static bool CIppMng_CheckHeader(struct CIppMng *this, void *ippData) { - memcpy(&this->header, &ippData->header, sizeof(this->header)); + memcpy(&this->header, ippData, sizeof(this->header)); - if (memcmp(this->header.model, s2245HeaderModel, 16)) - return 0; - if (memcmp(this->header.ipp, s2245IppStr, 4)) - return 0; - if (this->header.version != 0x3) + if (this->ka6900) { + if (memcmp(this->header.model, ka6900HeaderModel, 16)) + return 0; + } else { + if (memcmp(this->header.model, s2245HeaderModel, 16)) + return 0; + } + if (memcmp(this->header.ipp, ippStr, 4)) return 0; + if (this->ka6900) { + if (this->header.version != 0x7) + return 0; + } else { + if (this->header.version != 0x3) + return 0; + } return 1; } -static bool CIppMng_CheckConf(struct CIppMng *this, struct ippData *ippData) +static bool CIppMng_CheckConf(struct CIppMng *this, void *ippData) { uint8_t tmp; #ifndef USE_EXTRA_STUFF - memcpy(&this->conf, &ippData->conf, sizeof(this->conf)); + if (this->ka6900) { + struct ippDataKA *data = ippData; + memcpy(&this->conf, &data->conf, sizeof(this->conf)); + } else { + struct ippData *data = ippData; + memcpy(&this->conf, &data->conf, sizeof(this->conf)); + } #else (void)ippData; #endif @@ -298,40 +354,62 @@ static bool CIppMng_CheckConf(struct CIppMng *this, struct ippData *ippData) if (tmp > 1) return 0; + // XXX anything else for KA6900? + return 1; } -static bool CIppMng_CheckIpp(struct CIppMng *this, struct ippData *ippData) +static bool CIppMng_CheckIpp(struct CIppMng *this, void *ippData) { bool rval; rval = CIppMng_CheckHeader(this, ippData); - if (rval) rval = CIppMng_CheckConf(this, ippData); return rval; } -static bool CIppMng_SetConf(struct CIppMng *this, struct ippData *ippData, +static bool CIppMng_SetConf(struct CIppMng *this, void *ippData, uint16_t width, uint16_t height) { - memcpy(&this->conf, &ippData->conf, sizeof(this->conf)); + if (!memcmp(ippData, ka6900HeaderModel, sizeof(ka6900HeaderModel)-1)) + this->ka6900 = 1; if (!width || !height) return 0; + + if (this->ka6900) { + struct ippDataKA *data = ippData; + memcpy(&this->conf, &data->conf, sizeof(this->conf)); + } else { + struct ippData *data = ippData; + memcpy(&this->conf, &data->conf, sizeof(this->conf)); + memset(&this->conf + sizeof(data->conf), 0, sizeof(this->conf) - sizeof(data->conf)); + } + this->conf.width = width; this->conf.height = height; #if (__BYTE_ORDER != __LITTLE_ENDIAN) this->conf.headWidth = le16_to_cpu(this->conf.headWidth); #endif + if (this->ka6900) { + this->conf.max_panel_overlap = le16_to_cpu(this->conf.max_panel_overlap); + this->conf.unk_0x22 = le16_to_cpu(this->conf.unk_0x22); // XXX + for (int i = 0 ; i < 3 ; i++) { + this->conf.panel_rows[i] = le16_to_cpu(this->conf.panel_rows[i]); + this->conf.lam_rows[i] = le16_to_cpu(this->conf.lam_rows[i]); + } + // XXX additional fields. + } + return 1; } -static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData) +static bool CIppMng_SetData(struct CIppMng *this, void *ippData) { if (this->ippData) @@ -344,19 +422,26 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData) if (!this->ippData) return 0; - memcpy(this->ippData, &ippData->plane_rc, this->conf.planes * sizeof(*this->ippData)); + if (this->ka6900) { + struct ippDataKA *data = ippData; + memcpy(this->ippData, &data->plane_rc, this->conf.planes * sizeof(*this->ippData)); + } else { + struct ippData *data = ippData; + memcpy(this->ippData, &data->plane_rc, this->conf.planes * sizeof(*this->ippData)); + } #if (__BYTE_ORDER != __LITTLE_ENDIAN) -#define SWAP16(__x) __x = le16_to_cpu(ippBlock->__x) -#define SWAP32(__x) __x = le32_to_cpu(ippBlock->__x) +#define swap16(__x) ippBlock->__x = le16_to_cpu(ippBlock->__x) +#define swap32(__x) ippBlock->__x = le32_to_cpu(ippBlock->__x) + int i, j; for (i = 0 ; i < this->conf.planes ; i++) { - struct SIppData *ippBlock = &ippData->plane_rc + i; + struct SIppData *ippBlock = &this->ippData[i]; swap16(field_0x0); swap16(field_0x2); swap16(maxLineSum); swap16(minRowSum); - swap16(maxLineCorrecitonFactor); + swap16(maxLineCorrectionFactor); swap16(nextWeight); swap16(prevWeight); swap16(mtfPreCalcCutoff); @@ -365,7 +450,7 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData) swap16(pulseExMap[j]); swap16(heatCorrectionMinusTable[j]); swap16(heatCorrectionPlusTable[j]); - swap16(lineCorrection); + swap16(lineCorrection[j]); } for (j = 0 ; j < 4 ; j++) { swap32(heatCorrection.tankDivisor[j]); @@ -375,20 +460,20 @@ static bool CIppMng_SetData(struct CIppMng *this, struct ippData *ippData) for (j = 0 ; j < 5 ; j++) { swap32(heatCorrection.tankCoef[j]); } - swap32(tankPlusParam); - swap32(tankMinusParam); - swap32(tankPlusLimit); - swap32(tankMinusLimit); - swap32(useHeatCorrection); + swap32(heatCorrection.tankPlusParam); + swap32(heatCorrection.tankMinusParam); + swap32(heatCorrection.tankPlusLimit); + swap32(heatCorrection.tankMinusLimit); + swap32(heatCorrection.useHeatCorrection); } -#undef SWAP16 -#undef SWAP32 +#undef swap16 +#undef swap32 #endif return 1; } -static bool CIppMng_SetIPP(struct CIppMng *this, struct ippData *ippData, +static bool CIppMng_SetIPP(struct CIppMng *this, void *ippData, uint16_t width, uint16_t height) { @@ -418,7 +503,7 @@ static bool CIppMng_GetNumOfColor(struct CIppMng *this, uint8_t *planesOCG, uint return 1; } -static bool CIppMng_GetIppConf(struct CIppMng *this, struct ippConf *conf, +static bool CIppMng_GetIppConf(struct CIppMng *this, struct ippConfKA *conf, uint8_t *planesOCG, uint8_t *planesOCM) { @@ -1707,22 +1792,36 @@ bool ip_getMemorySize(uint32_t *szMemory, uint16_t width, uint16_t height, void *srcIpp) { - struct ippData *ippData; + struct CIppMng ippMng; uint32_t pixels; if (!width || !height || !szMemory || !srcIpp) return 0; - ippData = srcIpp; + CIppMng_Init(&ippMng); - if ((ippData->conf.borderCapable == 0x02) && +#ifdef USE_EXTRA_STUFF + int rval = CIppMng_SetConf(&ippMng, srcIpp, width, height); +#else + int rval = CIppMng_CheckIpp(&ippMng, srcIpp); +#endif + if (!rval) { + CIppMng_Cleanup(&ippMng); + return 0; + } + + // XXX KA6900 needs this to be rewritten heavily. + + if ((ippMng.conf.borderCapable == 0x02) && (width == 1548) && (height == 2140)) { pixels = 2434*1844; /* ie 8x6 */ } else { pixels = height * width; } - *szMemory = pixels * 2 * ippData->conf.planes; + *szMemory = pixels * 2 * ippMng.conf.planes; + + CIppMng_Cleanup(&ippMng); if (!*szMemory) return 0;