mega-usb: initial code
authornotaz <notasas@gmail.com>
Sun, 29 Sep 2013 11:33:57 +0000 (14:33 +0300)
committernotaz <notasas@gmail.com>
Sun, 29 Sep 2013 11:33:57 +0000 (14:33 +0300)
Mega Everdrive USB transfer

mega-usb/Makefile [new file with mode: 0644]
mega-usb/mega-usb.c [new file with mode: 0644]

diff --git a/mega-usb/Makefile b/mega-usb/Makefile
new file mode 100644 (file)
index 0000000..5c7aec3
--- /dev/null
@@ -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 (file)
index 0000000..7217080
--- /dev/null
@@ -0,0 +1,186 @@
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+
+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;
+}