From: notaz Date: Sun, 29 Sep 2013 11:33:57 +0000 (+0300) Subject: mega-usb: initial code X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9f5a788df6754d5556056e4fb6081ab75faab383;p=megadrive.git mega-usb: initial code Mega Everdrive USB transfer --- diff --git a/mega-usb/Makefile b/mega-usb/Makefile new file mode 100644 index 0000000..5c7aec3 --- /dev/null +++ b/mega-usb/Makefile @@ -0,0 +1,6 @@ +CFLAGS += -Wall -ggdb -O2 + +all: mega-usb + +clean: + $(RM) mega-usb diff --git a/mega-usb/mega-usb.c b/mega-usb/mega-usb.c new file mode 100644 index 0000000..7217080 --- /dev/null +++ b/mega-usb/mega-usb.c @@ -0,0 +1,186 @@ +#define _BSD_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int setup(int fd) +{ + speed_t ispeed, ospeed; + struct termios tty; + int ret; + + memset(&tty, 0, sizeof(tty)); + + ret = tcgetattr(fd, &tty); + if (ret != 0) + { + perror("tcgetattr"); + return 1; + } + + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP + | INLCR | IGNCR | ICRNL | IXON); + tty.c_oflag &= ~OPOST; + tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + tty.c_cflag &= ~(CSIZE | PARENB); + tty.c_cflag |= CS8; + + //tty.c_cc[VMIN] = 1; + //tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout + + ret = tcsetattr(fd, TCSANOW, &tty); + if (ret != 0) { + perror("tcsetattr"); + return ret; + } + + return 0; +} + +static int write_to_cart(int fd, const void *data, size_t size) +{ + int ret; + + ret = write(fd, data, size); + if (ret != size) { + perror("write"); + exit(1); + //return -1; + } + + return 0; +} + +static int read_from_cart(int fd, void *data, size_t size) +{ + int ret; + + ret = read(fd, data, size); + if (ret != (int)size) { + perror("read"); + exit(1); + //return -1; + } + + return 0; +} + +#define send_cmd(fd, cmd) \ + write_to_cart(fd, cmd, sizeof(cmd) - 1) + +static int read_check_byte(int fd, char expect) +{ + char r = '0'; + int ret; + + ret = read_from_cart(fd, &r, 1); + if (ret != 0) { + fprintf(stderr, "missing response, need '%c'\n", expect); + return -1; + } + + if (r != expect) { + fprintf(stderr, "unexpected response: '%c', need '%c'\n", + r, expect); + return -1; + } + + return 0; +} + +static int write_with_check(int fd, const void *data, size_t size, char chk) +{ + int ret; + + ret = write_to_cart(fd, data, size); + if (ret) + return ret; + + ret = read_check_byte(fd, chk); + if (ret != 0) { + if (size < 16) + fprintf(stderr, "data sent: '%16s'\n", + (const char *)data); + exit(1); + //return -1; + } + + return 0; +} + +#define send_cmd_check_k(fd, cmd) \ + write_with_check(fd, cmd, sizeof(cmd) - 1, 'k') + +int main(int argc, char *argv[]) +{ + const char *portname = "/dev/ttyUSB0"; + char buf[0x10000]; + size_t size; + int blocks; + FILE *f; + int ret; + int fd; + int i; + + fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); + if (fd < 0) { + perror("open"); + return 1; + } + + setup(fd); + + send_cmd_check_k(fd, " *T"); + + if (argv[1] != NULL) + { + f = fopen(argv[1], "rb"); + if (f == NULL) + { + perror("fopen"); + return 1; + } + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + if (size > 0xf00000) { + fprintf(stderr, "size too large: %zd\n", size); + return 1; + } + + blocks = (size + 0xffff) >> 16; + send_cmd(fd, "*g"); + write_with_check(fd, &blocks, 1, 'k'); + + // at this point, 'd' will arrive even if we don't + // write any more data, what's the point of that? + + for (i = 0; i < blocks; i++) { + ret = fread(buf, 1, sizeof(buf), f); + if (i != blocks - 1 && ret != sizeof(buf)) { + fprintf(stderr, "failed to read block %d/%d\n", + i, blocks); + } + if (ret < sizeof(buf)) + memset(buf + ret, 0, sizeof(buf) - ret); + + write_to_cart(fd, buf, sizeof(buf)); + } + + ret = read_check_byte(fd, 'd'); + if (ret) + return 1; + + send_cmd_check_k(fd, "*rm"); + } + + printf("all ok\n"); + + return 0; +}