diff options
Diffstat (limited to 'src/cups/selphy_print.c')
-rw-r--r-- | src/cups/selphy_print.c | 107 |
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) */ |