summaryrefslogtreecommitdiff
path: root/src/cups/backend_kodak6800.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cups/backend_kodak6800.c')
-rw-r--r--src/cups/backend_kodak6800.c730
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
+
*/