Implement tabby_printer_packet_recv() and tabby_printer_response_send()
This commit is contained in:
parent
c66bfade8f
commit
c675fc1f54
4 changed files with 169 additions and 293 deletions
303
bin/main.c
303
bin/main.c
|
@ -6,6 +6,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <tabby/link.h>
|
||||
#include <tabby/printer.h>
|
||||
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
56
include/tabby/printer.h
Normal file
56
include/tabby/printer.h
Normal file
|
@ -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 */
|
|
@ -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
|
||||
|
|
99
src/printer.c
Normal file
99
src/printer.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <tabby/link.h>
|
||||
#include <tabby/printer.h>
|
||||
|
||||
#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; i<header->size; 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));
|
||||
}
|
Loading…
Add table
Reference in a new issue