diff options
Diffstat (limited to 'src/cups/backend_kodak6800.c')
-rw-r--r-- | src/cups/backend_kodak6800.c | 730 |
1 files changed, 265 insertions, 465 deletions
diff --git a/src/cups/backend_kodak6800.c b/src/cups/backend_kodak6800.c index 79d950b..06c54cb 100644 --- a/src/cups/backend_kodak6800.c +++ b/src/cups/backend_kodak6800.c @@ -1,7 +1,7 @@ /* * Kodak 6800/6850 Photo Printer CUPS backend -- libusb-1.0 version * - * (c) 2013-2018 Solomon Peachy <pizza@shaftnet.org> + * (c) 2013-2019 Solomon Peachy <pizza@shaftnet.org> * * Development of this backend was sponsored by: * @@ -43,6 +43,7 @@ #define BACKEND kodak6800_backend #include "backend_common.h" +#include "backend_sinfonia.h" #define USB_VID_KODAK 0x040A #define USB_PID_KODAK_6800 0x4021 @@ -55,9 +56,9 @@ struct kodak6800_hdr { uint16_t copies; /* BE, in BCD format (1-9999) */ uint16_t columns; /* BE */ uint16_t rows; /* BE */ - uint8_t size; /* 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ + uint8_t size; /* media size; 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ uint8_t laminate; /* 0x01 to laminate, 0x00 for not */ - uint8_t mode; /* 0x00 or 0x01 (for 4x6 on 6x8 media) */ + uint8_t method; /* 0x00 or 0x01 (for 4x6 on 6x8 media), 0x21 for 2x6, 0x23 for 3x6 */ } __attribute__((packed)); struct kodak68x0_status_readback { @@ -68,15 +69,15 @@ struct kodak68x0_status_readback { uint8_t errcode; /* Error ## */ uint32_t lifetime; /* Lifetime Prints (BE) */ uint32_t maint; /* Maint Prints (BE) */ - uint32_t media; /* Media Prints (6850), Unknown (6800) (BE) */ - uint32_t cutter; /* Cutter Actuations (BE) */ + uint32_t media; /* Media Prints (6850), Unknown (6800) (BE) */ + uint32_t cutter; /* Cutter Actuations (BE) */ uint8_t nullB[2]; uint8_t errtype; /* seen 0x00 or 0xd0 */ uint8_t donor; /* Percentage, 0-100 */ uint16_t main_boot; /* Always 003 */ - uint16_t main_fw; /* seen 652, 656, 670, 671 (6850) and 232 (6800) */ + uint16_t main_fw; /* seen 6xx/8xx (6850) and 2xx/3xx/4xx (6800) */ uint16_t dsp_boot; /* Always 001 */ - uint16_t dsp_fw; /* Seen 540, 541, 560 (6850) and 131 (6800) */ + uint16_t dsp_fw; /* Seen 5xx (6850) and 1xx (6800) */ uint8_t b1_jobid; uint8_t b2_jobid; uint16_t b1_remain; /* Remaining prints in job */ @@ -88,181 +89,43 @@ struct kodak68x0_status_readback { uint8_t curve_status; /* Always seems to be 0x00 */ } __attribute__((packed)); -enum { - CMD_CODE_OK = 1, - CMD_CODE_BAD = 2, -}; - -enum { - STATUS_PRINTING = 1, - STATUS_IDLE = 2, -}; - -enum { - STATE_STATUS1_STANDBY = 1, - STATE_STATUS1_ERROR = 2, - STATE_STATUS1_WAIT = 3, -}; - -#define STATE_STANDBY_STATUS2 0x0 - -enum { - WAIT_STATUS2_INIT = 0, - WAIT_STATUS2_RIBBON = 1, - WAIT_STATUS2_THERMAL = 2, - WAIT_STATUS2_OPERATING = 3, - WAIT_STATUS2_BUSY = 4, -}; - -#define ERROR_STATUS2_CTRL_CIRCUIT (0x80000000) -#define ERROR_STATUS2_MECHANISM_CTRL (0x40000000) -#define ERROR_STATUS2_SENSOR (0x00002000) -#define ERROR_STATUS2_COVER_OPEN (0x00001000) -#define ERROR_STATUS2_TEMP_SENSOR (0x00000200) -#define ERROR_STATUS2_PAPER_JAM (0x00000100) -#define ERROR_STATUS2_PAPER_EMPTY (0x00000040) -#define ERROR_STATUS2_RIBBON_ERR (0x00000010) - -enum { - CTRL_CIR_ERROR_EEPROM1 = 0x01, - CTRL_CIR_ERROR_EEPROM2 = 0x02, - CTRL_CIR_ERROR_DSP = 0x04, - CTRL_CIR_ERROR_CRC_MAIN = 0x06, - CTRL_CIR_ERROR_DL_MAIN = 0x07, - CTRL_CIR_ERROR_CRC_DSP = 0x08, - CTRL_CIR_ERROR_DL_DSP = 0x09, - CTRL_CIR_ERROR_ASIC = 0x0a, - CTRL_CIR_ERROR_DRAM = 0x0b, - CTRL_CIR_ERROR_DSPCOMM = 0x29, -}; - -enum { - MECH_ERROR_HEAD_UP = 0x01, - MECH_ERROR_HEAD_DOWN = 0x02, - MECH_ERROR_MAIN_PINCH_UP = 0x03, - MECH_ERROR_MAIN_PINCH_DOWN = 0x04, - MECH_ERROR_SUB_PINCH_UP = 0x05, - MECH_ERROR_SUB_PINCH_DOWN = 0x06, - MECH_ERROR_FEEDIN_PINCH_UP = 0x07, - MECH_ERROR_FEEDIN_PINCH_DOWN = 0x08, - MECH_ERROR_FEEDOUT_PINCH_UP = 0x09, - MECH_ERROR_FEEDOUT_PINCH_DOWN = 0x0a, - MECH_ERROR_CUTTER_LR = 0x0b, - MECH_ERROR_CUTTER_RL = 0x0c, -}; - -enum { - SENSOR_ERROR_CUTTER = 0x05, - SENSOR_ERROR_HEAD_DOWN = 0x09, - SENSOR_ERROR_HEAD_UP = 0x0a, - SENSOR_ERROR_MAIN_PINCH_DOWN = 0x0b, - SENSOR_ERROR_MAIN_PINCH_UP = 0x0c, - SENSOR_ERROR_FEED_PINCH_DOWN = 0x0d, - SENSOR_ERROR_FEED_PINCH_UP = 0x0e, - SENSOR_ERROR_EXIT_PINCH_DOWN = 0x0f, - SENSOR_ERROR_EXIT_PINCH_UP = 0x10, - SENSOR_ERROR_LEFT_CUTTER = 0x11, - SENSOR_ERROR_RIGHT_CUTTER = 0x12, - SENSOR_ERROR_CENTER_CUTTER = 0x13, - SENSOR_ERROR_UPPER_CUTTER = 0x14, - SENSOR_ERROR_PAPER_FEED_COVER = 0x15, -}; - -enum { - TEMP_SENSOR_ERROR_HEAD_HIGH = 0x01, - TEMP_SENSOR_ERROR_HEAD_LOW = 0x02, - TEMP_SENSOR_ERROR_ENV_HIGH = 0x03, - TEMP_SENSOR_ERROR_ENV_LOW = 0x04, -}; - -enum { - COVER_OPEN_ERROR_UPPER = 0x01, - COVER_OPEN_ERROR_LOWER = 0x02, -}; - -enum { - PAPER_EMPTY_ERROR = 0x00, -}; - -enum { - RIBBON_ERROR = 0x00, -}; - -enum { - CURVE_TABLE_STATUS_INITIAL = 0x00, - CURVE_TABLE_STATUS_USERSET = 0x01, - CURVE_TABLE_STATUS_CURRENT = 0x02, -}; - -struct kodak6800_printsize { - uint8_t hdr; /* Always 0x06 */ - uint16_t width; /* BE */ - uint16_t height; /* BE */ - uint8_t type; /* MEDIA_TYPE_* [ ie paper ] */ - uint8_t code; /* 00, 01, 02, 03, 04, 05 seen. An index? */ - uint8_t code2; /* 00, 01 seen. Alternates every other 4x6 printed, but only 1 on unknown/1844x2490 print size. */ - uint8_t null[2]; -} __attribute__((packed)); - -#define MAX_MEDIA_LEN 128 +#define MAX_MEDIAS 16 struct kodak68x0_media_readback { uint8_t hdr; /* Always 0x01 */ uint8_t type; /* Media code, KODAK68x0_MEDIA_xxx */ uint8_t null[5]; uint8_t count; /* Always 0x04 (6800) or 0x06 (6850)? */ - struct kodak6800_printsize sizes[]; + struct sinfonia_mediainfo_item sizes[]; } __attribute__((packed)); -#define KODAK68x0_MEDIA_6R 0x0b // 197-4096 -#define KODAK68x0_MEDIA_UNK 0x03 -#define KODAK68x0_MEDIA_6TR2 0x2c // 396-2941 -#define KODAK68x0_MEDIA_NONE 0x00 -/* 6R: Also seen: 101-0867, 141-9597, 659-9054, 169-6418, DNP 900-060 */ - #define CMDBUF_LEN 17 /* Private data structure */ -struct kodak6800_printjob { - struct kodak6800_hdr hdr; - uint8_t *databuf; - int datalen; - int copies; -}; - struct kodak6800_ctx { struct libusb_device_handle *dev; uint8_t endp_up; uint8_t endp_down; int type; + int supports_sub4x6; uint8_t jobid; - struct kodak68x0_media_readback *media; + struct sinfonia_mediainfo_item sizes[MAX_MEDIAS]; + uint8_t media_count; + uint8_t media_type; + + struct kodak68x0_status_readback sts; struct marker marker; }; -static const char *kodak68xx_mediatypes(int type) -{ - switch(type) { - case KODAK68x0_MEDIA_NONE: - return "No media"; - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: - return "Kodak 6R"; - default: - return "Unknown"; - } - return "Unknown"; -} - /* Baseline commands */ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx, - void *cmd, int cmd_len, - void *resp, int resp_len, - int *actual_len) + void *cmd, int cmd_len, + void *resp, int resp_len, + int *actual_len) { int ret; @@ -280,66 +143,82 @@ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx, return 0; } -static void kodak68x0_dump_mediainfo(struct kodak68x0_media_readback *media) +static void kodak68x0_dump_mediainfo(struct sinfonia_mediainfo_item *sizes, + uint8_t media_count, uint8_t media_type) { int i; - if (media->type == KODAK68x0_MEDIA_NONE) { + + if (media_type == KODAK6_MEDIA_NONE) { INFO("No Media Loaded\n"); return; } + kodak6_dumpmediacommon(media_type); - switch (media->type) { - case KODAK68x0_MEDIA_6R: - INFO("Media type: 6R (Kodak 197-4096 or equivalent)\n"); - break; - case KODAK68x0_MEDIA_6TR2: - INFO("Media type: 6R (Kodak 396-2941 or equivalent)\n"); - break; - default: - INFO("Media type %02x (unknown, please report!)\n", media->type); - break; - } INFO("Legal print sizes:\n"); - for (i = 0 ; i < media->count ; i++) { - INFO("\t%d: %dx%d (%02x) %s\n", i, - be16_to_cpu(media->sizes[i].width), - be16_to_cpu(media->sizes[i].height), - media->sizes[i].code, - media->sizes[i].code2? "Disallowed?" : ""); + for (i = 0 ; i < media_count ; i++) { + INFO("\t%d: %dx%d (%02x)\n", i, + sizes[i].columns, + sizes[i].rows, + sizes[i].method); } INFO("\n"); } -static int kodak6800_get_mediainfo(struct kodak6800_ctx *ctx, struct kodak68x0_media_readback *media) +#define MAX_MEDIA_LEN (sizeof(struct kodak68x0_media_readback) + MAX_MEDIAS * sizeof(struct sinfonia_mediainfo_item)) + +static int kodak6800_get_mediainfo(struct kodak6800_ctx *ctx) { + struct kodak68x0_media_readback *media; uint8_t req[16]; - int ret, num; + int ret, num, i, j; memset(req, 0, sizeof(req)); - memset(media, 0, sizeof(*media)); + media = malloc(MAX_MEDIA_LEN); + if (!media) { + ERROR("Memory allocation failure!\n"); + return CUPS_BACKEND_RETRY_CURRENT; + } - req[0] = 0x03; - req[1] = 0x1b; - req[2] = 0x43; - req[3] = 0x48; - req[4] = 0x43; - req[5] = 0x1a; - req[6] = 0x00; /* This can be non-zero for additional "banks" */ + for (j = 0 ; j < 2 ; j ++) { + memset(media, 0, sizeof(*media)); - /* Issue command and get response */ - if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - media, MAX_MEDIA_LEN, - &num))) - return ret; + req[0] = 0x03; + req[1] = 0x1b; + req[2] = 0x43; + req[3] = 0x48; + req[4] = 0x43; + req[5] = 0x1a; + req[6] = j; - /* Validate proper response */ - if (media->hdr != CMD_CODE_OK || - media->null[0] != 0x00) { - ERROR("Unexpected response from media query!\n"); - return CUPS_BACKEND_STOP; + /* Issue command and get response */ + if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), + media, MAX_MEDIA_LEN, + &num))) { + free(media); + return ret; + } + + /* Validate proper response */ + if (media->hdr != CMD_CODE_OK || + media->null[0] != 0x00) { + ERROR("Unexpected response from media query!\n"); + free(media); + return CUPS_BACKEND_STOP; + } + ctx->media_type = media->type; + + for (i = 0; i < media->count ; i++) { + memcpy(&ctx->sizes[ctx->media_count], &media->sizes[i], sizeof(struct sinfonia_mediainfo_item)); + ctx->sizes[ctx->media_count].rows = be16_to_cpu(ctx->sizes[ctx->media_count].rows); + ctx->sizes[ctx->media_count].columns = be16_to_cpu(ctx->sizes[ctx->media_count].columns); + ctx->media_count++; + } + if (i < 6) + break; } - return 0; + free(media); + return CUPS_BACKEND_OK; } static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, @@ -347,7 +226,6 @@ static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, { uint8_t req[16]; int ret, num; - struct kodak68x0_status_readback sts; memset(req, 0, sizeof(req)); @@ -361,12 +239,12 @@ static int kodak68x0_canceljob(struct kodak6800_ctx *ctx, /* Issue command and get response */ if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - &sts, sizeof(sts), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; /* Validate proper response */ - if (sts.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from job cancel!\n"); return -99; } @@ -378,7 +256,6 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) { uint8_t req[16]; int ret, num; - struct kodak68x0_status_readback sts; memset(req, 0, sizeof(req)); @@ -390,12 +267,12 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) /* Issue command and get response */ if ((ret = kodak6800_do_cmd(ctx, req, sizeof(req), - &sts, sizeof(sts), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; /* Validate proper response */ - if (sts.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from job cancel!\n"); return -99; } @@ -403,153 +280,6 @@ static int kodak68x0_reset(struct kodak6800_ctx *ctx) return 0; } - -/* Structure dumps */ -static char *kodak68x0_status_str(struct kodak68x0_status_readback *resp) -{ - switch(resp->status1) { - case STATE_STATUS1_STANDBY: - return "Standby (Ready)"; - case STATE_STATUS1_WAIT: - switch (be32_to_cpu(resp->status2)) { - case WAIT_STATUS2_INIT: - return "Wait (Initializing)"; - case WAIT_STATUS2_RIBBON: - return "Wait (Ribbon Winding)"; - case WAIT_STATUS2_THERMAL: - return "Wait (Thermal Protection)"; - case WAIT_STATUS2_OPERATING: - return "Wait (Operating)"; - case WAIT_STATUS2_BUSY: - return "Wait (Busy)"; - default: - return "Wait (Unknown)"; - } - case STATE_STATUS1_ERROR: - switch (be32_to_cpu(resp->status2)) { - case ERROR_STATUS2_CTRL_CIRCUIT: - switch (resp->errcode) { - case CTRL_CIR_ERROR_EEPROM1: - return "Error (EEPROM1)"; - case CTRL_CIR_ERROR_EEPROM2: - return "Error (EEPROM2)"; - case CTRL_CIR_ERROR_DSP: - return "Error (DSP)"; - case CTRL_CIR_ERROR_CRC_MAIN: - return "Error (Main CRC)"; - case CTRL_CIR_ERROR_DL_MAIN: - return "Error (Main Download)"; - case CTRL_CIR_ERROR_CRC_DSP: - return "Error (DSP CRC)"; - case CTRL_CIR_ERROR_DL_DSP: - return "Error (DSP Download)"; - case CTRL_CIR_ERROR_ASIC: - return "Error (ASIC)"; - case CTRL_CIR_ERROR_DRAM: - return "Error (DRAM)"; - case CTRL_CIR_ERROR_DSPCOMM: - return "Error (DSP Communincation)"; - default: - return "Error (Unknown Circuit)"; - } - case ERROR_STATUS2_MECHANISM_CTRL: - switch (resp->errcode) { - case MECH_ERROR_HEAD_UP: - return "Error (Head Up Mechanism)"; - case MECH_ERROR_HEAD_DOWN: - return "Error (Head Down Mechanism)"; - case MECH_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Mechanism)"; - case MECH_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Mechanism)"; - case MECH_ERROR_SUB_PINCH_UP: - return "Error (Sub Pinch Up Mechanism)"; - case MECH_ERROR_SUB_PINCH_DOWN: - return "Error (Sub Pinch Down Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_UP: - return "Error (Feed-in Pinch Up Mechanism)"; - case MECH_ERROR_FEEDIN_PINCH_DOWN: - return "Error (Feed-in Pinch Down Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_UP: - return "Error (Feed-out Pinch Up Mechanism)"; - case MECH_ERROR_FEEDOUT_PINCH_DOWN: - return "Error (Feed-out Pinch Down Mechanism)"; - case MECH_ERROR_CUTTER_LR: - return "Error (Left->Right Cutter)"; - case MECH_ERROR_CUTTER_RL: - return "Error (Right->Left Cutter)"; - default: - return "Error (Unknown Mechanism)"; - } - case ERROR_STATUS2_SENSOR: - switch (resp->errcode) { - case SENSOR_ERROR_CUTTER: - return "Error (Cutter Sensor)"; - case SENSOR_ERROR_HEAD_DOWN: - return "Error (Head Down Sensor)"; - case SENSOR_ERROR_HEAD_UP: - return "Error (Head Up Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_DOWN: - return "Error (Main Pinch Down Sensor)"; - case SENSOR_ERROR_MAIN_PINCH_UP: - return "Error (Main Pinch Up Sensor)"; - case SENSOR_ERROR_FEED_PINCH_DOWN: - return "Error (Feed Pinch Down Sensor)"; - case SENSOR_ERROR_FEED_PINCH_UP: - return "Error (Feed Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_DOWN: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_EXIT_PINCH_UP: - return "Error (Exit Pinch Up Sensor)"; - case SENSOR_ERROR_LEFT_CUTTER: - return "Error (Left Cutter Sensor)"; - case SENSOR_ERROR_RIGHT_CUTTER: - return "Error (Right Cutter Sensor)"; - case SENSOR_ERROR_CENTER_CUTTER: - return "Error (Center Cutter Sensor)"; - case SENSOR_ERROR_UPPER_CUTTER: - return "Error (Upper Cutter Sensor)"; - case SENSOR_ERROR_PAPER_FEED_COVER: - return "Error (Paper Feed Cover)"; - default: - return "Error (Unknown Sensor)"; - } - case ERROR_STATUS2_COVER_OPEN: - switch (resp->errcode) { - case COVER_OPEN_ERROR_UPPER: - return "Error (Upper Cover Open)"; - case COVER_OPEN_ERROR_LOWER: - return "Error (Lower Cover Open)"; - default: - return "Error (Unknown Cover Open)"; - } - case ERROR_STATUS2_TEMP_SENSOR: - switch (resp->errcode) { - case TEMP_SENSOR_ERROR_HEAD_HIGH: - return "Error (Head Temperature High)"; - case TEMP_SENSOR_ERROR_HEAD_LOW: - return "Error (Head Temperature Low)"; - case TEMP_SENSOR_ERROR_ENV_HIGH: - return "Error (Environmental Temperature High)"; - case TEMP_SENSOR_ERROR_ENV_LOW: - return "Error (Environmental Temperature Low)"; - default: - return "Error (Unknown Temperature)"; - } - case ERROR_STATUS2_PAPER_JAM: - return "Error (Paper Jam)"; - case ERROR_STATUS2_PAPER_EMPTY: - return "Error (Paper Empty)"; - case ERROR_STATUS2_RIBBON_ERR: - return "Error (Ribbon)"; - default: - return "Error (Unknown)"; - } - default: - return "Unknown!"; - } -} - static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_status_readback *status) { char *detail; @@ -568,8 +298,8 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st INFO("Printer Status : %s\n", detail); INFO("Printer State : %s # %02x %08x %02x\n", - kodak68x0_status_str(status), - status->status1, be32_to_cpu(status->status2), status->errcode); + sinfonia_1x45_status_str(status->status1, status->status2, status->errcode), + status->status1, status->status2, status->errcode); INFO("Bank 1 ID: %u\n", status->b1_jobid); INFO("\tPrints: %d/%d complete\n", @@ -604,9 +334,9 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st INFO("\tMedia : %u\n", be32_to_cpu(status->media)); - switch(ctx->media->type) { - case KODAK68x0_MEDIA_6R: - case KODAK68x0_MEDIA_6TR2: + switch(ctx->media_type) { + case KODAK6_MEDIA_6R: + case KODAK6_MEDIA_6TR2: max = 375; break; default: @@ -615,7 +345,7 @@ static void kodak68x0_dump_status(struct kodak6800_ctx *ctx, struct kodak68x0_st } if (max) { - INFO("\t Remaining : %d\n", max - be32_to_cpu(status->media)); + INFO("\t Remaining : %u\n", max - be32_to_cpu(status->media)); } else { INFO("\t Remaining : Unknown\n"); } @@ -654,11 +384,12 @@ static int kodak6800_get_status(struct kodak6800_ctx *ctx, return -99; } + /* Byteswap important stuff */ + status->status2 = be32_to_cpu(status->status2); + return 0; } - -#define UPDATE_SIZE 1536 static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) { uint8_t cmdbuf[16]; @@ -666,7 +397,7 @@ static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) int ret, num = 0; int i; - uint16_t *data = malloc(UPDATE_SIZE); + uint16_t *data = malloc(TONE_CURVE_SIZE); if (!data) { ERROR("Memory Allocation Failure\n"); return -1; @@ -745,7 +476,7 @@ static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) for (i = 0 ; i < 768; i++) { /* Byteswap appropriately */ data[i] = cpu_to_be16(le16_to_cpu(data[i])); - write(tc_fd, &data[i], sizeof(uint16_t)); + ret = write(tc_fd, &data[i], sizeof(uint16_t)); } close(tc_fd); } @@ -764,7 +495,7 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) int ret, num = 0; int remain; - uint16_t *data = malloc(UPDATE_SIZE); + uint16_t *data = malloc(TONE_CURVE_SIZE); uint8_t *ptr; if (!data) { @@ -775,19 +506,13 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) INFO("Set Tone Curve from '%s'\n", fname); /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) { - ret = -1; - goto done; - } - if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) { - ret = -2; + if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) { + ERROR("Failed to read Tone Curve file\n"); goto done; } - close(tc_fd); /* Byteswap data to printer's format */ - for (ret = 0; ret < (UPDATE_SIZE)/2 ; ret++) { + for (ret = 0; ret < (TONE_CURVE_SIZE)/2 ; ret++) { data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); } @@ -828,7 +553,7 @@ static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) } ptr = (uint8_t*) data; - remain = UPDATE_SIZE; + remain = TONE_CURVE_SIZE; while (remain > 0) { int count = remain > 63 ? 63 : remain; @@ -971,16 +696,15 @@ static int kodak6800_cmdline_arg(void *vctx, int argc, char **argv) j = kodak6800_set_tonecurve(ctx, optarg); break; case 'm': - kodak68x0_dump_mediainfo(ctx->media); + kodak68x0_dump_mediainfo(ctx->sizes, ctx->media_count, ctx->media_type); break; case 'R': kodak68x0_reset(ctx); break; case 's': { - struct kodak68x0_status_readback status; - j = kodak6800_get_status(ctx, &status); + j = kodak6800_get_status(ctx, &ctx->sts); if (!j) - kodak68x0_dump_status(ctx, &status); + kodak68x0_dump_status(ctx, &ctx->sts); break; } case 'X': @@ -1005,8 +729,6 @@ static void *kodak6800_init(void) } memset(ctx, 0, sizeof(struct kodak6800_ctx)); - ctx->media = malloc(MAX_MEDIA_LEN); - return ctx; } @@ -1026,51 +748,57 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev, int ty ctx->jobid++; if (test_mode < TEST_MODE_NOATTACH) { + /* Query printer status */ + if (kodak6800_get_status(ctx, &ctx->sts)) { + ERROR("Can't query status\n"); + return CUPS_BACKEND_FAILED; + } + uint16_t fw = be16_to_cpu(ctx->sts.main_fw); + if (ctx->type == P_KODAK_6850) { + if ((fw >= 878) || + (fw < 800 && fw >= 678)) { + ctx->supports_sub4x6 = 1; + } else { + WARNING("Printer FW out of date, recommend updating for current media and features\n"); + } + } else { + if ((fw >= 459) || + (fw < 400 && fw >= 359) || + (fw < 300 && fw >= 259)) { + ctx->supports_sub4x6 = 1; + } else { + WARNING("Printer FW out of date, recommend updating for current media and features\n"); + } + } + /* Query media info */ - if (kodak6800_get_mediainfo(ctx, ctx->media)) { + if (kodak6800_get_mediainfo(ctx)) { ERROR("Can't query media\n"); return CUPS_BACKEND_FAILED; } } else { - int media_code = KODAK68x0_MEDIA_6TR2; + int media_code = KODAK6_MEDIA_6TR2; if (getenv("MEDIA_CODE")) media_code = atoi(getenv("MEDIA_CODE")); - ctx->media->type = media_code; + ctx->media_type = media_code; + ctx->supports_sub4x6 = 1; } ctx->marker.color = "#00FFFF#FF00FF#FFFF00"; - ctx->marker.name = kodak68xx_mediatypes(ctx->media->type); + ctx->marker.name = kodak6_mediatypes(ctx->media_type); ctx->marker.levelmax = 100; /* Ie percentage */ ctx->marker.levelnow = -2; return CUPS_BACKEND_OK; } -static void kodak6800_cleanup_job(const void *vjob) -{ - const struct kodak6800_printjob *job = vjob; - - if (job->databuf) - free(job->databuf); - - free((void*)job); -} - -static void kodak6800_teardown(void *vctx) { - struct kodak6800_ctx *ctx = vctx; - - if (!ctx) - return; - - free(ctx); -} - static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int copies) { struct kodak6800_ctx *ctx = vctx; int ret; - struct kodak6800_printjob *job = NULL; + struct kodak6800_hdr hdr; + struct sinfonia_printjob *job = NULL; if (!ctx) return CUPS_BACKEND_FAILED; @@ -1083,31 +811,51 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int memset(job, 0, sizeof(*job)); /* Read in then validate header */ - ret = read(data_fd, &job->hdr, sizeof(job->hdr)); - if (ret < 0 || ret != sizeof(job->hdr)) { - if (ret == 0) + ret = read(data_fd, &hdr, sizeof(hdr)); + if (ret < 0 || ret != sizeof(hdr)) { + if (ret == 0) { + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; + } ERROR("Read failed (%d/%d/%d)\n", - ret, 0, (int)sizeof(job->hdr)); + ret, 0, (int)sizeof(hdr)); perror("ERROR: Read failed"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } - if (job->hdr.hdr[0] != 0x03 || - job->hdr.hdr[1] != 0x1b || - job->hdr.hdr[2] != 0x43 || - job->hdr.hdr[3] != 0x48 || - job->hdr.hdr[4] != 0x43) { + if (hdr.hdr[0] != 0x03 || + hdr.hdr[1] != 0x1b || + hdr.hdr[2] != 0x43 || + hdr.hdr[3] != 0x48 || + hdr.hdr[4] != 0x43) { ERROR("Unrecognized data format!\n"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } - job->datalen = be16_to_cpu(job->hdr.rows) * be16_to_cpu(job->hdr.columns) * 3; + uint16_t rows = be16_to_cpu(hdr.rows); + uint16_t cols = be16_to_cpu(hdr.columns); + if (rows != 1240 && rows != 2434 && rows != 2140 && !ctx->supports_sub4x6) { + ERROR("Printer Firmware does not support non-4x6/8x6/5x7 prints, please upgrade!\n"); + sinfonia_cleanup_job(job); + return CUPS_BACKEND_CANCEL; + } + + job->datalen = rows * cols * 3; job->databuf = malloc(job->datalen); if (!job->databuf) { ERROR("Memory allocation failure!\n"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_RETRY_CURRENT; } + /* Windows driver only sends 634 rows of data, work around */ + if (rows == 636 && hdr.size == 6 && hdr.method == 0) { + rows = 634; + job->datalen -= 1844*2*3; + } + + /* Read in the spool data */ { int remain = job->datalen; uint8_t *ptr = job->databuf; @@ -1117,6 +865,7 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int ERROR("Read failed (%d/%d/%d)\n", ret, remain, job->datalen); perror("ERROR: Read failed"); + sinfonia_cleanup_job(job); return CUPS_BACKEND_CANCEL; } ptr += ret; @@ -1124,13 +873,47 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int } while (remain); } - /* Fix max print count. */ - if (copies > 9999) // XXX test against remaining media - copies = 9999; + /* Undo the Windows workaround... */ + if (rows == 634) { + rows = 636; + job->datalen += 1844*2*3; + } + + /* Perform some header re-jiggery */ + if (hdr.size == 0) { + if (cols == 1844) + hdr.size = 6; + else if (cols == 1548) + hdr.size = 7; + } + if (hdr.method == 0) { + if (rows == 636) { + hdr.method = 0x21; + } else if (rows == 936) { + hdr.method = 0x23; + } else if (rows == 1240) { + hdr.method = 0x01; + } else if (rows == 1282) { + hdr.method = 0x20; + } else if (rows == 1882) { + hdr.method = 0x22; + } else if (rows == 2490) { + hdr.method = 0x2; + } + } + + hdr.copies = be16_to_cpu(hdr.copies); + hdr.copies = packed_bcd_to_uint32((char*)&hdr.copies, 2); + if (hdr.copies > 1) + copies = hdr.copies; - /* Printer handles generating copies.. */ - if (le16_to_cpu(job->hdr.copies) < copies) - job->hdr.copies = cpu_to_be16(uint16_to_packed_bcd(copies)); + /* Fill out job structure */ + job->jp.copies = copies; + job->jp.rows = rows; + job->jp.columns = cols; + job->jp.media = hdr.size; + job->jp.oc_mode = hdr.laminate; + job->jp.method = hdr.method; *vjob = job; @@ -1139,28 +922,27 @@ static int kodak6800_read_parse(void *vctx, const void **vjob, int data_fd, int static int kodak6800_main_loop(void *vctx, const void *vjob) { struct kodak6800_ctx *ctx = vctx; - struct kodak68x0_status_readback status; int num, ret; + int copies; - const struct kodak6800_printjob *job = vjob; + const struct sinfonia_printjob *job = vjob; if (!ctx) return CUPS_BACKEND_FAILED; if (!job) return CUPS_BACKEND_FAILED; - struct kodak6800_hdr hdr; - memcpy(&hdr, &job->hdr, sizeof(hdr)); + copies = job->jp.copies; /* Validate against supported media list */ - for (num = 0 ; num < ctx->media->count; num++) { - if (ctx->media->sizes[num].height == hdr.rows && - ctx->media->sizes[num].width == hdr.columns && - ctx->media->sizes[num].code2 == 0x00) // XXX code2? + for (num = 0 ; num < ctx->media_count; num++) { + if (ctx->sizes[num].rows == job->jp.rows && + ctx->sizes[num].columns == job->jp.columns && + ctx->sizes[num].method == job->jp.method) break; } - if (num == ctx->media->count) { + if (num == ctx->media_count) { ERROR("Print size unsupported by media!\n"); return CUPS_BACKEND_HOLD; } @@ -1168,28 +950,25 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { INFO("Waiting for printer idle\n"); while(1) { - if (kodak6800_get_status(ctx, &status)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - if (ctx->marker.levelnow != status.donor) { - ctx->marker.levelnow = status.donor; + if (ctx->marker.levelnow != ctx->sts.donor) { + ctx->marker.levelnow = ctx->sts.donor; dump_markers(&ctx->marker, 1, 0); } - if (status.status1 == STATE_STATUS1_ERROR) { + if (ctx->sts.status1 == STATE_STATUS1_ERROR) { INFO("Printer State: %s # %02x %08x %02x\n", - kodak68x0_status_str(&status), - status.status1, be32_to_cpu(status.status2), status.errcode); + sinfonia_1x45_status_str(ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode), + ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode); return CUPS_BACKEND_FAILED; } - if (status.status == STATUS_IDLE) - break; - /* make sure we're not colliding with an existing jobid */ - while (ctx->jobid == status.b1_jobid || - ctx->jobid == status.b2_jobid) { + while (ctx->jobid == ctx->sts.b1_jobid || + ctx->jobid == ctx->sts.b2_jobid) { ctx->jobid++; ctx->jobid &= 0x7f; if (!ctx->jobid) @@ -1197,8 +976,8 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { } /* See if we have an open bank */ - if (!status.b1_remain || - !status.b2_remain) + if (!ctx->sts.b1_remain || + !ctx->sts.b2_remain) break; sleep(1); @@ -1211,25 +990,34 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { return ret; } - hdr.jobid = ctx->jobid; + /* Fix max print count. */ + if (copies > 9999) + copies = 9999; -#if 0 - /* If we want to disable 4x6 rewind on 8x6 media.. */ - // XXX not sure about this...? - if (hdr.size == 0x00 && - be16_to_cpu(ctx->media->sizes[0].width) == 0x0982) { - hdr.size = 0x06; - hdr.mode = 0x01; - } -#endif + /* Fill out printjob header */ + struct kodak6800_hdr hdr; + hdr.hdr[0] = 0x03; + hdr.hdr[1] = 0x1b; + hdr.hdr[2] = 0x43; + hdr.hdr[3] = 0x48; + hdr.hdr[4] = 0x43; + hdr.hdr[5] = 0x0a; + hdr.hdr[6] = 0x00; + hdr.jobid = ctx->jobid; + hdr.copies = uint16_to_packed_bcd(copies); + hdr.columns = cpu_to_be16(job->jp.columns); + hdr.rows = cpu_to_be16(job->jp.rows); + hdr.size = job->jp.media; + hdr.laminate = job->jp.oc_mode; + hdr.method = job->jp.method; INFO("Sending Print Job (internal id %u)\n", ctx->jobid); if ((ret = kodak6800_do_cmd(ctx, (uint8_t*) &hdr, sizeof(hdr), - &status, sizeof(status), + &ctx->sts, sizeof(ctx->sts), &num))) return ret; - if (status.hdr != CMD_CODE_OK) { + if (ctx->sts.hdr != CMD_CODE_OK) { ERROR("Unexpected response from print command!\n"); return CUPS_BACKEND_FAILED; } @@ -1243,25 +1031,25 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { INFO("Waiting for printer to acknowledge completion\n"); do { sleep(1); - if (kodak6800_get_status(ctx, &status)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - if (ctx->marker.levelnow != status.donor) { - ctx->marker.levelnow = status.donor; + if (ctx->marker.levelnow != ctx->sts.donor) { + ctx->marker.levelnow = ctx->sts.donor; dump_markers(&ctx->marker, 1, 0); } - if (status.status1 == STATE_STATUS1_ERROR) { + if (ctx->sts.status1 == STATE_STATUS1_ERROR) { INFO("Printer State: %s # %02x %08x %02x\n", - kodak68x0_status_str(&status), - status.status1, be32_to_cpu(status.status2), status.errcode); + sinfonia_1x45_status_str(ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode), + ctx->sts.status1, ctx->sts.status2, ctx->sts.errcode); return CUPS_BACKEND_FAILED; } /* If all prints are complete, we're done! */ - if (status.b1_jobid == hdr.jobid && status.b1_complete == status.b1_total) + if (ctx->sts.b1_jobid == hdr.jobid && ctx->sts.b1_complete == ctx->sts.b1_total) break; - if (status.b2_jobid == hdr.jobid && status.b2_complete == status.b2_total) + if (ctx->sts.b2_jobid == hdr.jobid && ctx->sts.b2_complete == ctx->sts.b2_total) break; if (fast_return) { @@ -1279,13 +1067,12 @@ static int kodak6800_main_loop(void *vctx, const void *vjob) { 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)) + if (kodak6800_get_status(ctx, &ctx->sts)) return CUPS_BACKEND_FAILED; - ctx->marker.levelnow = status.donor; + ctx->marker.levelnow = ctx->sts.donor; *markers = &ctx->marker; *count = 1; @@ -1304,14 +1091,13 @@ static const char *kodak6800_prefixes[] = { /* Exported */ struct dyesub_backend kodak6800_backend = { .name = "Kodak 6800/6850", - .version = "0.65", + .version = "0.73" " (lib " LIBSINFONIA_VER ")", .uri_prefixes = kodak6800_prefixes, .cmdline_usage = kodak6800_cmdline, .cmdline_arg = kodak6800_cmdline_arg, .init = kodak6800_init, .attach = kodak6800_attach, - .teardown = kodak6800_teardown, - .cleanup_job = kodak6800_cleanup_job, + .cleanup_job = sinfonia_cleanup_job, .read_parse = kodak6800_read_parse, .main_loop = kodak6800_main_loop, .query_serno = kodak6800_query_serno, @@ -1341,7 +1127,7 @@ struct dyesub_backend kodak6800_backend = { HH HH Number of rows. SS Print size -- 0x00 (4x6) 0x06 (8x6) 0x07 (5x7 on 6850) LL Laminate mode -- 0x00 (off) or 0x01 (on) - UU Print mode -- 0x00 (normal) or (0x01) 4x6 on 8x6 + UU Print mode -- 0x00 (normal) or 0x01 (4x6 on 8x6) 0x21 (2x6) 0x23 (3x6) ************************************************************************ @@ -1366,4 +1152,18 @@ struct dyesub_backend kodak6800_backend = { 00 01 02 1c 00 00 00 00 00 01 00 01 00 00 00 00 00 00 00 + An additional command that's also unknown + +-> 03 1b 43 48 43 4d 01 00 00 00 00 00 00 00 00 00 +<- 01 02 01 00 00 00 00 00 00 00 5d ca 00 00 5d ca + 00 00 00 15 00 00 b8 f8 00 00 00 40 00 03 02 a6 + 00 01 02 31 1e 00 00 00 00 01 00 01 00 00 00 00 + 00 00 00 + + One more note for the 6850. These sizes have been seen: + + 1844x2434, method 0x03 + 1844x2490, method 0x05 + 1844x2222, method 0x00 + */ |