diff options
author | Asbjørn Sloth Tønnesen <ast@2e8.dk> | 2023-07-08 22:40:00 +0000 |
---|---|---|
committer | Asbjørn Sloth Tønnesen <ast@2e8.dk> | 2023-07-10 19:53:57 +0000 |
commit | e8ea33f5c777874b25b858df3ef61ca7ebed60ff (patch) | |
tree | 1b1ead3a046d8dbeb7645c24743a85df0f4f0473 | |
parent | 5a72605339cbb275277be76d1259589137d5db6b (diff) | |
download | qlprint-e8ea33f5c777874b25b858df3ef61ca7ebed60ff.tar.gz qlprint-e8ea33f5c777874b25b858df3ef61ca7ebed60ff.tar.xz qlprint-e8ea33f5c777874b25b858df3ef61ca7ebed60ff.zip |
fix coding style
-rw-r--r-- | include/ql.h | 94 | ||||
-rw-r--r-- | src/loadpng.c | 131 | ||||
-rw-r--r-- | src/main.c | 333 | ||||
-rw-r--r-- | src/ql.c | 475 |
4 files changed, 512 insertions, 521 deletions
diff --git a/include/ql.h b/include/ql.h index b854c06..5e32fda 100644 --- a/include/ql.h +++ b/include/ql.h @@ -23,33 +23,32 @@ * */ -typedef struct -{ - uint8_t print_head_mark; - uint8_t sz; - uint8_t rsvd_2; // 'B' - uint8_t model_class; - uint8_t model_code; - uint8_t rsvd_5; // '0' - uint8_t rsvd_6; // '0' - uint8_t rsvd_7; // 0x00 - uint8_t err_info_1; - uint8_t err_info_2; - uint8_t media_width_mm; - uint8_t media_type; - uint8_t rsvd_12; // 0x00 - uint8_t rsvd_13; // 0x00 - uint8_t rsvd_14; // 0x3f - uint8_t mode; - uint8_t rsvd_16; // 0x00 - uint8_t media_length_mm; - uint8_t status_type; - uint8_t phase_type; - uint8_t phase_hi; - uint8_t phase_lo; - uint8_t notification; - uint8_t rsvd_23; // 0x00 - uint8_t rsvd_24[8]; // 0x00... +typedef struct { + uint8_t print_head_mark; + uint8_t sz; + uint8_t rsvd_2; // 'B' + uint8_t model_class; + uint8_t model_code; + uint8_t rsvd_5; // '0' + uint8_t rsvd_6; // '0' + uint8_t rsvd_7; // 0x00 + uint8_t err_info_1; + uint8_t err_info_2; + uint8_t media_width_mm; + uint8_t media_type; + uint8_t rsvd_12; // 0x00 + uint8_t rsvd_13; // 0x00 + uint8_t rsvd_14; // 0x3f + uint8_t mode; + uint8_t rsvd_16; // 0x00 + uint8_t media_length_mm; + uint8_t status_type; + uint8_t phase_type; + uint8_t phase_hi; + uint8_t phase_lo; + uint8_t notification; + uint8_t rsvd_23; // 0x00 + uint8_t rsvd_24[8]; // 0x00... } ql_status_t; #define QL_ERR_1_NO_MEDIA 0x01 @@ -98,22 +97,22 @@ typedef struct #define QL_NOTIFICATION_COOLING_DONE 0x04 // Flags for expanded mode -#define QL_EXPANDED_MODE_CUT_AT_END 0x10 /* Gah, 710 doc claims 0x08! */ -#define QL_EXPANDED_MODE_HIGH_RES 0x40 /* QL-570/580N/700 */ +#define QL_EXPANDED_MODE_CUT_AT_END 0x10 /* Gah, 710 doc claims 0x08! */ +#define QL_EXPANDED_MODE_HIGH_RES 0x40 /* QL-570/580N/700 */ typedef struct { - uint16_t width; - uint16_t height; - uint8_t data[]; + uint16_t width; + uint16_t height; + uint8_t data[]; } ql_raster_image_t; typedef struct { - uint8_t threshold; // pixel values below threshold deemed black - uint8_t flags; // QL_PRINT_CFG_xxx flags, indicating which other fields valid - uint8_t media_type; - uint8_t media_width; - uint8_t media_length; - bool first_page; // used for autocut pagination + uint8_t threshold; // pixel values below threshold deemed black + uint8_t flags; // QL_PRINT_CFG_xxx flags, indicating which other fields valid + uint8_t media_type; + uint8_t media_width; + uint8_t media_length; + bool first_page; // used for autocut pagination } ql_print_cfg_t; #define QL_PRINT_CFG_MEDIA_TYPE 0x02 @@ -126,11 +125,11 @@ typedef struct ql_ctx *ql_ctx_t; ql_ctx_t ql_open(const char *printer); void ql_close(ql_ctx_t ctx); -bool ql_init(ql_ctx_t ctx); // also cancel +bool ql_init(ql_ctx_t ctx); // also cancel bool ql_request_status(ql_ctx_t ctx); -bool ql_read_status(ql_ctx_t ctx, ql_status_t *status); +bool ql_read_status(ql_ctx_t ctx, ql_status_t * status); -bool ql_needs_mode_switch(const ql_status_t *status); +bool ql_needs_mode_switch(const ql_status_t * status); bool ql_switch_to_raster_mode(ql_ctx_t ctx); bool ql_set_mode(ql_ctx_t ctx, unsigned mode); @@ -139,17 +138,18 @@ bool ql_set_autocut_every_n(ql_ctx_t ctx, uint8_t n); bool ql_set_margin(ql_ctx_t ctx, uint16_t dots); // Note: status needed for 1050/1060N detection to adjust command format -bool ql_print_raster_image(ql_ctx_t ctx, const ql_status_t *status, const ql_raster_image_t *img, const ql_print_cfg_t *cfg); +bool ql_print_raster_image(ql_ctx_t ctx, const ql_status_t * status, + const ql_raster_image_t * img, const ql_print_cfg_t * cfg); // Caution: ql_decode_*() are *not* multi-thread safe -const char *ql_decode_mode(const ql_status_t *status); -const char *ql_decode_errors(const ql_status_t *status); -const char *ql_decode_model(const ql_status_t *status); -const char *ql_decode_media_type(const ql_status_t *status); +const char *ql_decode_mode(const ql_status_t * status); +const char *ql_decode_errors(const ql_status_t * status); +const char *ql_decode_model(const ql_status_t * status); +const char *ql_decode_media_type(const ql_status_t * status); #define QL_DECODE_MODEL 0x01 #define QL_DECODE_ERROR 0x02 #define QL_DECODE_MEDIA 0x04 #define QL_DECODE_MODE 0x08 -void ql_decode_print_status(FILE *out, const ql_status_t *status, unsigned flags); +void ql_decode_print_status(FILE * out, const ql_status_t * status, unsigned flags); #endif diff --git a/src/loadpng.c b/src/loadpng.c index fce5066..ed12886 100644 --- a/src/loadpng.c +++ b/src/loadpng.c @@ -10,95 +10,92 @@ #include <assert.h> #include <png.h> -static_assert(sizeof(png_byte) == sizeof( ((ql_raster_image_t *)0)->data[0]), "Code relies on png_byte being compatible with ql_raster_image_t data "); +static_assert(sizeof(png_byte) == sizeof(((ql_raster_image_t *) 0)->data[0]), + "Code relies on png_byte being compatible with ql_raster_image_t data "); ql_raster_image_t *loadpng(const char *path) { - ql_raster_image_t *ret = NULL; + ql_raster_image_t *ret = NULL; - if (!path) - goto out; + if (!path) + goto out; - FILE *f = fopen(path, "rb"); - if (!f) - goto out; + FILE *f = fopen(path, "rb"); + if (!f) + goto out; - uint8_t header[8]; - if (fread(header, 1, sizeof(header), f) != 8) - goto close_out; + uint8_t header[8]; + if (fread(header, 1, sizeof(header), f) != 8) + goto close_out; - if (!png_check_sig(header, sizeof(header))) - goto close_out; + if (!png_check_sig(header, sizeof(header))) + goto close_out; - png_infop info_ptr = NULL, end_ptr = NULL; - png_structp png_ptr = - png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - goto close_out; + png_infop info_ptr = NULL, end_ptr = NULL; + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + goto close_out; - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - goto destroy_read_out; + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + goto destroy_read_out; - end_ptr = png_create_info_struct(png_ptr); - if (!end_ptr) - goto destroy_read_out; + end_ptr = png_create_info_struct(png_ptr); + if (!end_ptr) + goto destroy_read_out; - if (setjmp(png_jmpbuf(png_ptr))) - goto destroy_read_out; + if (setjmp(png_jmpbuf(png_ptr))) + goto destroy_read_out; - png_init_io(png_ptr, f); - png_set_sig_bytes(png_ptr, sizeof(header)); + png_init_io(png_ptr, f); + png_set_sig_bytes(png_ptr, sizeof(header)); - png_read_info(png_ptr, info_ptr); + png_read_info(png_ptr, info_ptr); - png_uint_32 width, height; - int bit_depth, color_type; - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, - &color_type, NULL, NULL, NULL); + png_uint_32 width, height; + int bit_depth, color_type; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - if (color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) - png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1); // force into grayscale - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand_gray_1_2_4_to_8(png_ptr); // get us a known output format + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + if (color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) + png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1); // force into grayscale + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); // get us a known output format - png_read_update_info(png_ptr, info_ptr); + png_read_update_info(png_ptr, info_ptr); - png_bytepp row_ptrs = calloc(height, sizeof(png_bytep)); - if (!row_ptrs) - goto destroy_read_out; + png_bytepp row_ptrs = calloc(height, sizeof(png_bytep)); + if (!row_ptrs) + goto destroy_read_out; - const unsigned row_bytes = width * sizeof(png_byte); - ql_raster_image_t *img = - calloc(1, sizeof(ql_raster_image_t) + height * row_bytes); - if (!img) - goto free_image_out; + const unsigned row_bytes = width * sizeof(png_byte); + ql_raster_image_t *img = calloc(1, sizeof(ql_raster_image_t) + height * row_bytes); + if (!img) + goto free_image_out; - if (setjmp(png_jmpbuf(png_ptr))) - goto free_image_out; + if (setjmp(png_jmpbuf(png_ptr))) + goto free_image_out; - for (png_uint_32 i = 0; i < height; ++i) - row_ptrs[i] = (png_bytep)(img->data + (i * row_bytes)); + for (png_uint_32 i = 0; i < height; ++i) + row_ptrs[i] = (png_bytep) (img->data + (i * row_bytes)); - png_read_image(png_ptr, row_ptrs); - png_read_end(png_ptr, end_ptr); + png_read_image(png_ptr, row_ptrs); + png_read_end(png_ptr, end_ptr); - img->height = height; - img->width = width; + img->height = height; + img->width = width; - ret = img; - img = NULL; // don't free it, we're returning it now + ret = img; + img = NULL; // don't free it, we're returning it now -free_image_out: - free(img); - free(row_ptrs); -destroy_read_out: - png_destroy_read_struct( - &png_ptr, info_ptr ? &info_ptr : NULL, end_ptr ? &end_ptr : NULL); -close_out: - fclose(f); -out: - return ret; + free_image_out: + free(img); + free(row_ptrs); + destroy_read_out: + png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, end_ptr ? &end_ptr : NULL); + close_out: + fclose(f); + out: + return ret; } @@ -18,103 +18,116 @@ static bool timed_out = false; void on_alarm(int ignored) { - (void)ignored; - timed_out = true; + (void)ignored; + timed_out = true; } - void syntax(void) { - fprintf(stderr, -"Syntax:\n" -" qlprint [-p lp] -i\n" -" [-p lp] [-m margin] [-a] [-C|-D] [-W width] [-L length] [-Q] [-n num] [-t threshold] [-x timeout] png...\n" -"Where:\n" -" -p lp Printer port (default /dev/usb/lp0)\n" -" -i Print status information only, then exit\n" -" -m margin Margin (dots)\n" -" -a Enable auto-cut\n" -" -C Request continuous-length-tape when printing (error if not)\n" -" -D Request die-cut-labels when printing (error if not)\n" -" -W width Request particular width media when printing (error if not)\n" -" -L length Request particular length media when printing (error if not)\n" -" -Q Prioritise quality of speed\n" -" -n num Print num copies\n" -" -t threshold Threshold for black-vs-white (default 128, i.e. 0-127=black)\n" -" -x timeout Time to wait for successful print, in seconds (default 5)\n" -" png... One or more png files to print\n" -"\n"); - - exit(EXIT_FAILURE); + fprintf(stderr, + "Syntax:\n" + " qlprint [-p lp] -i\n" + " [-p lp] [-m margin] [-a] [-C|-D] [-W width] [-L length] [-Q] [-n num] [-t threshold] [-x timeout] png...\n" + "Where:\n" + " -p lp Printer port (default /dev/usb/lp0)\n" + " -i Print status information only, then exit\n" + " -m margin Margin (dots)\n" + " -a Enable auto-cut\n" + " -C Request continuous-length-tape when printing (error if not)\n" + " -D Request die-cut-labels when printing (error if not)\n" + " -W width Request particular width media when printing (error if not)\n" + " -L length Request particular length media when printing (error if not)\n" + " -Q Prioritise quality of speed\n" + " -n num Print num copies\n" + " -t threshold Threshold for black-vs-white (default 128, i.e. 0-127=black)\n" + " -x timeout Time to wait for successful print, in seconds (default 5)\n" + " png... One or more png files to print\n" "\n"); + + exit(EXIT_FAILURE); } -int main (int argc, char *argv[]) +int main(int argc, char *argv[]) { - bool info_only = false; - int32_t margin = -1; - bool autocut = false; - int num = 1; - ql_print_cfg_t cfg = { - .threshold = 0x80, - .flags = 0 - }; - const char *printer = "/dev/usb/lp0"; - unsigned timeout = 5; - int opt; - while ((opt = getopt(argc, argv, "ip:m:an:CDW:L:Qx:")) != -1) - { - switch(opt) - { - case 'i': info_only = true; break; - case 'p': printer = optarg; break; - case 'm': margin = atoi(optarg); break; - case 'a': autocut = true; break; - case 'n': num = atoi(optarg); break; - case 'C': cfg.media_type = QL_MEDIA_TYPE_CONTINUOUS; - cfg.flags |= QL_PRINT_CFG_MEDIA_TYPE; break; - case 'D': cfg.media_type = QL_MEDIA_TYPE_DIECUT_LABELS; - cfg.flags |= QL_PRINT_CFG_MEDIA_TYPE; break; - case 'W': cfg.media_width = atoi(optarg); - cfg.flags |= QL_PRINT_CFG_MEDIA_WIDTH; break; - case 'L': cfg.media_length = atoi(optarg); - cfg.flags |= QL_PRINT_CFG_MEDIA_LENGTH; break; - case 'Q': cfg.flags |= QL_PRINT_CFG_QUALITY_PRIO; break; - case 'x': timeout = atoi(optarg); break; - default: syntax(); - } - } - - if (optind >= argc && !info_only) - syntax(); - - ql_ctx_t ctx = ql_open(printer); - if (!ctx) - { - fprintf(stderr, "Unable to open '%s': %s\n", printer, strerror(errno)); - return EXIT_FAILURE; - } - - if (!ql_init(ctx)) - { - fprintf(stderr, "Failed to send initialisation sequence to printer: %s\n", - strerror(errno)); - return EXIT_FAILURE; - } - - if (!ql_request_status(ctx)) - { - fprintf(stderr, "Failed to request status from printer: %s\n", - strerror(errno)); - return EXIT_FAILURE; - } - - ql_status_t status = { 0, }; - if (!ql_read_status(ctx, &status)) - { - fprintf(stderr, "Failed to read status from printer: %s\n", - strerror(errno)); - return EXIT_FAILURE; - } + bool info_only = false; + int32_t margin = -1; + bool autocut = false; + int num = 1; + ql_print_cfg_t cfg = { + .threshold = 0x80, + .flags = 0 + }; + const char *printer = "/dev/usb/lp0"; + unsigned timeout = 5; + int opt; + while ((opt = getopt(argc, argv, "ip:m:an:CDW:L:Qx:")) != -1) { + switch (opt) { + case 'i': + info_only = true; + break; + case 'p': + printer = optarg; + break; + case 'm': + margin = atoi(optarg); + break; + case 'a': + autocut = true; + break; + case 'n': + num = atoi(optarg); + break; + case 'C': + cfg.media_type = QL_MEDIA_TYPE_CONTINUOUS; + cfg.flags |= QL_PRINT_CFG_MEDIA_TYPE; + break; + case 'D': + cfg.media_type = QL_MEDIA_TYPE_DIECUT_LABELS; + cfg.flags |= QL_PRINT_CFG_MEDIA_TYPE; + break; + case 'W': + cfg.media_width = atoi(optarg); + cfg.flags |= QL_PRINT_CFG_MEDIA_WIDTH; + break; + case 'L': + cfg.media_length = atoi(optarg); + cfg.flags |= QL_PRINT_CFG_MEDIA_LENGTH; + break; + case 'Q': + cfg.flags |= QL_PRINT_CFG_QUALITY_PRIO; + break; + case 'x': + timeout = atoi(optarg); + break; + default: + syntax(); + } + } + + if (optind >= argc && !info_only) + syntax(); + + ql_ctx_t ctx = ql_open(printer); + if (!ctx) { + fprintf(stderr, "Unable to open '%s': %s\n", printer, strerror(errno)); + return EXIT_FAILURE; + } + + if (!ql_init(ctx)) { + fprintf(stderr, "Failed to send initialisation sequence to printer: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + + if (!ql_request_status(ctx)) { + fprintf(stderr, "Failed to request status from printer: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + ql_status_t status = { 0, }; + if (!ql_read_status(ctx, &status)) { + fprintf(stderr, "Failed to read status from printer: %s\n", strerror(errno)); + return EXIT_FAILURE; + } /* for (int i = 0; i < 32; ++i) @@ -122,44 +135,37 @@ for (int i = 0; i < 32; ++i) printf("\n"); */ - if (info_only) - { - ql_decode_print_status(stdout, &status, - QL_DECODE_MODEL | QL_DECODE_MEDIA | QL_DECODE_ERROR | QL_DECODE_MODE); - return EXIT_SUCCESS; - } - - if (margin >= 0 && !ql_set_margin(ctx, (uint16_t)margin)) - { - fprintf(stderr, "Failed to set margin: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - if (autocut && - (!ql_set_mode(ctx, QL_MODE_AUTOCUT) || - !ql_set_autocut_every_n(ctx, argc - optind))) - { - fprintf(stderr, "Failed to set autocut: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - if (ql_needs_mode_switch(&status) && !ql_switch_to_raster_mode(ctx)) - { - fprintf(stderr, "Failed to set raster mode: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - signal(SIGALRM, on_alarm); - while (num--) - { - cfg.first_page = true; - for (int i = optind; i < argc; ++i) - { - ql_raster_image_t *img = loadpng(argv[i]); - if (!img) - { - fprintf(stderr, "Failed to load image '%s'\n", argv[i]); - return EXIT_FAILURE; - } + if (info_only) { + ql_decode_print_status(stdout, &status, + QL_DECODE_MODEL | QL_DECODE_MEDIA | QL_DECODE_ERROR | + QL_DECODE_MODE); + return EXIT_SUCCESS; + } + + if (margin >= 0 && !ql_set_margin(ctx, (uint16_t) margin)) { + fprintf(stderr, "Failed to set margin: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + if (autocut && (!ql_set_mode(ctx, QL_MODE_AUTOCUT) + || !ql_set_autocut_every_n(ctx, argc - optind))) { + fprintf(stderr, "Failed to set autocut: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + if (ql_needs_mode_switch(&status) && !ql_switch_to_raster_mode(ctx)) { + fprintf(stderr, "Failed to set raster mode: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + signal(SIGALRM, on_alarm); + while (num--) { + cfg.first_page = true; + for (int i = optind; i < argc; ++i) { + ql_raster_image_t *img = loadpng(argv[i]); + if (!img) { + fprintf(stderr, "Failed to load image '%s'\n", argv[i]); + return EXIT_FAILURE; + } /* for(int i = 0; i < img->height; ++i) { @@ -168,41 +174,38 @@ for(int i = 0; i < img->height; ++i) printf("\n"); } */ - if (!ql_print_raster_image(ctx, &status, img, &cfg)) - { - fprintf(stderr, "Failed to print '%s' (%ux%u)\n", - argv[i], img->width, img->height); - return EXIT_FAILURE; - } - alarm(timeout); - do { - if (!ql_read_status(ctx, &status)) - { - if (!timed_out) // try again, soon - { - usleep(50); - continue; - } - fprintf(stderr, "Printer stopped responding!\n"); - return EXIT_FAILURE; - } - if (status.err_info_1 || status.err_info_2) - { - fprintf(stderr, "Printer reported error(s): %s\n", - ql_decode_errors(&status)); - return EXIT_FAILURE; - } - } while (status.status_type != QL_STATUS_TYPE_PRINTING_DONE); - alarm(0); - - printf("%s (%ux%u) OK\n", argv[i], img->width, img->height); - - free(img); - cfg.first_page = false; - } - } - - ql_close(ctx); - - return EXIT_SUCCESS; + if (!ql_print_raster_image(ctx, &status, img, &cfg)) { + fprintf(stderr, "Failed to print '%s' (%ux%u)\n", argv[i], + img->width, img->height); + return EXIT_FAILURE; + } + alarm(timeout); + do { + if (!ql_read_status(ctx, &status)) { + if (!timed_out) // try again, soon + { + usleep(50); + continue; + } + fprintf(stderr, "Printer stopped responding!\n"); + return EXIT_FAILURE; + } + if (status.err_info_1 || status.err_info_2) { + fprintf(stderr, "Printer reported error(s): %s\n", + ql_decode_errors(&status)); + return EXIT_FAILURE; + } + } while (status.status_type != QL_STATUS_TYPE_PRINTING_DONE); + alarm(0); + + printf("%s (%ux%u) OK\n", argv[i], img->width, img->height); + + free(img); + cfg.first_page = false; + } + } + + ql_close(ctx); + + return EXIT_SUCCESS; } @@ -12,10 +12,9 @@ #include <stdlib.h> #include <string.h> -struct ql_ctx -{ - char *printer; - int fd; +struct ql_ctx { + char *printer; + int fd; }; #define ESC 0x1b @@ -26,308 +25,300 @@ struct ql_ctx ssize_t retry_write(int fd, const char *buf, size_t len) { - size_t written = 0; - while (written != len) - { - ssize_t n = write(fd, buf + written, len - written); - if (n == -1) - { - if (errno == EAGAIN || errno == EINTR) - continue; - else - break; - } - else - written += n; - } - return written; + size_t written = 0; + while (written != len) { + ssize_t n = write(fd, buf + written, len - written); + if (n == -1) { + if (errno == EAGAIN || errno == EINTR) + continue; + else + break; + } else + written += n; + } + return written; } - ql_ctx_t ql_open(const char *printer) { - int fd = open(printer, O_RDWR); - if (fd < 0) - return NULL; + int fd = open(printer, O_RDWR); + if (fd < 0) + return NULL; - ql_ctx_t ctx = malloc(sizeof(struct ql_ctx)); - if (!ctx) - return NULL; - ctx->printer = strdup(printer); - ctx->fd = fd; + ql_ctx_t ctx = malloc(sizeof(struct ql_ctx)); + if (!ctx) + return NULL; + ctx->printer = strdup(printer); + ctx->fd = fd; - const char clear[200] = { 0, }; - (void)full_write(fd, clear); // recommended to clear old/errored jobs + const char clear[200] = { 0, }; + (void)full_write(fd, clear); // recommended to clear old/errored jobs - return ctx; + return ctx; } void ql_close(ql_ctx_t ctx) { - free(ctx->printer); - close(ctx->fd); - free(ctx); + free(ctx->printer); + close(ctx->fd); + free(ctx); } bool ql_init(ql_ctx_t ctx) { - const char init[] = { ESC, '@' }; - return full_write(ctx->fd, init); + const char init[] = { ESC, '@' }; + return full_write(ctx->fd, init); } - bool ql_request_status(ql_ctx_t ctx) { - const char status_req[] = { ESC, 'i', 'S' }; - return full_write(ctx->fd, status_req); + const char status_req[] = { ESC, 'i', 'S' }; + return full_write(ctx->fd, status_req); } - -bool ql_read_status(ql_ctx_t ctx, ql_status_t *status) +bool ql_read_status(ql_ctx_t ctx, ql_status_t * status) { - for (int i = 0; i < NUM_STATUS_READ_RETRIES; ++i) - { - int ret = read(ctx->fd, status, sizeof(*status)); - if (ret == 32) - return true; - else if ( (ret == 0) // "no data yet, too bad we just eof'd your fd, sucker" - || (ret == -1 && errno == EBADF)) // in case we messed up, somehow - { - close(ctx->fd); - ctx->fd = open(ctx->printer, O_RDWR); - if (ctx->fd < 0) - return false; - } - else if (ret == -1 && (errno != EAGAIN || errno != EINTR)) - return false; // non-recoverable - } - errno = ETIME; - return false; + for (int i = 0; i < NUM_STATUS_READ_RETRIES; ++i) { + int ret = read(ctx->fd, status, sizeof(*status)); + if (ret == 32) + return true; + else if ((ret == 0) // "no data yet, too bad we just eof'd your fd, sucker" + || (ret == -1 && errno == EBADF)) // in case we messed up, somehow + { + close(ctx->fd); + ctx->fd = open(ctx->printer, O_RDWR); + if (ctx->fd < 0) + return false; + } else if (ret == -1 && (errno != EAGAIN || errno != EINTR)) + return false; // non-recoverable + } + errno = ETIME; + return false; } - bool ql_set_mode(ql_ctx_t ctx, unsigned mode) { - char cmd[] = { ESC, 'i', 'M', mode }; - return full_write(ctx->fd, cmd); + char cmd[] = { ESC, 'i', 'M', mode }; + return full_write(ctx->fd, cmd); } - bool ql_set_expanded_mode(ql_ctx_t ctx, unsigned mode) { - char cmd[] = { ESC, 'i', 'K', mode }; - return full_write(ctx->fd, cmd); + char cmd[] = { ESC, 'i', 'K', mode }; + return full_write(ctx->fd, cmd); } - bool ql_set_autocut_every_n(ql_ctx_t ctx, uint8_t n) { - char cmd[] = { ESC, 'i', 'A', n }; - return full_write(ctx->fd, cmd); + char cmd[] = { ESC, 'i', 'A', n }; + return full_write(ctx->fd, cmd); } - bool ql_set_margin(ql_ctx_t ctx, uint16_t dots) { - char cmd[] = { ESC, 'i', 'd', dots & 0xff, dots >> 8}; - return full_write(ctx->fd, cmd); + char cmd[] = { ESC, 'i', 'd', dots & 0xff, dots >> 8 }; + return full_write(ctx->fd, cmd); } - -bool ql_needs_mode_switch(const ql_status_t *status) +bool ql_needs_mode_switch(const ql_status_t * status) { - switch(status->model_code) - { - case '3': case '4': - case 'P': case 'Q': - return true; - default: break; - } - return false; + switch (status->model_code) { + case '3': + case '4': + case 'P': + case 'Q': + return true; + default: + break; + } + return false; } - bool ql_switch_to_raster_mode(ql_ctx_t ctx) { - #define MODE_ESC_P 0 - #define MODE_RASTER 1 - #define MODE_P_TOUCH_TEMPLATE 3 - char cmd[] = { ESC, 'i', 'a', MODE_RASTER }; - return full_write(ctx->fd, cmd); +#define MODE_ESC_P 0 +#define MODE_RASTER 1 +#define MODE_P_TOUCH_TEMPLATE 3 + char cmd[] = { ESC, 'i', 'a', MODE_RASTER }; + return full_write(ctx->fd, cmd); } - -static void pack_column(uint8_t *out, uint16_t bytes, uint16_t colno, const ql_raster_image_t *img, uint8_t black_below_v) +static void pack_column(uint8_t * out, uint16_t bytes, uint16_t colno, + const ql_raster_image_t * img, uint8_t black_below_v) { - for (unsigned n = 0; n < bytes; ++n, ++out) - { - *out = 0; - for (unsigned i = 0; i < 8; ++i) - { - unsigned img_row = n * 8 + i; - if (img_row < img->height) - if (img->data[img_row * img->width + colno] < black_below_v) - *out |= 1 << (7 - i); - } -//for(int i = 7; i >= 0; --i) fprintf(stderr, "%c", (*out & (1<<i)) ? '#' : '.'); - } -//fprintf(stderr,"\n"); + for (unsigned n = 0; n < bytes; ++n, ++out) { + *out = 0; + for (unsigned i = 0; i < 8; ++i) { + unsigned img_row = n * 8 + i; + if (img_row < img->height) + if (img->data[img_row * img->width + colno] < black_below_v) + *out |= 1 << (7 - i); + } + //for(int i = 7; i >= 0; --i) fprintf(stderr, "%c", (*out & (1<<i)) ? '#' : '.'); + } + //fprintf(stderr,"\n"); } - -bool ql_print_raster_image(ql_ctx_t ctx, const ql_status_t *status, const ql_raster_image_t *img, const ql_print_cfg_t *cfg) +bool ql_print_raster_image(ql_ctx_t ctx, const ql_status_t * status, + const ql_raster_image_t * img, const ql_print_cfg_t * cfg) { - unsigned dn = 90; // default raster transmission block size (720 pixels) - if (status->model_code == 'P' || status->model_code == '4') - dn = 162; // 1296 pixels - - if (img->height > dn * 8) - return false; // image too wide for printer - - char print_info[] = { ESC, 'i', 'z', - cfg->flags | 0x80, - (cfg->flags & QL_PRINT_CFG_MEDIA_TYPE) ? cfg->media_type : 0, - (cfg->flags & QL_PRINT_CFG_MEDIA_WIDTH) ? cfg->media_width : 0, - (cfg->flags & QL_PRINT_CFG_MEDIA_LENGTH) ? cfg->media_length : 0, - img->width & 0xff, img->width >> 8, 0, 0, - cfg->first_page ? 0 : 1, 0 }; - if (!full_write(ctx->fd, print_info)) - return false; - - for (unsigned w = 0; w < img->width; ++w) - { - char block[dn + 3]; - block[0] = 'g'; block[1] = 0; block[2] = dn; - pack_column((uint8_t *)block+3, dn, w, img, cfg->threshold); - if (!full_write(ctx->fd, block)) - return false; - } - - char done[] = { 0x1a }; // print with feeding - return full_write(ctx->fd, done); + unsigned dn = 90; // default raster transmission block size (720 pixels) + if (status->model_code == 'P' || status->model_code == '4') + dn = 162; // 1296 pixels + + if (img->height > dn * 8) + return false; // image too wide for printer + + char print_info[] = { ESC, 'i', 'z', + cfg->flags | 0x80, + (cfg->flags & QL_PRINT_CFG_MEDIA_TYPE) ? cfg->media_type : 0, + (cfg->flags & QL_PRINT_CFG_MEDIA_WIDTH) ? cfg->media_width : 0, + (cfg->flags & QL_PRINT_CFG_MEDIA_LENGTH) ? cfg->media_length : 0, + img->width & 0xff, img->width >> 8, 0, 0, + cfg->first_page ? 0 : 1, 0 + }; + if (!full_write(ctx->fd, print_info)) + return false; + + for (unsigned w = 0; w < img->width; ++w) { + char block[dn + 3]; + block[0] = 'g'; + block[1] = 0; + block[2] = dn; + pack_column((uint8_t *) block + 3, dn, w, img, cfg->threshold); + if (!full_write(ctx->fd, block)) + return false; + } + + char done[] = { 0x1a }; // print with feeding + return full_write(ctx->fd, done); } - -const char *ql_decode_model(const ql_status_t *status) +const char *ql_decode_model(const ql_status_t * status) { - switch(status->model_code) - { - case '1': return "QL-560"; - case '2': return "QL-570"; - case '3': return "QL-580N"; - case '4': return "QL-1060N"; - case '5': return "QL-700"; - case '6': return "QL-710W"; - case '7': return "QL-720NW"; - case 'O': return "QL-500/550"; - case 'P': return "QL-1050"; - case 'Q': return "QL-650TD"; - default: - { - static char buf[] = "unrecognised (type code 0x$$)"; - char *q = strchr(buf, '$'); - sprintf(q, "%02hhx)", status->model_code); - return buf; - } - } + switch (status->model_code) { + case '1': + return "QL-560"; + case '2': + return "QL-570"; + case '3': + return "QL-580N"; + case '4': + return "QL-1060N"; + case '5': + return "QL-700"; + case '6': + return "QL-710W"; + case '7': + return "QL-720NW"; + case 'O': + return "QL-500/550"; + case 'P': + return "QL-1050"; + case 'Q': + return "QL-650TD"; + default: + { + static char buf[] = "unrecognised (type code 0x$$)"; + char *q = strchr(buf, '$'); + sprintf(q, "%02hhx)", status->model_code); + return buf; + } + } } -const char *ql_decode_mode(const ql_status_t *status) +const char *ql_decode_mode(const ql_status_t * status) { - if (status->mode & QL_MODE_AUTOCUT) - return "auto-cut"; - else - return "no-auto-cut"; + if (status->mode & QL_MODE_AUTOCUT) + return "auto-cut"; + else + return "no-auto-cut"; } -const char *ql_decode_errors(const ql_status_t *status) +const char *ql_decode_errors(const ql_status_t * status) { - typedef struct { - uint16_t bit; - const char *str; - } strmap_t; - - #define ERR1(x) (x << 0) - #define ERR2(x) (x << 8) - const strmap_t strmap[] = { - { ERR1(QL_ERR_1_NO_MEDIA), "no-media " }, - { ERR1(QL_ERR_1_END_OF_MEDIA), "end-of-media " }, - { ERR1(QL_ERR_1_CUTTER_JAM), "cutter-jam " }, - { ERR1(QL_ERR_1_PRINTER_IN_USE), "printer-in-use " }, - { ERR1(QL_ERR_1_PRINTER_TURNED_OFF), "printer-turned-off " }, - { ERR1(QL_ERR_1_HIGH_VOLTAGE_ADAPTER), "high-voltage-adapter " }, - { ERR1(QL_ERR_1_FAN_MOTOR_ERROR), "fan-motor-error " }, - - { ERR2(QL_ERR_2_REPLACE_MEDIA), "replace-media " }, - { ERR2(QL_ERR_2_EXPANSION_BUFFER_FULL), "expansion-buffer-full " }, - { ERR2(QL_ERR_2_COMMUNICATION_ERROR), "communication-error " }, - { ERR2(QL_ERR_2_COMMUNICATION_BUFFER_FULL), "communication-buffer-full " }, - { ERR2(QL_ERR_2_COVER_OPEN), "cover-open " }, - { ERR2(QL_ERR_2_CANCEL_KEY), "cancel-key-pressed " }, - { ERR2(QL_ERR_2_MEDIA_CANNOT_BE_FED), "media-cannot-be-fed " }, - { ERR2(QL_ERR_2_SYSTEM_ERROR), "system-error " } - }; - - static char *buf = 0; - if (!buf) - { - int len = 0; - for (unsigned i = 0; i < (sizeof(strmap)/sizeof(strmap[0])); ++i) - len += strlen(strmap[i].str); - buf = malloc(len + 1); - if (!buf) - return "<host-out-of-memory>"; - } - - uint16_t errs = ERR1(status->err_info_1) | ERR2(status->err_info_2); - buf[0] = 0; - for (unsigned i = 0; i < (sizeof(strmap)/sizeof(strmap[0])); ++i) - { - if (errs & strmap[i].bit) - strcat(buf, strmap[i].str); - } - return (buf[0] == 0) ? "none" : buf; + typedef struct { + uint16_t bit; + const char *str; + } strmap_t; + +#define ERR1(x) (x << 0) +#define ERR2(x) (x << 8) + const strmap_t strmap[] = { + {ERR1(QL_ERR_1_NO_MEDIA), "no-media "}, + {ERR1(QL_ERR_1_END_OF_MEDIA), "end-of-media "}, + {ERR1(QL_ERR_1_CUTTER_JAM), "cutter-jam "}, + {ERR1(QL_ERR_1_PRINTER_IN_USE), "printer-in-use "}, + {ERR1(QL_ERR_1_PRINTER_TURNED_OFF), "printer-turned-off "}, + {ERR1(QL_ERR_1_HIGH_VOLTAGE_ADAPTER), "high-voltage-adapter "}, + {ERR1(QL_ERR_1_FAN_MOTOR_ERROR), "fan-motor-error "}, + + {ERR2(QL_ERR_2_REPLACE_MEDIA), "replace-media "}, + {ERR2(QL_ERR_2_EXPANSION_BUFFER_FULL), "expansion-buffer-full "}, + {ERR2(QL_ERR_2_COMMUNICATION_ERROR), "communication-error "}, + {ERR2(QL_ERR_2_COMMUNICATION_BUFFER_FULL), "communication-buffer-full "}, + {ERR2(QL_ERR_2_COVER_OPEN), "cover-open "}, + {ERR2(QL_ERR_2_CANCEL_KEY), "cancel-key-pressed "}, + {ERR2(QL_ERR_2_MEDIA_CANNOT_BE_FED), "media-cannot-be-fed "}, + {ERR2(QL_ERR_2_SYSTEM_ERROR), "system-error "} + }; + + static char *buf = 0; + if (!buf) { + int len = 0; + for (unsigned i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) + len += strlen(strmap[i].str); + buf = malloc(len + 1); + if (!buf) + return "<host-out-of-memory>"; + } + + uint16_t errs = ERR1(status->err_info_1) | ERR2(status->err_info_2); + buf[0] = 0; + for (unsigned i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) { + if (errs & strmap[i].bit) + strcat(buf, strmap[i].str); + } + return (buf[0] == 0) ? "none" : buf; } -const char *ql_decode_media_type(const ql_status_t *status) +const char *ql_decode_media_type(const ql_status_t * status) { - switch(status->media_type) - { - case QL_MEDIA_TYPE_NO_MEDIA: return "no-media"; - case QL_MEDIA_TYPE_CONTINUOUS: - case QL_MEDIA_TYPE_CONTINUOUS_ALT: - return "continuous-length-tape"; - case QL_MEDIA_TYPE_DIECUT_LABELS: - case QL_MEDIA_TYPE_DIECUT_LABELS_ALT: - return "die-cut-labels"; - default: { - static char buf[] = "unknown (code 0x$$)"; - char *q = strchr(buf, '$'); - sprintf(q, "%02hhx)", status->media_type); - return buf; - } - } + switch (status->media_type) { + case QL_MEDIA_TYPE_NO_MEDIA: + return "no-media"; + case QL_MEDIA_TYPE_CONTINUOUS: + case QL_MEDIA_TYPE_CONTINUOUS_ALT: + return "continuous-length-tape"; + case QL_MEDIA_TYPE_DIECUT_LABELS: + case QL_MEDIA_TYPE_DIECUT_LABELS_ALT: + return "die-cut-labels"; + default:{ + static char buf[] = "unknown (code 0x$$)"; + char *q = strchr(buf, '$'); + sprintf(q, "%02hhx)", status->media_type); + return buf; + } + } } -void ql_decode_print_status(FILE *f, const ql_status_t *status, unsigned flags) +void ql_decode_print_status(FILE * f, const ql_status_t * status, unsigned flags) { - if (!status) - return; - - const char *fmt_s = "%17s: %s\n"; - const char *fmt_u = "%17s: %u\n"; - if (flags & QL_DECODE_MODEL) - fprintf(f, fmt_s, "Printer", ql_decode_model(status)); - if (flags & QL_DECODE_MODE) - fprintf(f, fmt_s, "Mode", ql_decode_mode(status)); - if (flags & QL_DECODE_ERROR) - fprintf(f, fmt_s, "Errors", ql_decode_errors(status)); - if (flags & QL_DECODE_MEDIA) - { - fprintf(f, fmt_s, "Media type", ql_decode_media_type(status)); - fprintf(f, fmt_u, "Media width (mm)", status->media_width_mm); - if (status->media_type != QL_MEDIA_TYPE_CONTINUOUS) - fprintf(f, fmt_u, "Media length (mm)", status->media_length_mm); - } + if (!status) + return; + + const char *fmt_s = "%17s: %s\n"; + const char *fmt_u = "%17s: %u\n"; + if (flags & QL_DECODE_MODEL) + fprintf(f, fmt_s, "Printer", ql_decode_model(status)); + if (flags & QL_DECODE_MODE) + fprintf(f, fmt_s, "Mode", ql_decode_mode(status)); + if (flags & QL_DECODE_ERROR) + fprintf(f, fmt_s, "Errors", ql_decode_errors(status)); + if (flags & QL_DECODE_MEDIA) { + fprintf(f, fmt_s, "Media type", ql_decode_media_type(status)); + fprintf(f, fmt_u, "Media width (mm)", status->media_width_mm); + if (status->media_type != QL_MEDIA_TYPE_CONTINUOUS) + fprintf(f, fmt_u, "Media length (mm)", status->media_length_mm); + } } - |