From b038aa71c178fa468295f191ef1cf553e063166e Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 18 Jul 2013 18:03:40 -0400 Subject: [PATCH] kodak6800: 75% of new backend migration completed. Main loop is all that's left. --- .gitignore | 1 + Makefile | 25 +- backend_common.c | 19 +- backend_common.h | 6 +- kodak6800_print.c | 750 +++++++++++++++++++++------------------------- 5 files changed, 367 insertions(+), 434 deletions(-) diff --git a/.gitignore b/.gitignore index 0c068a1..6601397 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *~ sonyupdr150 +kodak6800 gutenprint diff --git a/Makefile b/Makefile index a277934..b44adfb 100644 --- a/Makefile +++ b/Makefile @@ -2,28 +2,21 @@ CFLAGS = -Wall LDFLAGS = -lusb-1.0 CUPS_BACKEND_DIR = /usr/lib/cups/backend -DEPS = backend_common.c backend_common.h +DEPS = backend_common.h +SOURCES = sony_updr150_print.c kodak6800_print.c backend_common.c -all: gutenprint sonyupdr150 +all: gutenprint sonyupdr150 kodak6800 -gutenprint: sony_updr150_print.c $(DEPS) - gcc -o $@ $< backend_common.c $(LDFLAGS) $(CFLAGS) - -canon-selphy_print: selphy_print.c $(DEPS) - gcc -o $@ $< $(LDFLAGS) $(CFLAGS) - -kodak-6800_print: kodak6800_print.c $(DEPS) - gcc -o $@ $< $(LDFLAGS) $(CFLAGS) - -kodak-1400_print: kodak1400_print.c $(DEPS) - gcc -o $@ $< $(LDFLAGS) $(CFLAGS) - -shinko-s2145_print: shinko_s2145_print.c $(DEPS) - gcc -o $@ $< $(LDFLAGS) $(CFLAGS) +gutenprint: $(SOURCES) $(DEPS) + gcc -o $@ $(SOURCES) $(LDFLAGS) $(CFLAGS) sonyupdr150: ln -s gutenprint $@ +kodak6800: + ln -s gutenprint $@ + + install: install -o root -m 700 gutenprint $(CUPS_BACKEND_DIR)/gutenprint+usb diff --git a/backend_common.c b/backend_common.c index b7bc386..83b11f7 100644 --- a/backend_common.c +++ b/backend_common.c @@ -27,7 +27,7 @@ #include "backend_common.h" -#define BACKEND_VERSION "0.7" +#define BACKEND_VERSION "0.08" #ifndef URI_PREFIX #define URI_PREFIX "gutenprint+usb" #endif @@ -346,6 +346,7 @@ static int find_and_enumerate(struct libusb_context *ctx, static struct dyesub_backend *backends[] = { &updr150_backend, + &kodak6800_backend, NULL, }; @@ -393,6 +394,7 @@ int main (int argc, char **argv) int copies = 1; char *uri = getenv("DEVICE_URI"); char *use_serno = NULL; + int query_only = 0; DEBUG("Multi-Call Gutenprint DyeSub CUPS Backend version %s\n", BACKEND_VERSION); @@ -412,14 +414,14 @@ int main (int argc, char **argv) if (!backend) { DEBUG("CUPS Usage:\n\tDEVICE_URI=someuri %s job user title num-copies options [ filename ]\n\n", URI_PREFIX); - DEBUG("Internal Backends:\n"); + DEBUG("Internal Backends: (prefix with SERIAL=serno for specific device)\n"); for (i = 0; ; i++) { backend = backends[i]; if (!backend) break; DEBUG(" %s backend version %s (BACKEND=%s)\n", backend->name, backend->version, backend->uri_prefix); - DEBUG(" Standalone Usage: (prefix with SERIAL=serno for specific device)\n"); + DEBUG(" Standalone Usage:\n"); DEBUG("\t\t%s [ infile | - ]\n", backend->uri_prefix); @@ -510,6 +512,10 @@ int main (int argc, char **argv) exit(1); } + if (backend->cmdline_arg(NULL, 0, argv[1], argv[2])) { + query_only = 1; + } + /* Open Input File */ if (strcmp("-", argv[1])) { data_fd = open(argv[1], O_RDONLY); @@ -576,11 +582,16 @@ int main (int argc, char **argv) /* Initialize backend */ backend_ctx = backend->init(dev, endp_up, endp_down); + + if (query_only) { + backend->cmdline_arg(backend_ctx, 1, argv[1], argv[2]); + goto done_claimed; + } /* Read in data */ if (backend->read_parse(backend_ctx, data_fd)) exit(1); - + close(data_fd); /* Time for the main processing loop */ diff --git a/backend_common.h b/backend_common.h index 6b3a70f..380ddf8 100644 --- a/backend_common.h +++ b/backend_common.h @@ -87,13 +87,10 @@ struct dyesub_backend { void *(*init)(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down); void (*teardown)(void *ctx); + int (*cmdline_arg)(void *ctx, int run, char *arg1, char *arg2); int (*read_parse)(void *ctx, int data_fd); int (*main_loop)(void *ctx, int copies); }; -/* XXX - - Cmdline Args Present - - Cmdline Arg Handling -*/ /* To enumerate supported devices */ enum { @@ -127,5 +124,6 @@ extern int terminate; /* External data */ extern struct dyesub_backend updr150_backend; +extern struct dyesub_backend kodak6800_backend; #endif /* __BACKEND_COMMON_H */ diff --git a/kodak6800_print.c b/kodak6800_print.c index 4e4a661..7147d44 100644 --- a/kodak6800_print.c +++ b/kodak6800_print.c @@ -35,224 +35,9 @@ #include #include -#define VERSION "0.14" -#define URI_PREFIX "kodak6800://" -#define STR_LEN_MAX 64 - -#include "backend_common.c" - -/* Program states */ -enum { - S_IDLE = 0, - S_PRINTER_READY_HDR, - S_PRINTER_SENT_HDR, - S_PRINTER_SENT_HDR2, - S_PRINTER_SENT_DATA, - S_FINISHED, -}; - -struct kodak6800_hdr { - uint8_t hdr[9]; - uint8_t copies; - uint16_t columns; /* BE */ - uint16_t rows; /* BE */ - uint8_t media; /* 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ - uint8_t laminate; /* 0x01 to laminate, 0x00 for not */ - uint8_t unk1; /* 0x00, 0x01 [may be print mode] */ -} __attribute__((packed)); - -#define CMDBUF_LEN 17 -#define READBACK_LEN 58 - -#define UPDATE_SIZE 1536 -static int get_tonecurve(char *fname, libusb_device_handle *dev, - uint8_t endp_down, uint8_t endp_up) -{ - uint8_t cmdbuf[16]; - uint8_t respbuf[64]; - int ret, num = 0; - int i; - - uint16_t *data = malloc(UPDATE_SIZE); - - INFO("Dump Tone Curve to '%s'\n", fname); - - /* Initial Request */ - cmdbuf[0] = 0x03; - cmdbuf[1] = 0x1b; - cmdbuf[2] = 0x43; - cmdbuf[3] = 0x48; - cmdbuf[4] = 0x43; - cmdbuf[5] = 0x0c; - cmdbuf[6] = 0x54; - cmdbuf[7] = 0x4f; - cmdbuf[8] = 0x4e; - cmdbuf[9] = 0x45; - cmdbuf[10] = 0x72; - cmdbuf[11] = 0x01; - cmdbuf[12] = 0x00; - cmdbuf[13] = 0x00; - cmdbuf[14] = 0x00; - cmdbuf[15] = 0x00; - - if ((ret = send_data(dev, endp_down, - cmdbuf, 16))) - return -1; - - ret = libusb_bulk_transfer(dev, endp_up, - respbuf, - sizeof(respbuf), - &num, - 5000); - if (ret < 0 || (num != 51)) { - ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); - return ret; - } - - /* Then we can poll the data */ - cmdbuf[0] = 0x03; - cmdbuf[1] = 0x1b; - cmdbuf[2] = 0x43; - cmdbuf[3] = 0x48; - cmdbuf[4] = 0x43; - cmdbuf[5] = 0x0c; - cmdbuf[6] = 0x54; - cmdbuf[7] = 0x4f; - cmdbuf[8] = 0x4e; - cmdbuf[9] = 0x45; - cmdbuf[10] = 0x20; - for (i = 0 ; i < 24 ; i++) { - if ((ret = send_data(dev, endp_down, - cmdbuf, 11))) - return -1; - - - ret = libusb_bulk_transfer(dev, endp_up, - respbuf, - sizeof(respbuf), - &num, - 5000); - if (ret < 0 || (num != 64)) { - ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); - return ret; - } - - /* Copy into buffer */ - memcpy(((uint8_t*)data)+i*64, respbuf, 64); - } - - /* Open file and write it out */ - { - int tc_fd = open(fname, O_WRONLY|O_CREAT); - if (tc_fd < 0) - return -1; - - 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)); - } - close(tc_fd); - } - - - /* We're done */ - free(data); - - return 0; -} - -static int set_tonecurve(char *fname, libusb_device_handle *dev, - uint8_t endp_down, uint8_t endp_up) -{ - uint8_t cmdbuf[64]; - uint8_t respbuf[64]; - int ret, num = 0; - int remain; - - uint16_t *data = malloc(UPDATE_SIZE); - uint8_t *ptr; - - INFO("Set Tone Curve from '%s'\n", fname); - - /* Read in file */ - int tc_fd = open(fname, O_RDONLY); - if (tc_fd < 0) - return -1; - if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) - return -2; - close(tc_fd); - - /* Byteswap data to printer's format */ - for (ret = 0; ret < (UPDATE_SIZE-16)/2 ; ret++) { - data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); - } - - /* Initial Request */ - cmdbuf[0] = 0x03; - cmdbuf[1] = 0x1b; - cmdbuf[2] = 0x43; - cmdbuf[3] = 0x48; - cmdbuf[4] = 0x43; - cmdbuf[5] = 0x0c; - cmdbuf[6] = 0x54; - cmdbuf[7] = 0x4f; - cmdbuf[8] = 0x4e; - cmdbuf[9] = 0x45; - cmdbuf[10] = 0x77; - cmdbuf[11] = 0x01; - cmdbuf[12] = 0x00; - cmdbuf[13] = 0x00; - cmdbuf[14] = 0x00; - cmdbuf[15] = 0x00; - - if ((ret = send_data(dev, endp_down, - cmdbuf, 16))) - return -1; - - ret = libusb_bulk_transfer(dev, endp_up, - respbuf, - sizeof(respbuf), - &num, - 5000); - if (ret < 0 || (num != 51)) { - ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); - return ret; - } - - ptr = (uint8_t*) data; - remain = UPDATE_SIZE; - while (remain > 0) { - int count = remain > 63 ? 63 : remain; - - cmdbuf[0] = 0x03; - memcpy(cmdbuf+1, ptr, count); - - remain -= count; - ptr += count; - - /* Send next block over */ - if ((ret = send_data(dev, endp_down, - cmdbuf, count+1))) - return -1; - - ret = libusb_bulk_transfer(dev, endp_up, - respbuf, - sizeof(respbuf), - &num, - 5000); - if (ret < 0 || (num != 51)) { - ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); - return ret; - } - - }; - - /* We're done */ - free(data); - return 0; -} +#include "backend_common.h" +#if 0 int main (int argc, char **argv) { struct libusb_context *ctx; @@ -268,7 +53,6 @@ int main (int argc, char **argv) int i, num; int claimed; - int query_only = 0; int ret = 0; int iface = 0; int found = -1; @@ -276,182 +60,10 @@ int main (int argc, char **argv) char *uri = getenv("DEVICE_URI");; char *use_serno = NULL; - struct kodak6800_hdr hdr; - uint8_t *planedata, *cmdbuf; - uint32_t datasize; - uint8_t rdbuf[READBACK_LEN]; uint8_t rdbuf2[READBACK_LEN]; int last_state = -1, state = S_IDLE; - DEBUG("Kodak 6800 CUPS backend version " VERSION "/" BACKEND_VERSION " \n"); - - /* Cmdline help */ - if (argc < 2) { - DEBUG("Usage:\n\t%s [ infile | - ]\n\t%s job user title num-copies options [ filename ]\n\t%s [ -qtc filename | -stc filename ] \n\n", - argv[0], argv[0], argv[0]); - libusb_init(&ctx); - find_and_enumerate(ctx, &list, NULL, P_KODAK_6800, 1); - libusb_free_device_list(list, 1); - libusb_exit(ctx); - exit(1); - } - - /* 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) { - perror("ERROR:Can't open input file"); - exit(1); - } - } - - /* Ensure we're using BLOCKING I/O */ - i = fcntl(data_fd, F_GETFL, 0); - if (i < 0) { - perror("ERROR:Can't open input"); - exit(1); - } - i &= ~O_NONBLOCK; - i = fcntl(data_fd, F_SETFL, 0); - if (i < 0) { - perror("ERROR:Can't open input"); - exit(1); - } - /* Start parsing URI 'selphy://PID/SERIAL' */ - if (strncmp(URI_PREFIX, uri, strlen(URI_PREFIX))) { - ERROR("Invalid URI prefix (%s)\n", uri); - exit(1); - } - use_serno = strchr(uri, '='); - if (!use_serno || !*(use_serno+1)) { - ERROR("Invalid URI (%s)\n", uri); - exit(1); - } - use_serno++; - } else { - use_serno = getenv("DEVICE"); - - if (!strcmp("-qtc", argv[1]) || - !strcmp("-stc", argv[1])) { - query_only = 1; - goto skip_read; - } - - /* Open Input File */ - if (strcmp("-", argv[1])) { - data_fd = open(argv[1], O_RDONLY); - if (data_fd < 0) { - perror("ERROR:Can't open input file"); - exit(1); - } - } - } - - /* Ignore SIGPIPE */ - signal(SIGPIPE, SIG_IGN); - signal(SIGTERM, sigterm_handler); - - /* Read in then validate header */ - read(data_fd, &hdr, sizeof(hdr)); - 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"); - exit(1); - } - - /* Read in image data */ - cmdbuf = malloc(CMDBUF_LEN); - datasize = be16_to_cpu(hdr.rows) * be16_to_cpu(hdr.columns) * 3; - planedata = malloc(datasize); - if (!cmdbuf || !planedata) { - ERROR("Memory allocation failure!\n"); - exit(1); - } - - { - int remain; - uint8_t *ptr = planedata; - remain = datasize; - do { - ret = read(data_fd, ptr, remain); - if (ret < 0) { - ERROR("Read failed (%d/%d/%d)\n", - ret, remain, datasize); - perror("ERROR: Read failed"); - exit(1); - } - ptr += ret; - remain -= ret; - } while (remain); - } - close(data_fd); /* We're done reading! */ - - skip_read: - /* Libusb setup */ - libusb_init(&ctx); - found = find_and_enumerate(ctx, &list, use_serno, P_KODAK_6800, 0); - - if (found == -1) { - ERROR("Printer open failure (No suitable printers found!)\n"); - ret = 3; - goto done; - } - - ret = libusb_open(list[found], &dev); - if (ret) { - ERROR("Printer open failure (Need to be root?) (%d)\n", ret); - ret = 4; - goto done; - } - - claimed = libusb_kernel_driver_active(dev, iface); - if (claimed) { - ret = libusb_detach_kernel_driver(dev, iface); - if (ret) { - ERROR("Printer open failure (Could not detach printer from kernel)\n"); - ret = 4; - goto done_close; - } - } - - ret = libusb_claim_interface(dev, iface); - if (ret) { - ERROR("Printer open failure (Could not claim printer interface)\n"); - ret = 4; - goto done_close; - } - - ret = libusb_get_active_config_descriptor(list[found], &config); - if (ret) { - ERROR("Printer open failure (Could not fetch config descriptor)\n"); - ret = 4; - goto done_close; - } - - for (i = 0 ; i < config->interface[0].altsetting[0].bNumEndpoints ; i++) { - if ((config->interface[0].altsetting[0].endpoint[i].bmAttributes & 3) == LIBUSB_TRANSFER_TYPE_BULK) { - if (config->interface[0].altsetting[0].endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_IN) - endp_up = config->interface[0].altsetting[0].endpoint[i].bEndpointAddress; - else - endp_down = config->interface[0].altsetting[0].endpoint[i].bEndpointAddress; - } - } - - if (query_only) { - if (!strcmp("-qtc", argv[1])) - get_tonecurve(argv[2], dev, endp_down, endp_up); - if (!strcmp("-stc", argv[1])) - set_tonecurve(argv[2], dev, endp_down, endp_up); - goto done_claimed; - } - /* Time for the main processing loop */ top: @@ -596,27 +208,345 @@ top: /* Done printing */ INFO("All printing done\n"); ret = 0; - -done_claimed: - libusb_release_interface(dev, iface); - -done_close: -#if 0 - if (claimed) - libusb_attach_kernel_driver(dev, iface); -#endif - libusb_close(dev); -done: - if (planedata) - free(planedata); - if (cmdbuf) - free(cmdbuf); - - libusb_free_device_list(list, 1); - libusb_exit(ctx); - - return ret; } +#endif + +#define CMDBUF_LEN 17 + +/* Private data stucture */ +struct kodak6800_ctx { + struct libusb_device_handle *dev; + uint8_t endp_up; + uint8_t endp_down; + + uint8_t *databuf; + uint8_t cmdbuf[CMDBUF_LEN]; + int datalen; +}; + + +/* Program states */ +enum { + S_IDLE = 0, + S_PRINTER_READY_HDR, + S_PRINTER_SENT_HDR, + S_PRINTER_SENT_HDR2, + S_PRINTER_SENT_DATA, + S_FINISHED, +}; + +#define READBACK_LEN 58 + +struct kodak6800_hdr { + uint8_t hdr[9]; + uint8_t copies; + uint16_t columns; /* BE */ + uint16_t rows; /* BE */ + uint8_t media; /* 0x06 for 6x8, 0x00 for 6x4, 0x07 for 5x7 */ + uint8_t laminate; /* 0x01 to laminate, 0x00 for not */ + uint8_t unk1; /* 0x00, 0x01 [may be print mode] */ +} __attribute__((packed)); + +#define UPDATE_SIZE 1536 +static int kodak6800_get_tonecurve(struct kodak6800_ctx *ctx, char *fname) +{ + libusb_device_handle *dev = ctx->dev; + uint8_t endp_down = ctx->endp_down; + uint8_t endp_up = ctx->endp_up; + + uint8_t cmdbuf[16]; + uint8_t respbuf[64]; + int ret, num = 0; + int i; + + uint16_t *data = malloc(UPDATE_SIZE); + + INFO("Dump Tone Curve to '%s'\n", fname); + + /* Initial Request */ + cmdbuf[0] = 0x03; + cmdbuf[1] = 0x1b; + cmdbuf[2] = 0x43; + cmdbuf[3] = 0x48; + cmdbuf[4] = 0x43; + cmdbuf[5] = 0x0c; + cmdbuf[6] = 0x54; + cmdbuf[7] = 0x4f; + cmdbuf[8] = 0x4e; + cmdbuf[9] = 0x45; + cmdbuf[10] = 0x72; + cmdbuf[11] = 0x01; + cmdbuf[12] = 0x00; + cmdbuf[13] = 0x00; + cmdbuf[14] = 0x00; + cmdbuf[15] = 0x00; + + if ((ret = send_data(dev, endp_down, + cmdbuf, 16))) + return -1; + + ret = libusb_bulk_transfer(dev, endp_up, + respbuf, + sizeof(respbuf), + &num, + 5000); + if (ret < 0 || (num != 51)) { + ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); + return ret; + } + + /* Then we can poll the data */ + cmdbuf[0] = 0x03; + cmdbuf[1] = 0x1b; + cmdbuf[2] = 0x43; + cmdbuf[3] = 0x48; + cmdbuf[4] = 0x43; + cmdbuf[5] = 0x0c; + cmdbuf[6] = 0x54; + cmdbuf[7] = 0x4f; + cmdbuf[8] = 0x4e; + cmdbuf[9] = 0x45; + cmdbuf[10] = 0x20; + for (i = 0 ; i < 24 ; i++) { + if ((ret = send_data(dev, endp_down, + cmdbuf, 11))) + return -1; + + + ret = libusb_bulk_transfer(dev, endp_up, + respbuf, + sizeof(respbuf), + &num, + 5000); + if (ret < 0 || (num != 64)) { + ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); + return ret; + } + + /* Copy into buffer */ + memcpy(((uint8_t*)data)+i*64, respbuf, 64); + } + + /* Open file and write it out */ + { + int tc_fd = open(fname, O_WRONLY|O_CREAT); + if (tc_fd < 0) + return -1; + + 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)); + } + close(tc_fd); + } + + + /* We're done */ + free(data); + + return 0; +} + +static int kodak6800_set_tonecurve(struct kodak6800_ctx *ctx, char *fname) +{ + libusb_device_handle *dev = ctx->dev; + uint8_t endp_down = ctx->endp_down; + uint8_t endp_up = ctx->endp_up; + + uint8_t cmdbuf[64]; + uint8_t respbuf[64]; + int ret, num = 0; + int remain; + + uint16_t *data = malloc(UPDATE_SIZE); + uint8_t *ptr; + + INFO("Set Tone Curve from '%s'\n", fname); + + /* Read in file */ + int tc_fd = open(fname, O_RDONLY); + if (tc_fd < 0) + return -1; + if (read(tc_fd, data, UPDATE_SIZE) != UPDATE_SIZE) + return -2; + close(tc_fd); + + /* Byteswap data to printer's format */ + for (ret = 0; ret < (UPDATE_SIZE-16)/2 ; ret++) { + data[ret] = cpu_to_le16(be16_to_cpu(data[ret])); + } + + /* Initial Request */ + cmdbuf[0] = 0x03; + cmdbuf[1] = 0x1b; + cmdbuf[2] = 0x43; + cmdbuf[3] = 0x48; + cmdbuf[4] = 0x43; + cmdbuf[5] = 0x0c; + cmdbuf[6] = 0x54; + cmdbuf[7] = 0x4f; + cmdbuf[8] = 0x4e; + cmdbuf[9] = 0x45; + cmdbuf[10] = 0x77; + cmdbuf[11] = 0x01; + cmdbuf[12] = 0x00; + cmdbuf[13] = 0x00; + cmdbuf[14] = 0x00; + cmdbuf[15] = 0x00; + + if ((ret = send_data(dev, endp_down, + cmdbuf, 16))) + return -1; + + ret = libusb_bulk_transfer(dev, endp_up, + respbuf, + sizeof(respbuf), + &num, + 5000); + if (ret < 0 || (num != 51)) { + ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); + return ret; + } + + ptr = (uint8_t*) data; + remain = UPDATE_SIZE; + while (remain > 0) { + int count = remain > 63 ? 63 : remain; + + cmdbuf[0] = 0x03; + memcpy(cmdbuf+1, ptr, count); + + remain -= count; + ptr += count; + + /* Send next block over */ + if ((ret = send_data(dev, endp_down, + cmdbuf, count+1))) + return -1; + + ret = libusb_bulk_transfer(dev, endp_up, + respbuf, + sizeof(respbuf), + &num, + 5000); + if (ret < 0 || (num != 51)) { + ERROR("Failure to receive data from printer (libusb error %d: (%d/%d from 0x%02x))\n", ret, num, (int)sizeof(respbuf), endp_up); + return ret; + } + + }; + + /* We're done */ + free(data); + return 0; +} + +static void kodak6800_cmdline(char *caller) +{ + DEBUG("\t\t%s [ -qtc filename | -stc filename ]\n", caller); +} + +int kodak6800_cmdline_arg(void *vctx, int run, char *arg1, char *arg2) +{ + struct kodak6800_ctx *ctx = vctx; + + if (!run || !ctx) + return (!strcmp("-qtc", arg1) || + !strcmp("-stc", arg1)); + + if (!strcmp("-qtc", arg1)) + return kodak6800_get_tonecurve(ctx, arg2); + if (!strcmp("-stc", arg1)) + return kodak6800_set_tonecurve(ctx, arg2); + + return -1; +} + + +static void *kodak6800_init(struct libusb_device_handle *dev, + uint8_t endp_up, uint8_t endp_down) +{ + struct kodak6800_ctx *ctx = malloc(sizeof(struct kodak6800_ctx)); + if (!ctx) + return NULL; + memset(ctx, 0, sizeof(struct kodak6800_ctx)); + + ctx->endp_up = endp_up; + ctx->endp_down = endp_down; + return ctx; +} + +static void kodak6800_teardown(void *vctx) { + struct kodak6800_ctx *ctx = vctx; + + if (!ctx) + return; + + if (ctx->databuf) + free(ctx->databuf); + free(ctx); +} + +static int kodak6800_read_parse(void *vctx, int data_fd) { + struct kodak6800_ctx *ctx = vctx; + struct kodak6800_hdr hdr; + + if (!ctx) + return 1; + + /* Read in then validate header */ + read(data_fd, &hdr, sizeof(hdr)); + 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"); + return(1); + } + + ctx->datalen = be16_to_cpu(hdr.rows) * be16_to_cpu(hdr.columns) * 3; + ctx->databuf = malloc(ctx->datalen); + if (!ctx->databuf) { + ERROR("Memory allocation failure!\n"); + return 2; + } + + { + int remain = ctx->datalen; + uint8_t *ptr = ctx->databuf; + int ret; + do { + ret = read(data_fd, ptr, remain); + if (ret < 0) { + ERROR("Read failed (%d/%d/%d)\n", + ret, remain, ctx->datalen); + perror("ERROR: Read failed"); + exit(1); + } + ptr += ret; + remain -= ret; + } while (remain); + } + + return 0; +} + +/* Exported */ +struct dyesub_backend kodak6800_backend = { + .name = "Kodak 6800", + .version = "0.14", + .uri_prefix = "kodak6800", + .cmdline_usage = kodak6800_cmdline, + .cmdline_arg = kodak6800_cmdline_arg, + .init = kodak6800_init, + .teardown = kodak6800_teardown, + .read_parse = kodak6800_read_parse, +#if 0 + .main_loop = kodak6800_main_loop, +#endif +}; /* Kodak 6800/6850 data format