summaryrefslogtreecommitdiff
path: root/upload.c
diff options
context:
space:
mode:
Diffstat (limited to 'upload.c')
-rw-r--r--upload.c315
1 files changed, 0 insertions, 315 deletions
diff --git a/upload.c b/upload.c
deleted file mode 100644
index 36434ac..0000000
--- a/upload.c
+++ /dev/null
@@ -1,315 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-
-#include <getopt.h>
-#include <termios.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <search.h>
-#include <errno.h>
-
-#define PACKET_SIZE 8
-
-#define LEN(x) (sizeof(x) / sizeof(x[0]))
-
-typedef unsigned char uchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-typedef unsigned long long ulonglong;
-
-enum verbose_level {
- NONE,
- DEBUG,
- WARNING,
- ERROR
-};
-
-// in bootloader spam \n or anything? until some buffer is full
-
-speed_t baud = 0;
-char port[32] = {0};
-int serial_fd = -1;
-FILE *file = NULL;
-const char *flush = "aaaaaaaaaaaaa\n";
-int verbose = 0;
-
-void help()
-{
- puts("help");
- exit(EXIT_SUCCESS);
-}
-
-void die()
-{
- if (file)
- fclose(file);
- if (serial_fd < 0)
- close(serial_fd);
- exit(EXIT_FAILURE);
-}
-
-int log_msg(int lvl, const char *fmt, ...)
-{
- int ret = 0;
- va_list args;
- if (verbose >= lvl) {
- va_start(args, fmt);
- ret = vprintf(fmt, args);
- fflush(stdout);
- va_end(args);
- }
- return ret;
-}
-
-struct baud_pair {
- const char *b;
- speed_t c;
-};
-
-// Conversion table for baud rates
-const struct baud_pair baud_rates[] = {
- {"1200", B1200},
- {"2400", B2400},
- {"4800", B4800},
- {"9600", B9600},
- {"19200", B19200},
-};
-
-int parse_argv(int argc, char *const argv[])
-{
- struct option long_opts[] = {
- { "baud", required_argument, 0, 'b'},
- { "verbose", no_argument, 0, 'v'},
- { "port", required_argument, 0, 'p'},
- { "help", no_argument, 0, 'h'},
- { 0, 0, 0, 0 }
- };
-
- int long_index = 0;
- int c;
-
- while ((c = getopt_long(argc, argv, "b:p:h",
- long_opts, &long_index)) != -1) {
- switch (c) {
- case 'b':
- for (int i = 0; i < LEN(baud_rates); i++) {
- if (!strcmp(baud_rates[i].b, optarg)) {
- baud = baud_rates[i].c;
- break;
- }
- }
-
- if (baud == 0) {
- fprintf(stderr, "Error: Invalid baud rate '%s'\n", optarg);
- exit(EXIT_FAILURE);
- }
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- case 'p':
- strncpy(port, optarg, LEN(port));
- break;
-
- case 'h':
- help();
- break;
-
- case '?':
- help();
- break;
-
- default:
- break;
- }
- }
-
- if (argc <= optind) {
- fprintf(stderr, "Error: No file was provided to upload\n\n");
- help();
- }
-
- return optind;
-}
-
-int open_tty(const char *port)
-{
- int fd = open(port, O_RDWR);
-
- if (fd < 0) {
- fprintf(stderr, "Error: Port '%s' could not be opened\n", port);
- exit(EXIT_FAILURE);
- }
-
- struct termios term;
- tcgetattr(fd, &term);
-
- cfmakeraw(&term);
- term.c_cc[VTIME] = 1;
- term.c_cc[VMIN] = 0;
- term.c_lflag &= ~OCRNL;
- cfsetspeed(&term, baud);
-
- tcsetattr(fd, TCSANOW, &term);
-
- return fd;
-}
-
-ssize_t read_line(int fd, uchar *buf, size_t len)
-{
- int ret = 0;
- ssize_t bytes_read = 0;
-
- // The Serial port runs at ~9600 baud. This loop, as inefficient as it is,
- // won' t ever be a bottleneck
- for (int i = 0; bytes_read < len; i++) {
- ssize_t rd = read(fd, &buf[bytes_read], 1);
- if (rd < 0) {
- fprintf(stderr, "Error: read from port failed\n%s\n",
- strerror(errno));
- die();
- }
-
- if (rd == 0)
- return -1;
-
- bytes_read += rd;
- if (buf[bytes_read - 1] == '\n')
- break;
- }
-
- buf[bytes_read] = 0;
- return bytes_read;
-}
-
-void flush_bootloader(int serial_fd)
-{
- /* Clean up */
- // tcflush(serial_fd, TCIOFLUSH);
- /* Send empty line to get a ready prompt from bootloader */
- write(serial_fd, flush, strlen(flush));
- tcdrain(serial_fd);
-}
-
-/*
- * Get the bootloader in a ready state, cleaning up any previous errors
- */
-void begin_command(int serial_fd)
-{
- char buf[32];
- int timeout = 1;
-
- buf[0] = 0;
-
- while (timeout) {
- /* Comparing should stop after \n even if buf is undefined */
- while (strcmp("ready\r\n", buf) != 0) {
- if (read_line(serial_fd, buf, LEN(buf)) < 0) {
- timeout = 1;
- log_msg(DEBUG, "timeout\n%32s\n", buf);
- flush_bootloader(serial_fd);
- break;
- } else {
- timeout = 0;
- }
- }
- }
-}
-
-void send_packet(int index, uint address, int plen, const uchar *packet)
-{
- char obuf[128];
- int len = sprintf(obuf, "W %04X %02X ", address, plen);
-
- for (int i = 0; i < plen; i++)
- len += sprintf(&obuf[len], "%02X", packet[i]);
-
- obuf[len++] = '\r';
- obuf[len++] = '\n';
- obuf[len] = '\0';
-
- int cmp = 1;
- char ibuf[128];
- char ebuf[128];
-
- for (int attempt = 1; cmp != 0; attempt++) {
- log_msg(DEBUG, "Sending packet %d, attempt %d\n", index, attempt);
-
- begin_command(serial_fd);
- write(serial_fd, obuf, len);
-
- if((read_line(serial_fd, ibuf, LEN(ibuf)) == -1)
- || (read_line(serial_fd, ebuf, LEN(ebuf)) == -1)) {
- continue;
- }
-
- log_msg(DEBUG, "sent: %s", obuf);
- log_msg(DEBUG, "recv: %s", ibuf);
- log_msg(DEBUG, "ebuf: %s", ebuf);
-
- cmp = strncmp(ibuf, obuf, LEN(ibuf));
- if (cmp != 0) {
- usleep(100);
- }
- }
-}
-
-int upload_file(FILE *file, int serial_fd)
-{
- int file_size = 0;
- fseek(file, 0, SEEK_END);
- file_size = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- int total = (file_size / PACKET_SIZE
- + ((file_size % PACKET_SIZE) == 0 ? 0 : 1));
-
- printf("Sending %d bytes\n", file_size);
- printf("Progress: [ %3d%% ]", 0);
- fflush(stdout);
-
- uint address = 0x4000;
- uchar packet[PACKET_SIZE];
-
- for (int i = 1; !feof(file); i++) {
- size_t n = fread(packet, sizeof(uchar), LEN(packet), file);
- if (n > 0) {
- send_packet(i, address, n, packet);
- address += n;
- }
- printf("\rProgress: [ %3d%% ]", 100 * i / total);
- fflush(stdout);
- }
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- int ind = parse_argv(argc, argv);
- serial_fd = open_tty(port);
- FILE *file = fopen(argv[ind], "r");
-
- if (!file) {
- fprintf(stderr, "Error: File '%s' could not be opened\n", argv[ind]);
- close(serial_fd);
- exit(EXIT_FAILURE);
- }
-
- tcflush(serial_fd, TCIOFLUSH);
- flush_bootloader(serial_fd);
-
- upload_file(file, serial_fd);
- puts("\ndone");
-
- fclose(file);
- close(serial_fd);
-
- exit(EXIT_SUCCESS);
-}