From eab5c72c27e018c4131f8cf03fb558baa507d7c9 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 2 May 2013 20:27:32 -0400 Subject: [PATCH] selphy: Some major internal reworking, inspired by Ake Koomsin * Ignore SIGPIPE * Buffer entire job into memory before sending it to the printer * Better informational messages This patch also enables support for the CUPS backend 'num-copies' argument. Ake's patch adds much better error handling, but I need to spend more time studying it due to the major changes it has on control flow. --- selphy_print.c | 128 +++++++++++++++++++++++++++++------------- selphy_print_common.h | 3 +- 2 files changed, 90 insertions(+), 41 deletions(-) diff --git a/selphy_print.c b/selphy_print.c index 1ba63dd..c7ae460 100644 --- a/selphy_print.c +++ b/selphy_print.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -150,14 +151,10 @@ done: return printer_type; } -static int dump_data_libusb(int remaining, int present, int data_fd, - struct libusb_device_handle *dev, - uint8_t endpoint, - uint8_t *buf, uint16_t buflen) { +static int read_data(int remaining, int present, int data_fd, uint8_t *target, + uint8_t *buf, uint16_t buflen) { int cnt; - int i; int wrote = 0; - int num; while (remaining > 0) { cnt = read(data_fd, buf + present, (remaining < (buflen-present)) ? remaining : (buflen-present)); @@ -170,27 +167,12 @@ static int dump_data_libusb(int remaining, int present, int data_fd, present = 0; } - i = libusb_bulk_transfer(dev, endpoint, - buf, - cnt, - &num, - 2000); - if (i < 0) { - ERROR("libusb error %d: (%d/%d to 0x%02x)\n", i, num, cnt, endpoint); - return -1; - } + memcpy(target + wrote, buf, cnt); - if (num != cnt) { - /* Realign buffer.. */ - present = cnt - num; - memmove(buf, buf + num, present); - } - wrote += num; - remaining -= num; + wrote += cnt; + remaining -= cnt; } - DEBUG("Wrote %d bytes\n", wrote); - return wrote; } @@ -367,7 +349,7 @@ int main (int argc, char **argv) uint8_t rdbuf[READBACK_LEN], rdbuf2[READBACK_LEN]; int last_state = -1, state = S_IDLE; - int plane_len = 0; + int plane_len = 0, header_len = 0, footer_len = 0; int bw_mode = 0; int16_t paper_code_offset = -1; @@ -377,9 +359,12 @@ int main (int argc, char **argv) int data_fd = fileno(stdin); + int copies = 1; char *uri = getenv("DEVICE_URI");; char *use_serno = NULL; + uint8_t *plane_y, *plane_m, *plane_c, *footer, *header; + /* Static initialization */ setup_paper_codes(); @@ -397,6 +382,8 @@ int main (int argc, char **argv) /* Are we running as a CUPS backend? */ if (uri) { + if (argv[4]) + copies = atoi(argv[4]); if (argv[6]) { /* IOW, is it specified? */ data_fd = open(argv[6], O_RDONLY); if (data_fd < 0) { @@ -448,9 +435,35 @@ int main (int argc, char **argv) ERROR("Unrecognized printjob file format!\n"); exit(1); } - + footer_len = printers[printer_type].foot_length; + header_len = printers[printer_type].init_length; DEBUG("%sFile intended for a '%s' printer\n", bw_mode? "B/W " : "", printers[printer_type].model); + /* Set up buffers */ + plane_y = malloc(plane_len); + plane_m = malloc(plane_len); + plane_c = malloc(plane_len); + header = malloc(header_len); + footer = malloc(footer_len); + if (!plane_y || !plane_m || !plane_c || !header || + (footer_len && !footer)) { + ERROR("Memory allocation failure!\n"); + exit(1); + } + + /* Ignore SIGPIPE */ + signal(SIGPIPE, SIG_IGN); + + /* Read in entire print job */ + memcpy(header, buffer, header_len); + memmove(buffer, buffer+header_len, + MAX_HEADER-header_len); + read_data(plane_len, MAX_HEADER-header_len, data_fd, plane_y, buffer, BUF_LEN); + read_data(plane_len, 0, data_fd, plane_m, buffer, BUF_LEN); + read_data(plane_len, 0, data_fd, plane_c, buffer, BUF_LEN); + read_data(footer_len, 0, data_fd, footer, buffer, BUF_LEN); + close(data_fd); /* We're done */ + /* Libusb setup */ libusb_init(&ctx); found = find_and_enumerate(ctx, &list, use_serno, printer_type, 0); @@ -558,24 +571,22 @@ top: } break; case S_PRINTER_READY: - DEBUG("Sending init sequence (%d bytes)\n", printers[printer_type].init_length); + DEBUG("Sending init sequence (%d bytes)\n", header_len); + + INFO("Printing started\n"); /* Send printer init */ ret = libusb_bulk_transfer(dev, endp_down, - buffer, - printers[printer_type].init_length, + header, + header_len, &num, 2000); if (ret < 0) { - ERROR("libusb error %d: (%d/%d to 0x%02x)\n", ret, num, printers[printer_type].init_length, endp_down); + ERROR("libusb error %d: (%d/%d to 0x%02x)\n", ret, num, header_len, endp_down); ret = 4; goto done_claimed; } - /* Realign plane data to start of buffer.. */ - memmove(buffer, buffer+printers[printer_type].init_length, - MAX_HEADER-printers[printer_type].init_length); - state = S_PRINTER_INIT_SENT; break; case S_PRINTER_INIT_SENT: @@ -588,7 +599,11 @@ top: DEBUG("Sending BLACK plane\n"); else DEBUG("Sending YELLOW plane\n"); - ret = dump_data_libusb(plane_len, MAX_HEADER-printers[printer_type].init_length, data_fd, dev, endp_down, buffer, BUF_LEN); + ret = libusb_bulk_transfer(dev, endp_down, + plane_y, + plane_len, + &num, + 10000); if (ret < 0) { ret = 4; goto done_claimed; @@ -605,7 +620,11 @@ top: break; case S_PRINTER_READY_M: DEBUG("Sending MAGENTA plane\n"); - ret = dump_data_libusb(plane_len, 0, data_fd, dev, endp_down, buffer, BUF_LEN); + ret = libusb_bulk_transfer(dev, endp_down, + plane_m, + plane_len, + &num, + 10000); if (ret < 0) { ret = 4; goto done_claimed; @@ -619,7 +638,11 @@ top: break; case S_PRINTER_READY_C: DEBUG("Sending CYAN plane\n"); - ret = dump_data_libusb(plane_len, 0, data_fd, dev, endp_down, buffer, BUF_LEN); + ret = libusb_bulk_transfer(dev, endp_down, + plane_c, + plane_len, + &num, + 10000); if (ret < 0) { ret = 4; goto done_claimed; @@ -632,10 +655,17 @@ top: } break; case S_PRINTER_DONE: - if (printers[printer_type].foot_length) { + if (footer_len) { DEBUG("Sending cleanup sequence\n"); - ret = dump_data_libusb(printers[printer_type].foot_length, 0, data_fd, dev, endp_down, buffer, BUF_LEN); + + ret = libusb_bulk_transfer(dev, endp_down, + footer, + footer_len, + &num, + 2000); if (ret < 0) { + ERROR("libusb error %d: (%d/%d to 0x%02x)\n", ret, num, footer_len, endp_down); + ret = 4; goto done_claimed; } @@ -649,7 +679,15 @@ top: if (state != S_FINISHED) goto top; + INFO("Print complete (%d remaining)\n", copies - 1); + + if (copies && --copies) { + state = S_IDLE; + goto top; + } + /* Done printing */ + INFO("All printing done\n"); ret = 0; done_claimed: @@ -665,7 +703,17 @@ done: libusb_free_device_list(list, 1); libusb_exit(ctx); - close(data_fd); + if (plane_y) + free(plane_y); + if (plane_m) + free(plane_m); + if (plane_c) + free(plane_c); + if (header) + free(header); + if (footer) + free(footer); + return ret; } diff --git a/selphy_print_common.h b/selphy_print_common.h index a5eaefa..455d1a7 100644 --- a/selphy_print_common.h +++ b/selphy_print_common.h @@ -25,9 +25,10 @@ * */ -#define VERSION "0.44" +#define VERSION "0.45" #define DEBUG( ... ) fprintf(stderr, "DEBUG: " __VA_ARGS__ ) +#define INFO( ... ) fprintf(stderr, "INFO: " __VA_ARGS__ ) #define ERROR( ... ) fprintf(stderr, "ERROR: " __VA_ARGS__ ) #if (__BYTE_ORDER == __LITTLE_ENDIAN)