diff --git a/bin/Makefile b/bin/Makefile index a27d05a..f27db7b 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -8,9 +8,9 @@ CFLAGS += -I$(INCLUDE_PATH) LDFLAGS = TABBY = tabby -TABBY_OBJS = main.o +TABBY_OBJS = main.o grab.o print.o TABBY_STATIC = ../src/lib$(LIBNAME).a -TABBY_HEADERS = +TABBY_HEADERS = commands.h TABBY_LDFLAGS = LIBNAME = tabby diff --git a/bin/commands.h b/bin/commands.h new file mode 100644 index 0000000..aae6d7f --- /dev/null +++ b/bin/commands.h @@ -0,0 +1,7 @@ +#ifndef _COMMANDS_H +#define _COMMANDS_H + +int tabby_command_grab(int argc, char **argv); +int tabby_command_print(int argc, char **argv); + +#endif /* _COMMANDS_H */ diff --git a/bin/grab.c b/bin/grab.c new file mode 100644 index 0000000..46a96fa --- /dev/null +++ b/bin/grab.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void usage(int argc, char **argv, char *message, ...) { + if (message) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + fprintf(stderr, "\n"); + va_end(args); + } + + fprintf(stderr, "usage: %s grab device\n", argv[0]); + + exit(1); +} + +int tabby_command_grab(int argc, char **argv) { + tabby_printer *printer; + tabby_printer_packet header; + + uint8_t body[TABBY_PRINTER_PACKET_MAX_SIZE]; + + if (argc != 2) { + usage(argc, argv, "No device specified"); + } + + if ((printer = tabby_printer_open(argv[1])) == NULL) { + fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "tabby_printer_open()", + argv[1], strerror(errno)); + + goto error_printer_open; + } + + while (1) { + if (tabby_printer_packet_recv(printer, &header, &body) < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "tabby_printer_packet_recv()", strerror(errno)); + + continue; + } + + if (header.type == 0x04) { + write(1, &body, header.size); + } + } + + tabby_printer_close(printer); + + return 0; + +error_printer_open: + return 1; +} diff --git a/bin/main.c b/bin/main.c index 9d8bb48..f38c587 100644 --- a/bin/main.c +++ b/bin/main.c @@ -9,6 +9,8 @@ #include #include +#include "commands.h" + static void usage(int argc, char **argv, char *message, ...) { if (message) { va_list args; @@ -19,48 +21,36 @@ static void usage(int argc, char **argv, char *message, ...) { va_end(args); } - fprintf(stderr, "usage: %s device\n", argv[0]); + fprintf(stderr, "usage: %1$s print ...\n" + " %1$s grab ...\n", + argv[0]); exit(1); } +static struct { + char *name; + int (*fun)(int, char **); +} commands[] = { + { "print", tabby_command_print }, + { "grab", tabby_command_grab }, + { NULL, NULL } +}; + int main(int argc, char **argv) { - int fd, status; + int i; - tabby_printer_packet header; - - uint8_t body[TABBY_PRINTER_PACKET_MAX_SIZE]; - - if (argc != 2) { - usage(argc, argv, "No device specified"); + if (argc < 2) { + usage(argc, argv, "No command specified"); } - if ((fd = tabby_link_open(argv[1])) < 0) { - fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "tabby_link_open()", - argv[1], strerror(errno)); - - goto error_link_open; - } - - while (1) { - status = tabby_printer_packet_recv(fd, &header, &body); - - if (status < 0) { - fprintf(stderr, "%s: %s: %s\n", - argv[0], "tabby_printer_packet_recv()", strerror(errno)); - - continue; - } - - if (header.type == 0x04) { - write(1, &body, header.size); + for (i=0; commands[i].name; i++) { + if (strcmp(argv[1], commands[i].name) == 0) { + return commands[i].fun(argc, argv); } } - tabby_link_close(fd); + usage(argc, argv, "Unknown command '%s'", argv[1]); return 0; - -error_link_open: - return 1; } diff --git a/bin/print.c b/bin/print.c new file mode 100644 index 0000000..78af7ae --- /dev/null +++ b/bin/print.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void usage(int argc, char **argv, char *message, ...) { + if (message) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + fprintf(stderr, "\n"); + va_end(args); + } + + fprintf(stderr, "usage: %s print device sheet.tile\n", argv[0]); + + exit(1); +} + +int tabby_command_print(int argc, char **argv) { + int fd; + + ssize_t readlen; + size_t offset = 0; + + tabby_printer *printer; + + uint8_t band[TABBY_PRINTER_BAND_SIZE]; + + if (argc != 3) { + usage(argc, argv, "Must specify device and tile"); + } + + if ((fd = open(argv[2], O_RDONLY)) < 0) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "open()", argv[2], strerror(errno)); + + goto error_open_tile; + } + + if ((printer = tabby_printer_open(argv[1])) == NULL) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "tabby_printer_open()", argv[1], strerror(errno)); + + goto error_printer_open; + } + + do { + sleep(1); + + tabby_printer_init(printer); + } while (printer->device != TABBY_PRINTER_DEVICE_ID); + + while ((readlen = read(fd, band, sizeof(band))) >= 0) { + offset += readlen; + + tabby_printer_band_send(printer, band); + + if (offset % TABBY_PRINTER_SHEET_SIZE == 0) { + uint8_t feeds = 0x00; + + if (offset == TABBY_PRINTER_SHEET_SIZE) { + feeds |= 0x10; + } + + tabby_printer_band_finish(printer); + + tabby_printer_job_start(printer, 1, feeds, 0x00, 0x40); + + tabby_printer_job_wait(printer); + } + } + + tabby_printer_job_start(printer, 1, 0x03, 0x00, 0x40); + + tabby_printer_job_wait(printer); + + tabby_printer_close(printer); + + return 0; + +error_printer_open: + close(fd); + +error_open_tile: + return 1; +} diff --git a/include/tabby/printer.h b/include/tabby/printer.h index dfe319c..613b274 100644 --- a/include/tabby/printer.h +++ b/include/tabby/printer.h @@ -39,6 +39,24 @@ typedef enum { TABBY_PRINTER_COMPRESSION_RLE = 0x01 } tabby_printer_compression; +typedef struct _tabby_printer_response { + uint8_t device; + uint8_t status; +} tabby_printer_response; + +typedef struct _tabby_printer { + int fd; + + union { + tabby_printer_response response; + + struct { + uint8_t device, + status; + }; + }; +} tabby_printer; + /* * Data definitions for packets sent from Game Boy to printer */ @@ -75,42 +93,42 @@ typedef struct _tabby_printer_buffer { uint16_t sum; } tabby_printer_buffer; -typedef struct _tabby_printer_response { - uint8_t device; - uint8_t status; -} tabby_printer_response; +tabby_printer *tabby_printer_open(const char *device); + +void tabby_printer_close(tabby_printer *printer); /* * For receiving printer data packets from a Game Boy Camera */ -int tabby_printer_packet_recv(int fd, +int tabby_printer_packet_recv(tabby_printer *printer, tabby_printer_packet *header, void *body); /* * For sending printer data packets to a Game Boy Printer */ -int tabby_printer_packet_send(int fd, +int tabby_printer_packet_send(tabby_printer *printer, tabby_printer_packet *header, - void *body, - tabby_printer_response *response); + void *body); -int tabby_printer_init(int fd, - tabby_printer_response *response); +int tabby_printer_init(tabby_printer *printer); -int tabby_printer_send_inquiry(int fd, - tabby_printer_response *response); +int tabby_printer_inquiry_send(tabby_printer *printer); -int tabby_printer_job_start(int fd, uint8_t sheets, - uint8_t linefeeds, - uint8_t palette, - uint8_t density, - tabby_printer_response *response); +int tabby_printer_job_start(tabby_printer *printer, uint8_t sheets, + uint8_t linefeeds, + uint8_t palette, + uint8_t density); -int tabby_printer_job_cancel(int fd, - tabby_printer_response *response); +int tabby_printer_job_cancel(tabby_printer *printer); -int tabby_printer_send_sheet(int fd, void *data, - tabby_printer_response *response); +int tabby_printer_job_wait(tabby_printer *printer); + +int tabby_printer_band_send(tabby_printer *printer, uint8_t *band); + +int tabby_printer_band_finish(tabby_printer *printer); + +int tabby_printer_sheet_send(tabby_printer *printer, void *data, + uint16_t size); #endif /* _TABBY_PRINTER_H */ diff --git a/src/link.c b/src/link.c index c5e7495..359f097 100644 --- a/src/link.c +++ b/src/link.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -18,6 +17,8 @@ int tabby_link_open(const char *dev) { cfmakeraw(&attr); cfsetspeed(&attr, TABBY_LINK_BAUD); + sleep(1); + if (tcsetattr(fd, TCSAFLUSH, &attr) < 0) { goto error_io; } diff --git a/src/printer.c b/src/printer.c index 29f612f..ffce444 100644 --- a/src/printer.c +++ b/src/printer.c @@ -1,5 +1,6 @@ -#include +#include #include +#include #include #include #include @@ -9,6 +10,34 @@ #define PACKET_RECV_ERROR_THRESHOLD 30 +tabby_printer *tabby_printer_open(const char *device) { + tabby_printer *printer; + + if ((printer = malloc(sizeof(*printer))) == NULL) { + goto error_malloc_printer; + } + + if ((printer->fd = tabby_link_open(device)) < 0) { + goto error_link_open; + } + + printer->device = TABBY_PRINTER_DEVICE_ID; + printer->status = TABBY_PRINTER_OK; + + return printer; + +error_link_open: + free(printer); + +error_malloc_printer: + return NULL; +} + +void tabby_printer_close(tabby_printer *printer) { + tabby_link_close(printer->fd); + free(printer); +} + static uint16_t checksum(tabby_printer_packet *header, void *body) { uint16_t checksum = header->data[2] + header->data[3] @@ -24,7 +53,7 @@ static uint16_t checksum(tabby_printer_packet *header, void *body) { return checksum; } -int tabby_printer_packet_recv(int fd, +int tabby_printer_packet_recv(tabby_printer *printer, tabby_printer_packet *header, void *body) { ssize_t len; @@ -38,7 +67,7 @@ int tabby_printer_packet_recv(int fd, memset(header, '\0', sizeof(*header)); - while ((len = read(fd, &value, 1)) >= 0) { + while ((len = read(printer->fd, &value, 1)) >= 0) { if (i == 0) { if (value == TABBY_PRINTER_SYNC_1) { header->preamble[0] = value; @@ -90,39 +119,26 @@ error_io: return -errno; } -static inline int resend(tabby_printer_response *response) { - if (response->device != TABBY_PRINTER_DEVICE_ID) { - return 1; - } - - if (response->status & (TABBY_PRINTER_ER0 | TABBY_PRINTER_SUM)) { - return 1; - } - - return 0; -} - -int tabby_printer_packet_send(int fd, +int tabby_printer_packet_send(tabby_printer *printer, tabby_printer_packet *header, - void *body, - tabby_printer_response *response) { + void *body) { uint16_t sum = checksum(header, body); - if (write(fd, header, sizeof(*header)) < 0) { + if (write(printer->fd, header, sizeof(*header)) < 0) { goto error_io; } if (header->size) { - if (write(fd, body, header->size) < 0) { + if (write(printer->fd, body, header->size) < 0) { goto error_io; } } - if (write(fd, &sum, sizeof(sum)) < 0) { + if (write(printer->fd, &sum, sizeof(sum)) < 0) { goto error_io; } - if (read(fd, response, sizeof(*response)) < 0) { + if (read(printer->fd, &printer->response, sizeof(printer->response)) < 0) { goto error_io; } @@ -141,29 +157,26 @@ static void init_header(tabby_printer_packet *header, header->size = (uint16_t)size; } -int tabby_printer_init(int fd, - tabby_printer_response *response) { +int tabby_printer_init(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INIT, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_send_inquiry(int fd, - tabby_printer_response *response) { +int tabby_printer_inquiry_send(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INQUIRY, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_job_start(int fd, uint8_t sheets, - uint8_t linefeeds, - uint8_t palette, - uint8_t density, - tabby_printer_response *response) { +int tabby_printer_job_start(tabby_printer *printer, uint8_t sheets, + uint8_t linefeeds, + uint8_t palette, + uint8_t density) { tabby_printer_packet header; uint8_t body[4] = { @@ -172,41 +185,69 @@ int tabby_printer_job_start(int fd, uint8_t sheets, init_header(&header, TABBY_PRINTER_PACKET_JOB, sizeof(body)); - return tabby_printer_packet_send(fd, &header, &body, response); + return tabby_printer_packet_send(printer, &header, &body); } -int tabby_printer_job_cancel(int fd, - tabby_printer_response *response) { +int tabby_printer_job_cancel(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_CANCEL, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_send_sheet(int fd, void *data, - tabby_printer_response *response) { - int i; - size_t offset = 0; +int tabby_printer_job_wait(tabby_printer *printer) { + do { + sleep(1); + + if (tabby_printer_inquiry_send(printer) < 0) { + goto error_inquiry_send; + } + } while (printer->status & TABBY_PRINTER_UNTRAN); + + return 0; + +error_inquiry_send: + return -1; +} + +int tabby_printer_band_send(tabby_printer *printer, uint8_t *band) { + tabby_printer_packet header; + + init_header(&header, TABBY_PRINTER_PACKET_DATA, TABBY_PRINTER_BAND_SIZE); + + return tabby_printer_packet_send(printer, &header, band); +} + +int tabby_printer_band_finish(tabby_printer *printer) { + tabby_printer_packet header; + + init_header(&header, TABBY_PRINTER_PACKET_DATA, 0); + + return tabby_printer_packet_send(printer, &header, NULL); +} + +int tabby_printer_sheet_send(tabby_printer *printer, void *data, + uint16_t size) { + uint16_t offset = 0; tabby_printer_packet header; - for (i=0; istatus & TABBY_PRINTER_SUM) { + tabby_printer_init(printer); + + offset = 0; continue; } @@ -216,7 +257,7 @@ int tabby_printer_send_sheet(int fd, void *data, init_header(&header, TABBY_PRINTER_PACKET_DATA, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); error_packet_send: return -1;