diff options
author | Didier Raboud <odyx@debian.org> | 2016-11-01 18:45:10 +0100 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2016-11-01 18:45:10 +0100 |
commit | 54a135b87201e48d4da4894a61b81a8c6fe46d26 (patch) | |
tree | 74b42137b1e3eb634c01cb593469dddc727cd124 /src/cups/backend_mitsu70x.c | |
parent | d69d392d8c45cdcc93e58f0e1bdbb2b66d6b9566 (diff) |
New upstream version 5.2.12~pre4
Diffstat (limited to 'src/cups/backend_mitsu70x.c')
-rw-r--r-- | src/cups/backend_mitsu70x.c | 522 |
1 files changed, 280 insertions, 242 deletions
diff --git a/src/cups/backend_mitsu70x.c b/src/cups/backend_mitsu70x.c index 9a94a32..16099ba 100644 --- a/src/cups/backend_mitsu70x.c +++ b/src/cups/backend_mitsu70x.c @@ -35,10 +35,76 @@ #include <fcntl.h> #include <signal.h> +/* For Integration into gutenprint */ +#if defined(HAVE_CONFIG_H) +#include <config.h> +#endif + +#if defined(USE_DLOPEN) +#define WITH_DYNAMIC +#include <dlfcn.h> +#define DL_INIT() do {} while(0) +#define DL_OPEN(__x) dlopen(__x, RTLD_NOW) +#define DL_SYM(__x, __y) dlsym(__x, __y) +#define DL_CLOSE(__x) dlclose(__x) +#define DL_EXIT() do {} while(0) +#elif defined(USE_LTDL) +#define WITH_DYNAMIC +#include <ltdl.h> +#define DL_INIT() lt_dlinit() +#define DL_OPEN(__x) lt_dlopen(__x) +#define DL_SYM(__x, __y) lt_dlsym(__x, __y) +#define DL_CLOSE(__x) do {} while(0) +#define DL_EXIT() lt_dlexit() +#else +#define DL_INIT() do {} while(0) +#define DL_CLOSE(__x) do {} while(0) +#define DL_EXIT() do {} while(0) +#warning "No dynamic loading support!" +#endif + #define BACKEND mitsu70x_backend #include "backend_common.h" +// #include "lib70x/libMitsuD70ImageReProcess.h" + +#ifndef LUT_LEN +#define COLORCONV_RGB 0 +#define COLORCONV_BGR 1 + +#define LUT_LEN 14739 +struct BandImage { + void *imgbuf; + int32_t bytes_per_row; + uint16_t origin_cols; + uint16_t origin_rows; + uint16_t cols; + uint16_t rows; +}; +#endif + +/* Image processing library function prototypes */ +#define LIB_NAME_RE "libMitsuD70ImageReProcess.so" // Reimplemented library + +typedef int (*Get3DColorTableFN)(uint8_t *buf, const char *filename); +typedef struct CColorConv3D *(*Load3DColorTableFN)(const uint8_t *ptr); +typedef void (*Destroy3DColorTableFN)(struct CColorConv3D *this); +typedef void (*DoColorConvFN)(struct CColorConv3D *this, uint8_t *data, uint16_t cols, uint16_t rows, uint32_t bytes_per_row, int rgb_bgr); +typedef struct CPCData *(*get_CPCDataFN)(const char *filename); +typedef void (*destroy_CPCDataFN)(struct CPCData *data); +typedef int (*do_image_effectFN)(struct CPCData *cpc, struct BandImage *input, struct BandImage *output, int sharpen, uint8_t rew[2]); +typedef int (*send_image_dataFN)(struct BandImage *out, void *context, + int (*callback_fn)(void *context, void *buffer, uint32_t len)); + +#ifndef CORRTABLE_PATH +#ifdef PACKAGE_DATA_DIR +#define CORRTABLE_PATH PACKAGE_DATA_DIR "/backend_data" +#else +#error "Must define CORRTABLE_PATH or PACKAGE_DATA_DIR!" +#endif +#endif + #define USB_VID_MITSU 0x06D3 #define USB_PID_MITSU_D70X 0x3B30 #define USB_PID_MITSU_K60 0x3B31 @@ -48,15 +114,8 @@ //#define USB_VID_FUJIFILM XXXXXX //#define USB_PID_FUJI_ASK300 XXXXXX -//#define ENABLE_CORRTABLES - -#ifndef CORRTABLE_PATH -#define CORRTABLE_PATH "D70" -#endif - -#ifdef ENABLE_CORRTABLES -#include "D70/Mitsu_D70.c" -#endif +/* Width of the laminate data file */ +#define LAMINATE_STRIDE 1864 /* Private data stucture */ struct mitsu70x_ctx { @@ -80,18 +139,31 @@ struct mitsu70x_ctx { int supports_jobs_query; -#ifdef ENABLE_CORRTABLES char *laminatefname; char *lutfname; char *cpcfname; - struct CColorConv3D lut; - struct CPCData cpcdata; + void *dl_handle; + Get3DColorTableFN Get3DColorTable; + Load3DColorTableFN Load3DColorTable; + Destroy3DColorTableFN Destroy3DColorTable; + DoColorConvFN DoColorConv; + get_CPCDataFN GetCPCData; + destroy_CPCDataFN DestroyCPCData; + do_image_effectFN DoImageEffect; + send_image_dataFN SendImageData; + + struct CColorConv3D *lut; + struct CPCData *cpcdata; char *last_cpcfname; int raw_format; -#endif + int sharpen; /* ie mhdr.sharpen - 1 */ + + uint8_t rew[2]; /* 1 for rewind ok (default!) */ + + struct BandImage output; }; /* Printer data structures */ @@ -257,10 +329,13 @@ struct mitsu70x_memorystatus_resp { uint8_t rsvd; } __attribute__((packed)); +// XXX also seen commands 0x67, 0x72, 0x54, 0x6e + struct mitsu70x_hdr { - uint8_t hdr[4]; /* 1b 5a 54 XX */ + uint8_t hdr[4]; /* 1b 5a 54 XX */ // XXX also, seen 1b 5a 43! uint16_t jobid; - uint8_t zero0[10]; + uint8_t rewind[2]; /* XXX K60/EK305/D80 only, 0 normally, 1 for "skip" ??? */ + uint8_t zero0[8]; uint16_t cols; uint16_t rows; @@ -272,11 +347,12 @@ struct mitsu70x_hdr { uint8_t deck; /* 0 = default, 1 = lower, 2 = upper */ uint8_t zero2[7]; uint8_t laminate; /* 00 == on, 01 == off */ - uint8_t laminate_mode; + uint8_t laminate_mode; /* 00 == glossy, 02 == matte */ uint8_t zero3[6]; uint8_t multicut; - uint8_t zero4[13]; + uint8_t zero4[12]; + uint8_t sharpen; /* 0-9. 5 is "normal", 0 is "off" */ uint8_t mode; /* 0 for cooked YMC planar, 1 for packed BGR */ uint8_t use_lut; /* in BGR mode, 0 disables, 1 enables */ @@ -536,6 +612,8 @@ static void *mitsu70x_init(void) } memset(ctx, 0, sizeof(struct mitsu70x_ctx)); + DL_INIT(); + return ctx; } @@ -567,6 +645,36 @@ static void mitsu70x_attach(void *vctx, struct libusb_device_handle *dev, ctx->supports_jobs_query = 0; else ctx->supports_jobs_query = 1; + + /* Attempt to open the library */ +#if defined(WITH_DYNAMIC) + INFO("Attempting to load image processing library\n"); + ctx->dl_handle = DL_OPEN(LIB_NAME_RE); + if (!ctx->dl_handle) + WARNING("Image processing library not found, using internal fallback code\n"); + if (ctx->dl_handle) { + ctx->Get3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Get3DColorTable"); + ctx->Load3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Load3DColorTable"); + ctx->Destroy3DColorTable = DL_SYM(ctx->dl_handle, "CColorConv3D_Destroy3DColorTable"); + ctx->DoColorConv = DL_SYM(ctx->dl_handle, "CColorConv3D_DoColorConv"); + ctx->GetCPCData = DL_SYM(ctx->dl_handle, "get_CPCData"); + ctx->DestroyCPCData = DL_SYM(ctx->dl_handle, "destroy_CPCData"); + ctx->DoImageEffect = DL_SYM(ctx->dl_handle, "do_image_effect"); + ctx->SendImageData = DL_SYM(ctx->dl_handle, "send_image_data"); + if (!ctx->Get3DColorTable || !ctx->Load3DColorTable || + !ctx->Destroy3DColorTable || !ctx->DoColorConv || + !ctx->GetCPCData || !ctx->DestroyCPCData || + !ctx->DoImageEffect || !ctx->SendImageData) { + WARNING("Problem resolving symbols in imaging processing library\n"); + DL_CLOSE(ctx->dl_handle); + ctx->dl_handle = NULL; + } else { + INFO("Image processing library successfully loaded\n"); + } + } +#else + WARNING("Dynamic library support not enabled, using internal fallback code\n"); +#endif } static void mitsu70x_teardown(void *vctx) { @@ -578,6 +686,16 @@ static void mitsu70x_teardown(void *vctx) { if (ctx->databuf) free(ctx->databuf); + if (ctx->dl_handle) { + if (ctx->cpcdata) + ctx->DestroyCPCData(ctx->cpcdata); + if (ctx->lut) + ctx->Destroy3DColorTable(ctx->lut); + DL_CLOSE(ctx->dl_handle); + } + + DL_EXIT(); + free(ctx); } @@ -596,6 +714,8 @@ static int mitsu70x_read_parse(void *vctx, int data_fd) { } ctx->matte = 0; + ctx->rew[0] = 1; + ctx->rew[1] = 1; repeat: /* Read in initial header */ @@ -625,7 +745,6 @@ repeat: return CUPS_BACKEND_CANCEL; } -#ifdef ENABLE_CORRTABLES ctx->raw_format = !mhdr.mode; /* Figure out the correction data table to use */ @@ -640,6 +759,10 @@ repeat: } else { ctx->cpcfname = CORRTABLE_PATH "/CPD70N01.cpc"; } + if (mhdr.hdr[3] != 0x01) { + WARNING("Print job has wrong submodel specifier (%x)\n", mhdr.hdr[3]); + mhdr.hdr[3] = 0x01; + } } else if (ctx->type == P_MITSU_D80) { ctx->laminatefname = CORRTABLE_PATH "/D80MAT01.raw"; ctx->lutfname = CORRTABLE_PATH "/CPD80L01.lut"; @@ -652,6 +775,10 @@ repeat: ctx->cpcfname = CORRTABLE_PATH "/CPD80N01.cpc"; } // XXX what about CPD80**E**01? + if (mhdr.hdr[3] != 0x01) { + WARNING("Print job has wrong submodel specifier (%x)\n", mhdr.hdr[3]); + mhdr.hdr[3] = 0x01; + } } else if (ctx->type == P_MITSU_K60) { ctx->laminatefname = CORRTABLE_PATH "/S60MAT02.raw"; ctx->lutfname = CORRTABLE_PATH "/CPS60L01.lut"; @@ -662,6 +789,10 @@ repeat: } else { ctx->cpcfname = CORRTABLE_PATH "/CPS60T01.cpc"; } + if (mhdr.hdr[3] != 0x00) { + WARNING("Print job has wrong submodel specifier (%x)\n", mhdr.hdr[3]); + mhdr.hdr[3] = 0x00; + } } else if (ctx->type == P_KODAK_305) { ctx->laminatefname = CORRTABLE_PATH "/EK305MAT.raw"; // Same as K60 ctx->lutfname = CORRTABLE_PATH "/EK305L01.lut"; @@ -672,7 +803,11 @@ repeat: } else { ctx->cpcfname = CORRTABLE_PATH "/EK305T01.cpc"; } - + // XXX what about using K60 media if we read back the proper code? + if (mhdr.hdr[3] != 0x90) { + WARNING("Print job has wrong submodel specifier (%x)\n", mhdr.hdr[3]); + mhdr.hdr[3] = 0x90; + } } else if (ctx->type == P_FUJI_ASK300) { ctx->laminatefname = CORRTABLE_PATH "/ASK300M2.raw"; // Same as D70 ctx->lutfname = CORRTABLE_PATH "/CPD70L01.lut"; // XXX guess, driver did not come with external LUT! @@ -682,14 +817,20 @@ repeat: } else { ctx->cpcfname = CORRTABLE_PATH "/ASK300T1.cpc"; } + if (mhdr.hdr[3] != 0x01) { + WARNING("Print job has wrong submodel specifier (%x)\n", mhdr.hdr[3]); + mhdr.hdr[3] = 0x01; + } } if (!mhdr.use_lut) ctx->lutfname = NULL; + ctx->sharpen = mhdr.sharpen - 1; + /* Clean up header back to pristine. */ mhdr.use_lut = 0; mhdr.mode = 0; -#endif + mhdr.sharpen = 0; /* Work out total printjob size */ ctx->cols = be16_to_cpu(mhdr.cols); @@ -707,7 +848,8 @@ repeat: remain = 3 * planelen + ctx->matte; ctx->datalen = 0; - ctx->databuf = malloc(sizeof(mhdr) + remain); + ctx->databuf = malloc(sizeof(mhdr) + remain + LAMINATE_STRIDE*2); /* Give us a bit extra */ + if (!ctx->databuf) { ERROR("Memory allocation failure!\n"); return CUPS_BACKEND_FAILED; @@ -716,9 +858,7 @@ repeat: memcpy(ctx->databuf + ctx->datalen, &mhdr, sizeof(mhdr)); ctx->datalen += sizeof(mhdr); -#ifdef ENABLE_CORRTABLES if (ctx->raw_format) { /* RAW MODE */ -#endif DEBUG("Reading in %d bytes of 16bpp YMCL data\n", remain); /* Read in the spool data */ @@ -731,7 +871,6 @@ repeat: ctx->datalen += i; remain -= i; } -#ifdef ENABLE_CORRTABLES } else { /* RAW MODE OFF */ int spoolbuflen = 0; uint8_t *spoolbuf; @@ -757,90 +896,109 @@ repeat: } /* Run through basic LUT, if present and enabled */ - if (ctx->lutfname) { + if (ctx->dl_handle && ctx->lutfname && !ctx->lut) { /* printer-specific, it is fixed per-job */ DEBUG("Running print data through LUT\n"); uint8_t *buf = malloc(LUT_LEN); if (!buf) { ERROR("Memory allocation failure!\n"); return CUPS_BACKEND_FAILED; } - if (CColorConv3D_Get3DColorTable(buf, ctx->lutfname)) { + if (ctx->Get3DColorTable(buf, ctx->lutfname)) { ERROR("Unable to open LUT file '%s'\n", ctx->lutfname); return CUPS_BACKEND_CANCEL; } - CColorConv3D_Load3DColorTable(&ctx->lut, buf); + ctx->lut = ctx->Load3DColorTable(buf); free(buf); - CColorConv3D_DoColorConv(&ctx->lut, spoolbuf, ctx->cols, ctx->rows, ctx->cols * 3, 1); - // XXX proprietary lib also does gamma+contrast+brightness + if (!ctx->lut) { + ERROR("Unable to parse LUT file '%s'!\n", ctx->lutfname); + return CUPS_BACKEND_CANCEL; + } + ctx->DoColorConv(ctx->lut, spoolbuf, ctx->cols, ctx->rows, ctx->cols * 3, COLORCONV_BGR); } /* Load in the CPC file, if needed! */ - if (ctx->cpcfname && ctx->cpcfname != ctx->last_cpcfname) { - ctx->last_cpcfname = ctx->cpcfname; - if (load_CPCData(&ctx->cpcdata, ctx->cpcfname)) { - ERROR("Unable to load CPC file '%s'\n", ctx->cpcfname); - return CUPS_BACKEND_CANCEL; + if (ctx->dl_handle) { + struct BandImage input; + + if (ctx->cpcfname && ctx->cpcfname != ctx->last_cpcfname) { + ctx->last_cpcfname = ctx->cpcfname; + if (ctx->cpcdata) + ctx->DestroyCPCData(ctx->cpcdata); + ctx->cpcdata = ctx->GetCPCData(ctx->cpcfname); + if (!ctx->cpcdata) { + ERROR("Unable to load CPC file '%s'\n", ctx->cpcfname); + return CUPS_BACKEND_CANCEL; + } } - } - // XXX INSERT ALGORITHM HERE... + /* Convert using image processing library */ - // XXX optionally CreateInkCorrectGammaTable(...) + input.origin_rows = input.origin_cols = 0; + input.rows = ctx->rows; + input.cols = ctx->cols; + input.imgbuf = spoolbuf; + input.bytes_per_row = ctx->cols * 3; - /* Convert to YMC using corrtables (aka CImageEffect70::DoGamma) */ - { - uint32_t r, c; - uint32_t in = 0, out = 0; + ctx->output.origin_rows = ctx->output.origin_cols = 0; + ctx->output.rows = ctx->rows; + ctx->output.cols = ctx->cols; + ctx->output.imgbuf = ctx->databuf + ctx->datalen; + ctx->output.bytes_per_row = ctx->cols * 3 * 2; - uint16_t *offset_y = (uint16_t*)(ctx->databuf + ctx->datalen); - uint16_t *offset_m = offset_y + planelen/2; - uint16_t *offset_c = offset_m + planelen/2; -// uint16_t *offset_l = offset_c + planelen/2; - DEBUG("Running print data through BGR->YMC table (crude)\n"); - for(r = 0 ; r < ctx->rows; r++) { - for (c = 0 ; c < ctx->cols ; c++) { - offset_y[out] = cpu_to_be16(ctx->cpcdata.GNMby[spoolbuf[in]]); - offset_m[out] = cpu_to_be16(ctx->cpcdata.GNMgm[spoolbuf[in + 1]]); - offset_c[out] = cpu_to_be16(ctx->cpcdata.GNMrc[spoolbuf[in + 2]]); - in += 3; - out++; - } + DEBUG("Running print data through processing library\n"); + if (ctx->DoImageEffect(ctx->cpcdata, &input, &ctx->output, ctx->sharpen, ctx->rew)) { + ERROR("Image Processing failed, aborting!\n"); + return CUPS_BACKEND_CANCEL; } + } else { + // XXXFALLBACK write fallback code? + ERROR("!!! Image Processing Library not found, aborting!\n"); + return CUPS_BACKEND_CANCEL; } - // XXX then call CImageEffect70::DoConv(...) to do the final corrections.. - /* Move up the pointer */ + /* Move up the pointer to after the image data */ ctx->datalen += 3*planelen; /* Clean up */ free(spoolbuf); - /* Now that we've filled everything in, read latte from file */ + /* Now that we've filled everything in, read matte from file */ if (ctx->matte) { int fd; - DEBUG("Reading %d bytes of matte data from disk\n", ctx->matte); + uint32_t j; + DEBUG("Reading %d bytes of matte data from disk (%d/%d)\n", ctx->matte, ctx->cols, LAMINATE_STRIDE); fd = open(ctx->laminatefname, O_RDONLY); if (fd < 0) { ERROR("Unable to open matte lamination data file '%s'\n", ctx->laminatefname); return CUPS_BACKEND_CANCEL; } - remain = ctx->matte; - while (remain) { - i = read(fd, ctx->databuf + ctx->datalen, remain); - if (i == 0) { - /* We hit EOF, restart from beginning */ - lseek(fd, 0, SEEK_SET); - continue; + + for (j = 0 ; j < be16_to_cpu(mhdr.lamrows) ; j++) { + remain = LAMINATE_STRIDE * 2; + + /* Read one row of lamination data at a time */ + while (remain) { + i = read(fd, ctx->databuf + ctx->datalen, remain); + if (i < 0) + return CUPS_BACKEND_CANCEL; + if (i == 0) { + /* We hit EOF, restart from beginning */ + lseek(fd, 0, SEEK_SET); + continue; + } + ctx->datalen += i; + remain -= i; } - if (i < 0) - return CUPS_BACKEND_CANCEL; - ctx->datalen += i; - remain -= i; + /* Back off the buffer so we "wrap" on the print row. */ + ctx->datalen -= ((LAMINATE_STRIDE - ctx->cols) * 2); } + + /* Zero out the tail end of the buffer. */ + j = be16_to_cpu(mhdr.lamcols) * be16_to_cpu(mhdr.lamrows) * 2; + memset(ctx->databuf + ctx->datalen, 0, ctx->matte - j); } } -#endif return CUPS_BACKEND_OK; } @@ -1014,7 +1172,7 @@ static int mitsu70x_set_sleeptime(struct mitsu70x_ctx *ctx, uint8_t time) memset(cmdbuf, 0, 4); cmdbuf[0] = 0x1b; cmdbuf[1] = 0x53; - cmdbuf[2] = 0x53; + cmdbuf[2] = 0x53; // XXX also, 0x4e and 0x50 are other params. cmdbuf[3] = time; if ((ret = send_data(ctx->dev, ctx->endp_down, @@ -1032,7 +1190,7 @@ static int mitsu70x_wakeup(struct mitsu70x_ctx *ctx) memset(buf, 0, sizeof(buf)); buf[0] = 0x1b; buf[1] = 0x45; - buf[2] = 0x57; + buf[2] = 0x57; // XXX also, 0x53, 0x54 seen. buf[3] = 0x55; INFO("Waking up printer...\n"); @@ -1043,6 +1201,13 @@ static int mitsu70x_wakeup(struct mitsu70x_ctx *ctx) return 0; } +static int d70_library_callback(void *context, void *buffer, uint32_t len) +{ + struct mitsu70x_ctx *ctx = context; + + return send_data(ctx->dev, ctx->endp_down, buffer, len); +} + static int mitsu70x_main_loop(void *vctx, int copies) { struct mitsu70x_ctx *ctx = vctx; @@ -1175,23 +1340,34 @@ skip_status: hdr->deck = 1; /* All others only have a "lower" deck. */ } + + /* Twiddle rewind stuff if needed */ + if (ctx->type != P_MITSU_D70X) { + hdr->rewind[0] = !ctx->rew[0]; + hdr->rewind[1] = !ctx->rew[1]; + } + /* Matte operation requires Ultrafine/superfine */ if (ctx->matte) { if (ctx->type != P_MITSU_D70X) { - hdr->speed = 0x04; /* Force UltraFine */ + if (hdr->speed != 0x03 && hdr->speed != 0x04) { + WARNING("Forcing Ultrafine mode for matte printing!\n"); + hdr->speed = 0x04; /* Force UltraFine */ + } } else { - hdr->speed = 0x03; /* Force SuperFine */ + if (hdr->speed != 0x03) { + hdr->speed = 0x03; /* Force SuperFine */ + WARNING("Forcing Ultrafine mode for matte printing!\n"); + } } } /* Any other fixups? */ -#if 1 // XXX is this actually needed? if ((ctx->type == P_MITSU_K60 || ctx->type == P_KODAK_305) && ctx->cols == 0x0748 && - ctx->rows == 0x04c2) { - hdr->multicut = 1; // XXX only if print count even? + ctx->rows == 0x04c2 && !hdr->multicut) { + hdr->multicut = 1; } -#endif /* We're clear to send data over! */ INFO("Sending Print Job (internal id %u)\n", ctx->jobid); @@ -1201,11 +1377,17 @@ skip_status: sizeof(struct mitsu70x_hdr)))) return CUPS_BACKEND_FAILED; - { - /* K60 and 305 need data sent in 256K chunks, but the first - chunk needs to subtract the length of the 512-byte header */ + if (ctx->dl_handle && !ctx->raw_format) { + if (ctx->SendImageData(&ctx->output, ctx, d70_library_callback)) + return CUPS_BACKEND_FAILED; + + if (ctx->matte) + if (d70_library_callback(ctx, ctx->databuf + ctx->datalen - ctx->matte, ctx->matte)) + return CUPS_BACKEND_FAILED; + } else { // Fallback code.. + /* K60 and 305 need data sent in 256K chunks, but the first + chunk needs to subtract the length of the 512-byte header */ - // XXX is this special case actually needed? int chunk = 256*1024 - sizeof(struct mitsu70x_hdr); int sent = 512; while (chunk > 0) { @@ -1217,7 +1399,7 @@ skip_status: if (chunk > 256*1024) chunk = 256*1024; } - } + } /* Then wait for completion, if so desired.. */ INFO("Waiting for printer to acknowledge completion\n"); @@ -1277,9 +1459,9 @@ skip_status: jobstatus.job_status[2] || jobstatus.job_status[3]) { ERROR("Abnormal exit: %02x/%02x/%02x\n", - jobstatus.error_status[0], - jobstatus.error_status[1], - jobstatus.error_status[2]); + jobstatus.job_status[1], + jobstatus.job_status[2], + jobstatus.job_status[3]); return CUPS_BACKEND_STOP; } /* Job complete */ @@ -1476,7 +1658,7 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv) /* Exported */ struct dyesub_backend mitsu70x_backend = { .name = "Mitsubishi CP-D70/D707/K60/D80", - .version = "0.43WIP", + .version = "0.51", .uri_prefix = "mitsu70x", .cmdline_usage = mitsu70x_cmdline, .cmdline_arg = mitsu70x_cmdline_arg, @@ -1496,7 +1678,8 @@ struct dyesub_backend mitsu70x_backend = { } }; -/* Mitsubish CP-D70DW/CP-D707DW/CP-K60DW-S/CP-D80DW/Kodak 305 data format +/* Mitsubish CP-D70DW/D707DW/K60DW-S/D80DW, Kodak 305, Fuji ASK-300 + data format: Spool file consists of two headers followed by three image planes and an optional lamination data plane. All blocks are rounded up to @@ -1504,30 +1687,32 @@ struct dyesub_backend mitsu70x_backend = { All multi-byte numbers are big endian, ie MSB first. - Header 1: (Init) (AKA Wake Up) + Header 1: (AKA Wake Up) 1b 45 57 55 00 00 00 00 00 00 00 00 00 00 00 00 (padded by NULLs to a 512-byte boundary) - Header 2: (Header) + Header 2: (Print Header) - 1b 5a 54 PP JJ JJ 00 00 00 00 00 00 00 00 00 00 + 1b 5a 54 PP JJ JJ RR RR 00 00 00 00 00 00 00 00 XX XX YY YY QQ QQ ZZ ZZ SS 00 00 00 00 00 00 00 - UU 00 00 00 00 00 00 00 00 TT 00 00 00 00 00 00 + UU 00 00 00 00 00 00 00 LL TT 00 00 00 00 00 00 RR 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (padded by NULLs to a 512-byte boundary) - PP == 0x01 on D70x/D80, 0x02 on K60, 0x90 on K305 + PP == 0x01 on D70x/D80/ASK300, 0x00 on K60, 0x90 on K305 JJ JJ == Job ID, can leave at 00 00 XX XX == columns YY YY == rows QQ QQ == lamination columns (equal to XX XX) - ZZ ZZ == lamination rows (YY YY + 12) + ZZ ZZ == lamination rows (YY YY + 12 on D70x/D80/ASK300, YY YY on others) + RR RR == "rewind inhibit", 01 01 enabled, normally 00 00 SS == Print mode: 00 = Fine, 03 = SuperFine (D70x/D80 only), 04 = UltraFine (Matte requires Superfine or Ultrafine) UU == 00 = Auto, 01 = Lower Deck (required for !D70x), 02 = Upper Deck - TT == lamination: 00 glossy, 02 matte. + LL == lamination enable, 00 == on, 01 == off + TT == lamination mode: 00 glossy, 02 matte. RR == 00 (normal), 01 = (Double-cut 4x6), 05 = (double-cut 2x6) Data planes: @@ -1536,151 +1721,4 @@ struct dyesub_backend mitsu70x_backend = { Lamination plane: (only present if QQ and ZZ are nonzero) 16-byte data, rounded up to 512-byte block (QQ * ZZ * 2 bytes) - ******************************************************************** - - Command format: - - -> 1b 56 32 30 - <- [256 byte payload] - - PRINTER STATUS - - e4 56 32 30 00 00 00 00 00 00 00 00 00 00 00 00 .V20............ - 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 ................ - 44 80 00 00 5f 00 00 3d 43 00 50 00 44 00 37 00 D..._..=C.P.D.7. - 30 00 44 00 30 00 30 00 31 00 31 00 31 00 37 00 0.D.0.0.1.1.1.7. - 33 31 36 54 31 33 21 a3 33 31 35 42 31 32 f5 e5 316T13!.315B12.. - 33 31 39 42 31 31 a3 fb 33 31 38 45 31 32 50 0d 319B11..318E12P. - 33 31 37 41 32 32 a3 82 44 55 4d 4d 59 40 00 00 317A22..DUMMY@.. - 44 55 4d 4d 59 40 00 00 00 00 00 00 00 00 00 00 DUMMY@.......... - - LOWER DECK STATUS - - 00 00 00 00 00 00 02 04 3f 00 00 04 96 00 00 00 MM MM: media capacity - ff 0f 01 00 MM MM NN NN 00 00 00 00 05 28 75 80 NN NN: prints remaining - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - - alt (some sort of error state) - - 00 00 00 0a 05 05 01 d5 38 00 00 00 14 00 00 00 - ff ff ff ff ff ff ff ff ff ff 00 00 00 27 72 80 - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - - UPPER DECK STATUS (if present) - - XX XX 00 00 00 00 01 ee 3d 00 00 06 39 00 00 00 MM MM: media capacity - ff 02 00 00 MM MM NN NN 00 00 00 00 06 67 78 00 NN NN: prints remaining - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 XX XX: 0x80 00 if no deck - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - - alt (no deck present) - - 80 00 00 00 00 00 00 ff ff 00 00 00 00 00 00 00 - ff ff ff ff ff ff ff ff ff ff 00 00 00 00 80 00 - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 - - -> 1b 56 31 30 00 00 - <- [26 byte payload] - - CP-D707DW: - - e4 56 31 30 00 00 00 XX YY ZZ 00 00 TT 00 00 00 - 00 00 00 00 WW 00 00 00 00 00 - - XX/YY/ZZ and WW/TT are unknown. Observed values: - - 00 00 00 00/00 - 40 80 a0 80/0f - 80 80 a0 - 40 80 90 - 40 80 00 - - also seen: - - e4 56 31 30 00 00 00 00 00 00 00 00 0f 00 00 00 - 00 0a 05 05 80 00 00 00 00 00 - - e4 56 31 30 00 00 00 40 80 90 10 00 0f 00 00 00 - 00 0a 05 05 80 00 00 00 00 00 - - e4 56 31 30 00 00 00 00 40 80 00 00 00 ff 40 00 - 00 00 00 00 80 00 00 00 00 00 - - print just submitted: - - e4 56 31 30 00 00 00 00 40 20 00 00 00 8c 00 00 - 00 00 00 00 80 00 00 00 00 00 - - prints running... - - e4 56 31 30 00 00 00 00 40 20 00 00 00 cf 00 20 - 00 00 00 00 80 00 00 00 00 00 - - CP-K60DW-S: - - e4 56 31 30 00 00 00 XX YY 00 00 00 0f 00 00 00 - 00 00 00 00 80 00 00 00 00 00 - - XX/YY are unknown, observed values: - - 40/80 - 00/00 - - Memory status query: - - -> 1b 56 33 00 XX XX YY YY UU 00 - - XX XX == columns - YY YY == rows - UU == 0x00 glossy, 0x80 matte - - <- [ 6 byte payload ] - - e4 56 33 00 00 00 - e4 56 33 00 00 01 - e4 56 33 ff 01 01 - - |--- Size check, 00 ok, 01 fail - |------ Memory check, 00 ok, 01 fail, ff bad size - - ** ** ** ** ** ** - - The windows drivers seem to send the id and status queries before - and in between each of the chunks sent to the printer. There doesn't - appear to be any particular intelligence in the protocol, but it didn't - work when the raw dump was submitted as-is. - - ** ** ** ** ** ** - -Various deck status dumps: - -0080 00 00 00 00 00 00 01 d2 39 00 00 00 07 00 00 00 ........9....... -0090 61 8f 00 00 01 40 01 36 00 00 00 00 00 17 79 80 a....@.6......y. - -0080 00 00 00 00 00 00 01 c6 39 00 00 00 08 00 00 00 ........9....... -0090 61 8f 00 00 01 40 01 35 00 00 00 00 00 18 79 80 a....@.5......y. - -0080 00 00 00 00 00 00 02 19 50 00 00 00 19 00 00 01 ........P....... -0090 6c 8f 00 00 01 40 01 22 00 00 00 00 00 27 83 80 l....@.".....'.. - -0080 00 00 00 00 00 00 02 00 3e 00 00 04 96 00 00 00 ........>....... -0090 ff 0f 01 00 00 c8 00 52 00 00 00 00 05 28 75 80 .......R.....(u. - -00c0 00 00 00 00 00 00 01 f3 3d 00 00 06 39 00 00 00 ........=...9... -00d0 ff 02 00 00 01 90 00 c3 00 00 00 00 06 67 78 00 .............gx. - -0080 00 00 00 00 00 00 01 d0 38 00 00 03 70 00 00 00 ........8...p... -0090 ff 02 00 00 01 90 00 1e 01 00 00 00 03 83 72 80 ..............r. - -0080 00 00 00 00 00 00 01 d6 39 00 00 00 20 00 00 00 ........9... ... -0090 ff 02 00 00 01 90 01 7c 01 00 00 00 00 33 72 80 .......|.....3r. - - 00 00 00 0a 05 05 01 d5 38 00 00 00 14 00 00 00 - ff ff ff ff ff ff ff ff ff ff 00 00 00 27 72 80 ?? Error ?? - - 80 00 00 00 00 00 00 ff ff 00 00 00 00 00 00 00 - ff ff ff ff ff ff ff ff ff ff 00 00 00 00 80 00 NO DECK PRESENT */ |