From c675fc1f54bc199ac4cc95136fd813181cc6340b Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Sun, 29 May 2016 14:21:16 -0500 Subject: [PATCH] Implement tabby_printer_packet_recv() and tabby_printer_response_send() --- bin/main.c | 303 ++-------------------------------------- include/tabby/printer.h | 56 ++++++++ src/Makefile | 4 +- src/printer.c | 99 +++++++++++++ 4 files changed, 169 insertions(+), 293 deletions(-) create mode 100644 include/tabby/printer.h create mode 100644 src/printer.c diff --git a/bin/main.c b/bin/main.c index 0ef6102..563d4ff 100644 --- a/bin/main.c +++ b/bin/main.c @@ -6,6 +6,7 @@ #include #include +#include static void usage(int argc, char **argv, char *message, ...) { if (message) { @@ -23,18 +24,12 @@ static void usage(int argc, char **argv, char *message, ...) { } int main(int argc, char **argv) { - int fd; - ssize_t len; + int fd, status; - uint8_t state = 0, - value = 0, - compression = 0, - dataLengthLSB = 0, - dataLengthMSB = 0, - acknowledgeCode = 129, - statusCode = 0; + tabby_printer_packet_header header; + tabby_printer_packet_footer footer; - uint16_t dataPosition = 0; + uint8_t body[TABBY_PRINTER_MAX_PACKET_SIZE]; if (argc != 2) { usage(argc, argv, "No device specified"); @@ -47,291 +42,17 @@ int main(int argc, char **argv) { goto error_link_open; } - while ((len = tabby_link_recv(fd, &value, 1)) >= 0) { - uint8_t response = 0; + while (1) { + status = tabby_printer_packet_recv(fd, &header, &body, &footer); - fprintf(stderr, "state %d recv 0x%02x\n", state, value); + if (status < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "tabby_printer_packet_recv()", strerror(errno)); - switch (state) { - case 0: { - if (value == 136) { - state = 1; - } - - response = 0; - - break; - } - - case 1: { - if (value == 51) { - state = 2; - response = 0; - } else { - state = 0; - response = 0; - } - - break; - } - - case 2: { - if (value == 1) { - state = 3; - response = 0; - compression = 0; - dataLengthLSB = 0; - dataLengthMSB = 0; - } else if (value == 2) { - state = 50; - response = 0; - } else if (value == 4) { - state = 20; - response = 0; - } else if (value == 15) { - state = 90; - response = 0; - } else { - state = 0; - response = 5; - } - - break; - } - - case 3: { - compression = value; - response = 0; - state = 4; - - break; - } - - case 4: { - dataLengthLSB = value; - response = 0; - state = 5; - - break; - } - - case 5: { - dataLengthMSB = value; - response = 0; - state = 6; - - break; - } - - case 6: { - response = 0; - state = 7; - - break; - } - - case 7: { - response = 129; - state = 8; - - break; - } - - case 8: { - response = statusCode; - state = 0; - - break; - } - - case 20: { - compression = value; - response = 0; - state = 21; - - break; - } - - case 21: { - dataLengthLSB = value; - response = 0; - state = 22; - - break; - } - - case 22: { - dataLengthMSB = value; - response = 0; - state = 23; - dataPosition = 256 * dataLengthMSB + dataLengthLSB; - - break; - } - - case 23: { - dataPosition--; - - if (dataPosition == 0 || dataPosition == 65535) { - state = 24; - } else { - state = 23; - } - - response = 0; - - break; - } - - case 24: { - response = 0; - state = 25; - - break; - } - - case 26: { - response = acknowledgeCode; - state = 27; - - break; - } - - case 27: { - response = statusCode; - state = 0; - - break; - } - - case 50: { - response = 0; - state = 51; - - break; - } - - case 51: { - response = 0; - state = 52; - - break; - } - - case 52: { - response = 0; - state = 53; - - break; - } - - case 53: { - response = 0; - state = 54; - - break; - } - - case 54: { - response = 0; - state = 55; - - break; - } - - case 55: { - response = 0; - state = 56; - - break; - } - - case 56: { - response = 0; - state = 57; - - break; - } - - case 57: { - response = 0; - state = 58; - - break; - } - - case 58: { - response = acknowledgeCode; - state = 59; - - break; - } - - case 59: { - response = statusCode; - state = 0; - - break; - } - - case 90: { - response = 0; - state = 91; - - break; - } - - case 91: { - response = 0; - state = 92; - - break; - } - - case 92: { - response = 0; - state = 93; - - break; - } - - case 93: { - response = 0; - state = 94; - - break; - } - - case 94: { - response = 129; - state = 95; - - break; - } - - case 95: { - response = statusCode; - state = 0; - - break; - } - - default: { - response = 0; - state = 0; - - break; - } + continue; } - fprintf(stderr, "send 0x%02x\n", response); - - if (tabby_link_send(fd, &response, 1) < 0) { - fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "tabby_link_send()", - argv[1], strerror(errno)); - - goto error_link_send; - } + fprintf(stderr, "Got a packet\n"); } tabby_link_close(fd); diff --git a/include/tabby/printer.h b/include/tabby/printer.h new file mode 100644 index 0000000..fc583b2 --- /dev/null +++ b/include/tabby/printer.h @@ -0,0 +1,56 @@ +#ifndef _TABBY_PRINTER_H +#define _TABBY_PRINTER_H + +#define TABBY_PRINTER_MAX_PACKET_SIZE 640 + +typedef enum { + TABBY_PRINTER_LOWBAT = (1 << 7), + TABBY_PRINTER_ER2 = (1 << 6), + TABBY_PRINTER_ER1 = (1 << 5), + TABBY_PRINTER_ER0 = (1 << 4), + TABBY_PRINTER_UNTRAN = (1 << 3), + TABBY_PRINTER_FULL = (1 << 2), + TABBY_PRINTER_BUSY = (1 << 1), + TABBY_PRINTER_SUM = (1 << 0) +} tabby_printer_status; + +/* + * Data definitions for packets sent from Game Boy to printer + */ +typedef struct _tabby_printer_packet_header { + union { + struct { + uint8_t preamble[2], + type, + compression; + + uint16_t size; + }; + + uint8_t data[6]; + }; +} tabby_printer_packet_header; + +typedef struct _tabby_printer_packet_footer { + union { + struct { + uint16_t checksum; + + uint8_t peripheral, + status; + }; + + uint8_t data[4]; + }; +} tabby_printer_packet_footer; + +/* + * Methods for communicating with Game Boy as a printer + */ +int tabby_printer_packet_recv(int fd, tabby_printer_packet_header *header, + void *body, + tabby_printer_packet_footer *footer); + +int tabby_printer_response_send(int fd, uint8_t device, uint8_t status); + +#endif /* _TABBY_PRINTER_H */ diff --git a/src/Makefile b/src/Makefile index 87ca16c..b1319ba 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,8 +11,8 @@ HEADERS_LOCAL = HEADERS_BUILD = $(HEADERS_LOCAL) \ $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS)) -HEADERS = link.h -OBJS = link.o +HEADERS = link.h printer.h +OBJS = link.o printer.o VERSION_MAJOR = 0 VERSION_MINOR = 0.1 diff --git a/src/printer.c b/src/printer.c new file mode 100644 index 0000000..4c3c152 --- /dev/null +++ b/src/printer.c @@ -0,0 +1,99 @@ +#include + +#include +#include + +#define PACKET_RECV_ERROR_THRESHOLD 30 + +static uint16_t checksum(tabby_printer_packet_header *header, void *body) { + uint16_t checksum = header->data[2] + + header->data[3] + + header->data[4] + + header->data[5]; + + size_t i; + + for (i=0; isize; i++) { + checksum += ((uint8_t *)body)[i]; + } + + return checksum; +} + +int tabby_printer_packet_recv(int fd, tabby_printer_packet_header *header, + void *body, + tabby_printer_packet_footer *footer) { + ssize_t len; + + size_t i = 0, + b = 0, + f = 0; + + uint8_t value, + last; + + int started = 0; + + memset(header, '\0', sizeof(*header)); + memset(footer, '\0', sizeof(*footer)); + + while ((len = tabby_link_recv(fd, &value, 1)) >= 0) { + if (started) { + if (i == 2) { + header->type = value; + } else if (i == 3) { + header->compression = value; + } else if (i == 4 || i == 5) { + header->size <<= 8; + header->size |= value; + } else if (i > 5 && b < header->size) { + ((uint8_t *)body)[b++] = value; + } else if (b >= header->size && f < 2) { + footer->checksum <<= 8; + footer->checksum |= value; + + f++; + } else if (f >= 2) { + footer->data[f++] = value; + + if (f == sizeof(*footer)) { + if (checksum(header, body) != footer->checksum) { + errno = EIO; + + goto error_io; + } + + return 0; + } + } + } else { + if (last == 0x88 && value == 0x33) { + started = 1; + i = 2; + b = 0; + f = 0; + } else if (i == PACKET_RECV_ERROR_THRESHOLD) { + errno = EIO; + + goto error_io; + } + } + + last = value; + + i++; + } + + return errno = 0; + +error_io: + return -errno; +} + +int tabby_printer_response_send(int fd, uint8_t device, uint8_t status) { + uint8_t response[2] = { + device, status + }; + + return tabby_link_send(fd, &response, sizeof(response)); +}