summaryrefslogtreecommitdiff
path: root/src/cups/selphy_print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cups/selphy_print.c')
-rw-r--r--src/cups/selphy_print.c107
1 files changed, 68 insertions, 39 deletions
diff --git a/src/cups/selphy_print.c b/src/cups/selphy_print.c
index 7247e51..2c9bab0 100644
--- a/src/cups/selphy_print.c
+++ b/src/cups/selphy_print.c
@@ -1,7 +1,7 @@
/*
* Canon SELPHY ES/CP series CUPS backend -- libusb-1.0 version
*
- * (c) 2007-2014 Solomon Peachy <pizza@shaftnet.org>
+ * (c) 2007-2015 Solomon Peachy <pizza@shaftnet.org>
*
* The latest version of this program can be found at:
*
@@ -426,6 +426,7 @@ enum {
S_PRINTER_M_SENT,
S_PRINTER_READY_C,
S_PRINTER_C_SENT,
+ S_PRINTER_CP900_FOOTER,
S_PRINTER_DONE,
S_FINISHED,
};
@@ -519,19 +520,28 @@ struct canonselphy_ctx {
uint8_t *footer;
uint8_t *buffer;
+
+ uint8_t cp900;
};
static void *canonselphy_init(void)
{
struct canonselphy_ctx *ctx = malloc(sizeof(struct canonselphy_ctx));
- if (!ctx)
+ if (!ctx) {
+ ERROR("Memory Allocation Failure!\n");
return NULL;
+ }
memset(ctx, 0, sizeof(struct canonselphy_ctx));
/* Static initialization */
setup_paper_codes();
ctx->buffer = malloc(MAX_HEADER);
+ if (!ctx->buffer) {
+ ERROR("Memory Allocation Failure!\n");
+ free(ctx);
+ ctx = NULL;
+ }
return ctx;
}
@@ -540,6 +550,8 @@ static void canonselphy_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
struct canonselphy_ctx *ctx = vctx;
+ struct libusb_device *device;
+ struct libusb_device_descriptor desc;
UNUSED(jobid);
@@ -547,15 +559,14 @@ static void canonselphy_attach(void *vctx, struct libusb_device_handle *dev,
ctx->endp_up = endp_up;
ctx->endp_down = endp_down;
+ device = libusb_get_device(dev);
+ libusb_get_device_descriptor(device, &desc);
+
/* Special cases for some models */
if (ctx->printer->type == P_ES40_CP790) {
- struct libusb_device *device;
- struct libusb_device_descriptor desc;
int i;
int printer_type;
- device = libusb_get_device(dev);
- libusb_get_device_descriptor(device, &desc);
if (desc.idProduct == USB_PID_CANON_CP790)
printer_type = P_CP790;
@@ -568,6 +579,8 @@ static void canonselphy_attach(void *vctx, struct libusb_device_handle *dev,
break;
}
}
+ } else if (desc.idProduct == USB_PID_CANON_CP900) {
+ ctx->cp900 = 1;
}
}
@@ -610,7 +623,7 @@ static int canonselphy_early_parse(void *vctx, int data_fd)
ERROR("Read failed (%d/%d/%d)\n",
i, 0, MAX_HEADER);
perror("ERROR: Read failed");
- return i;
+ return -1;
}
printer_type = parse_printjob(ctx->buffer, &ctx->bw_mode, &ctx->plane_len);
@@ -642,7 +655,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
int i, remain;
if (!ctx)
- return 1;
+ return CUPS_BACKEND_FAILED;
if (ctx->header) {
free(ctx->header);
@@ -674,7 +687,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
if (!ctx->plane_y || !ctx->plane_m || !ctx->plane_c || !ctx->header ||
(ctx->printer->foot_length && !ctx->footer)) {
ERROR("Memory allocation failure!\n");
- return 1;
+ return CUPS_BACKEND_FAILED;
}
/* Move over chunks already read in */
@@ -687,7 +700,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
while (remain > 0) {
i = read(data_fd, ctx->plane_y + (ctx->plane_len - remain), remain);
if (i < 0)
- return i;
+ return CUPS_BACKEND_CANCEL;
remain -= i;
}
@@ -696,7 +709,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
while (remain > 0) {
i = read(data_fd, ctx->plane_m + (ctx->plane_len - remain), remain);
if (i < 0)
- return i;
+ return CUPS_BACKEND_CANCEL;
remain -= i;
}
@@ -705,7 +718,7 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
while (remain > 0) {
i = read(data_fd, ctx->plane_c + (ctx->plane_len - remain), remain);
if (i < 0)
- return i;
+ return CUPS_BACKEND_CANCEL;
remain -= i;
}
@@ -715,12 +728,12 @@ static int canonselphy_read_parse(void *vctx, int data_fd)
while (remain > 0) {
i = read(data_fd, ctx->footer + (ctx->printer->foot_length - remain), remain);
if (i < 0)
- return i;
+ return CUPS_BACKEND_CANCEL;
remain -= i;
}
}
- return 0;
+ return CUPS_BACKEND_OK;
}
static int canonselphy_main_loop(void *vctx, int copies) {
@@ -735,7 +748,7 @@ static int canonselphy_main_loop(void *vctx, int copies) {
rdbuf, READBACK_LEN, &num);
if (ret < 0)
- return ret;
+ return CUPS_BACKEND_FAILED;
top:
@@ -748,11 +761,11 @@ top:
ret = read_data(ctx->dev, ctx->endp_up,
rdbuf, READBACK_LEN, &num);
if (ret < 0)
- return ret;
+ return CUPS_BACKEND_FAILED;
if (num != READBACK_LEN) {
ERROR("Short read! (%d/%d)\n", num, READBACK_LEN);
- return 4;
+ return CUPS_BACKEND_FAILED;
}
/* Error detection */
@@ -760,8 +773,8 @@ top:
if (ctx->printer->clear_error_len)
/* Try to clear error state */
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->printer->clear_error, ctx->printer->clear_error_len)))
- return ret;
- return 4;
+ return CUPS_BACKEND_FAILED;
+ return CUPS_BACKEND_HOLD;
}
if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
@@ -787,20 +800,20 @@ top:
if (pc & 0xf0) {
ERROR("Incorrect paper tray loaded, aborting job!\n");
- return 3;
+ return CUPS_BACKEND_HOLD;
} else {
ERROR("No paper tray loaded, aborting!\n");
- return 4;
+ return CUPS_BACKEND_STOP;
}
}
if ((pc & 0xf) != (ctx->paper_code & 0xf)) {
if (pc & 0x0f) {
ERROR("Incorrect ribbon loaded, aborting job!\n");
- return 3;
+ return CUPS_BACKEND_HOLD;
} else {
ERROR("No ribbon loaded, aborting job!\n");
- return 4;
+ return CUPS_BACKEND_STOP;
}
}
} else {
@@ -809,7 +822,7 @@ top:
ERROR("Incorrect media/ribbon loaded (%02x vs %02x), aborting job!\n",
ctx->paper_code,
rdbuf[ctx->printer->paper_code_offset]);
- return 3; /* Hold this job, don't stop queue */
+ return CUPS_BACKEND_HOLD; /* Hold this job, don't stop queue */
}
}
} else if (ctx->printer->type == P_CP790) {
@@ -818,17 +831,17 @@ top:
if (ribbon == 0xf) {
ERROR("No ribbon loaded, aborting!\n");
- return 4;
+ return CUPS_BACKEND_STOP;
} else if (ribbon != ctx->paper_code) {
ERROR("Incorrect ribbon loaded, aborting job!\n");
- return 3;
+ return CUPS_BACKEND_HOLD;
}
if (paper == 0xf) {
ERROR("No paper tray loaded, aborting!\n");
- return 4;
+ return CUPS_BACKEND_STOP;
} else if (paper != ctx->paper_code) {
ERROR("Incorrect paper loaded, aborting job!\n");
- return 3;
+ return CUPS_BACKEND_HOLD;
}
}
@@ -838,7 +851,7 @@ top:
INFO("Printing started; Sending init sequence\n");
/* Send printer init */
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->header, ctx->printer->init_length)))
- return ret;
+ return CUPS_BACKEND_FAILED;
state = S_PRINTER_INIT_SENT;
break;
@@ -854,7 +867,7 @@ top:
INFO("Sending YELLOW plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_y, ctx->plane_len)))
- return ret;
+ return CUPS_BACKEND_FAILED;
state = S_PRINTER_Y_SENT;
break;
@@ -870,7 +883,7 @@ top:
INFO("Sending MAGENTA plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_m, ctx->plane_len)))
- return ret;
+ return CUPS_BACKEND_FAILED;
state = S_PRINTER_M_SENT;
break;
@@ -883,21 +896,35 @@ top:
INFO("Sending CYAN plane\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->plane_c, ctx->plane_len)))
- return ret;
+ return CUPS_BACKEND_FAILED;
state = S_PRINTER_C_SENT;
break;
case S_PRINTER_C_SENT:
if (!fancy_memcmp(rdbuf, ctx->printer->done_c_readback, READBACK_LEN)) {
- state = S_PRINTER_DONE;
+ if (ctx->cp900)
+ state = S_PRINTER_CP900_FOOTER;
+ else
+ state = S_PRINTER_DONE;
}
break;
+ case S_PRINTER_CP900_FOOTER: {
+ uint32_t empty = 0;
+
+ INFO("Sending CP900 Footer\n");
+ if ((ret = send_data(ctx->dev, ctx->endp_down,
+ (uint8_t*)&empty, sizeof(empty))))
+ return CUPS_BACKEND_FAILED;
+
+ state = S_PRINTER_DONE;
+ break;
+ }
case S_PRINTER_DONE:
if (ctx->printer->foot_length) {
INFO("Cleaning up\n");
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->footer, ctx->printer->foot_length)))
- return ret;
+ return CUPS_BACKEND_FAILED;
}
state = S_FINISHED;
/* Intentional Fallthrough */
@@ -919,12 +946,12 @@ top:
goto top;
}
- return 0;
+ return CUPS_BACKEND_OK;
}
struct dyesub_backend canonselphy_backend = {
.name = "Canon SELPHY CP/ES",
- .version = "0.82.2G",
+ .version = "0.87",
.uri_prefix = "canonselphy",
.init = canonselphy_init,
.attach = canonselphy_attach,
@@ -1284,6 +1311,8 @@ struct dyesub_backend canonselphy_backend = {
adding a 50x50mm sticker and 22x17.3mm ministickers, though I think the
driver treats all of those as 'C' sizes for printing purposes.
+ Printer does *not* apparently require use of a spooler!
+
32-byte header:
0f 00 00 40 00 00 00 00 00 00 00 00 00 00 01 00
@@ -1305,8 +1334,8 @@ struct dyesub_backend canonselphy_backend = {
05 (L)
02 (C)
- P == 7008800 == 2336256 * 3 + 32 (4.884% larger than CP)
- L == 5087264 == 1695744 * 3 + 32 (5.878% larger than CP)
- C == 2180384 == 726784 * 3 + 32 (3.991% larger than CP)
+ P == 7008800 == 2336256 * 3 + 32 (1872*1248)
+ L == 5087264 == 1695744 * 3 + 32 (1536*1104)
+ C == 2180384 == 726784 * 3 + 32 (1088*668)
*/