From 15f943938b622a3f32bbb8847809acb53782df2a Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 18 Jun 2018 18:10:50 +0200 Subject: avrdude: add file offset to update operation spec, refactoring --- xs/src/avrdude/arduino.c | 95 +++++++++++++++++------------------- xs/src/avrdude/fileio.c | 57 ++++++++++++++-------- xs/src/avrdude/libavrdude.h | 5 +- xs/src/avrdude/main.c | 2 +- xs/src/avrdude/update.c | 38 +++++++++++---- xs/src/slic3r/GUI/FirmwareDialog.cpp | 4 +- 6 files changed, 118 insertions(+), 83 deletions(-) (limited to 'xs') diff --git a/xs/src/avrdude/arduino.c b/xs/src/avrdude/arduino.c index 886a43f0b..5e0693e94 100644 --- a/xs/src/avrdude/arduino.c +++ b/xs/src/avrdude/arduino.c @@ -80,6 +80,49 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) return 3; } +static int prusa_init_external_flash(PROGRAMMER * pgm) +{ + // Note: send/receive as in _the firmare_ send & receives + const char entry_magic_send [] = "start\n"; + const char entry_magic_receive[] = "w25x20cl_enter\n"; + const char entry_magic_cfm [] = "w25x20cl_cfm\n"; + const size_t buffer_len = 32; // Should be large enough for the above messages + + int res; + size_t recv_size; + char *buffer = alloca(buffer_len); + + // 1. receive the "start" command + recv_size = sizeof(entry_magic_send) - 1; + res = serial_recv(&pgm->fd, buffer, recv_size); + if (res < 0) { + avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); + return -1; + } else if (strncmp(buffer, entry_magic_send, recv_size) != 0) { + avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname); + return -1; + } + + // 2. Send the external flash programmer enter command + if (serial_send(&pgm->fd, entry_magic_receive, sizeof(entry_magic_receive) - 1) < 0) { + avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): Failed to send command to the printer\n",progname); + return -1; + } + + // 3. Receive the entry confirmation command + recv_size = sizeof(entry_magic_cfm) - 1; + res = serial_recv(&pgm->fd, buffer, recv_size); + if (res < 0) { + avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); + return -1; + } else if (strncmp(buffer, entry_magic_cfm, recv_size) != 0) { + avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code\n", progname); + return -1; + } + + return 0; +} + static int arduino_open(PROGRAMMER * pgm, char * port) { union pinfo pinfo; @@ -102,56 +145,10 @@ static int arduino_open(PROGRAMMER * pgm, char * port) */ stk500_drain(pgm, 0); -{ - //FIXME initialization sequence for programming the external FLASH. - const char entry_magic_send [] = "start\n"; - const char entry_magic_receive[] = "w25x20cl_enter\n"; - const char entry_magic_cfm [] = "w25x20cl_cfm\n"; - const char *entry_magic_ptr = entry_magic_send; - struct timeval tv; - double tstart, tnow; - char c; - gettimeofday(&tv, NULL); - tstart = tv.tv_sec; - while (*entry_magic_ptr != 0) { - if (serial_recv(&pgm->fd, &c, 1) < 0) - goto timedout; - printf("Received: %c (%d)\n", c, (int)c); - if (c != *entry_magic_ptr ++) { - avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer emited incorrect start code\n", progname); - return -1; - } - gettimeofday(&tv, NULL); - tnow = tv.tv_sec; - if (tnow-tstart > 2.) { // wuff - signed/unsigned/overflow - timedout: - avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer did not boot up on time\n", progname); - return -1; - } - } - if (serial_send(&pgm->fd, entry_magic_receive, strlen(entry_magic_receive)) < 0) { - avrdude_message(MSG_INFO, "%s: stk500v2_send(): failed to send command to serial port\n",progname); - return -1; - } - - entry_magic_ptr = entry_magic_cfm; - while (*entry_magic_ptr != 0) { - if (serial_recv(&pgm->fd, &c, 1) < 0) - goto timedout2; - printf("Received: %c (%d)\n", c, (int)c); - if (c != *entry_magic_ptr++) { - avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer emited incorrect start code\n", progname); - return -1; - } - gettimeofday(&tv, NULL); - tnow = tv.tv_sec; - if (tnow - tstart > 2.) { // wuff - signed/unsigned/overflow - timedout2: - avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer did not boot up on time\n", progname); - return -1; - } + // Initialization sequence for programming the external FLASH on the Prusa MK3 + if (prusa_init_external_flash(pgm) < 0) { + avrdude_message(MSG_INFO, "%s: arduino_open(): Failed to initialize MK3 external flash programming mode\n", progname); } -} if (stk500_getsync(pgm) < 0) return -1; diff --git a/xs/src/avrdude/fileio.c b/xs/src/avrdude/fileio.c index 2ed19bd15..aa57f5587 100644 --- a/xs/src/avrdude/fileio.c +++ b/xs/src/avrdude/fileio.c @@ -45,7 +45,7 @@ #define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ -#define MAX_MODE_LEN 32 // For fopen_utf8() +#define MAX_MODE_LEN 32 // For fopen_and_seek() struct ihexrec { @@ -98,12 +98,13 @@ static int fileio_num(struct fioparms * fio, char * filename, FILE * f, AVRMEM * mem, int size, FILEFMT fmt); -static int fmt_autodetect(char * fname); +static int fmt_autodetect(char * fname, size_t offset); -static FILE *fopen_utf8(const char *filename, const char *mode) +static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset) { + FILE *file; // On Windows we need to convert the filename to UTF-16 #if defined(WIN32NATIVE) static wchar_t fname_buffer[PATH_MAX]; @@ -112,10 +113,24 @@ static FILE *fopen_utf8(const char *filename, const char *mode) if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; } if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; } - return _wfopen(fname_buffer, mode_buffer); + file = _wfopen(fname_buffer, mode_buffer); #else - return fopen(filename, mode); + file = fopen(filename, mode); #endif + + if (file != NULL) { + // Some systems allow seeking past the end of file, so we need check for that first and disallow + if (fseek(file, 0, SEEK_END) != 0 + || offset >= ftell(file) + || fseek(file, offset, SEEK_SET) != 0 + ) { + fclose(file); + file = NULL; + errno = EINVAL; + } + } + + return file; } @@ -1377,7 +1392,7 @@ int fileio_setparms(int op, struct fioparms * fp, -static int fmt_autodetect(char * fname) +static int fmt_autodetect(char * fname, size_t offset) { FILE * f; unsigned char buf[MAX_LINE_LEN]; @@ -1387,9 +1402,9 @@ static int fmt_autodetect(char * fname) int first = 1; #if defined(WIN32NATIVE) - f = fopen_utf8(fname, "r"); + f = fopen_and_seek(fname, "r", offset); #else - f = fopen(fname, "rb"); + f = fopen_and_seek(fname, "rb", offset); #endif if (f == NULL) { @@ -1465,7 +1480,7 @@ static int fmt_autodetect(char * fname) int fileio(int op, char * filename, FILEFMT format, - struct avrpart * p, char * memtype, int size) + struct avrpart * p, char * memtype, int size, size_t offset) { int rc; FILE * f; @@ -1497,15 +1512,17 @@ int fileio(int op, char * filename, FILEFMT format, using_stdio = 0; if (strcmp(filename, "-")==0) { - if (fio.op == FIO_READ) { - fname = ""; - f = stdin; - } - else { - fname = ""; - f = stdout; - } - using_stdio = 1; + return -1; + // Note: we don't want to read stdin or write to stdout as part of Slic3r + // if (fio.op == FIO_READ) { + // fname = ""; + // f = stdin; + // } + // else { + // fname = ""; + // f = stdout; + // } + // using_stdio = 1; } else { fname = filename; @@ -1522,7 +1539,7 @@ int fileio(int op, char * filename, FILEFMT format, return -1; } - format_detect = fmt_autodetect(fname); + format_detect = fmt_autodetect(fname, offset); if (format_detect < 0) { avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n", progname, fname); @@ -1553,7 +1570,7 @@ int fileio(int op, char * filename, FILEFMT format, if (format != FMT_IMM) { if (!using_stdio) { - f = fopen_utf8(fname, fio.mode); + f = fopen_and_seek(fname, fio.mode, offset); if (f == NULL) { avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n", progname, fio.iodesc, fname, strerror(errno)); diff --git a/xs/src/avrdude/libavrdude.h b/xs/src/avrdude/libavrdude.h index 238f59615..536f1a2f7 100644 --- a/xs/src/avrdude/libavrdude.h +++ b/xs/src/avrdude/libavrdude.h @@ -821,7 +821,7 @@ extern "C" { char * fmtstr(FILEFMT format); int fileio(int op, char * filename, FILEFMT format, - struct avrpart * p, char * memtype, int size); + struct avrpart * p, char * memtype, int size, size_t offset); #ifdef __cplusplus } @@ -870,6 +870,7 @@ enum updateflags { typedef struct update_t { char * memtype; int op; + size_t offset; char * filename; int format; } UPDATE; @@ -881,7 +882,7 @@ extern "C" { extern UPDATE * parse_op(char * s); extern UPDATE * dup_update(UPDATE * upd); extern UPDATE * new_update(int op, char * memtype, int filefmt, - char * filename); + char * filename, size_t offset); extern void free_update(UPDATE * upd); extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags); diff --git a/xs/src/avrdude/main.c b/xs/src/avrdude/main.c index 0550ceff1..91f2fc827 100644 --- a/xs/src/avrdude/main.c +++ b/xs/src/avrdude/main.c @@ -194,7 +194,7 @@ static void usage(void) " -F Override invalid signature check.\n" " -e Perform a chip erase.\n" " -O Perform RC oscillator calibration (see AVR053). \n" - " -U :r|w|v:[:format]\n" + " -U :r|w|v::[:format]\n" " Memory operation specification.\n" " Multiple -U options are allowed, each request\n" " is performed in the order specified.\n" diff --git a/xs/src/avrdude/update.c b/xs/src/avrdude/update.c index a73461dfa..fa3372476 100644 --- a/xs/src/avrdude/update.c +++ b/xs/src/avrdude/update.c @@ -101,6 +101,25 @@ UPDATE * parse_op(char * s) p++; + // Extension: Parse file contents offset + size_t offset = 0; + + for (; *p != ':'; p++) { + if (*p >= '0' && *p <= '9') { + offset *= 10; + offset += *p - 0x30; + } else { + avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname); + free(upd->memtype); + free(upd); + return NULL; + } + } + + upd->offset = offset; + printf("parse_op: offset: %lu\n", offset); + p++; + /* * Now, parse the filename component. Instead of looking for the * leftmost possible colon delimiter, we look for the rightmost one. @@ -176,7 +195,7 @@ UPDATE * dup_update(UPDATE * upd) return u; } -UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) +UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset) { UPDATE * u; @@ -190,6 +209,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename) u->filename = strdup(filename); u->op = op; u->format = filefmt; + u->offset = offset; return u; } @@ -250,7 +270,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f progname, strcmp(upd->filename, "-")==0 ? "" : upd->filename); } - rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size); + rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size, 0); if (rc < 0) { avrdude_message(MSG_INFO, "%s: write to file '%s' failed\n", progname, upd->filename); @@ -267,7 +287,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f progname, strcmp(upd->filename, "-")==0 ? "" : upd->filename); } - rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); + rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset); if (rc < 0) { avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", progname, upd->filename); @@ -296,11 +316,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f report_progress(1,1,NULL); } else { - /* - * test mode, don't actually write to the chip, output the buffer - * to stdout in intel hex instead - */ - rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size); + // /* + // * test mode, don't actually write to the chip, output the buffer + // * to stdout in intel hex instead + // */ + // rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size, 0); } if (rc < 0) { @@ -332,7 +352,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f progname, mem->desc, upd->filename); } - rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); + rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset); if (rc < 0) { avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n", progname, upd->filename); diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/xs/src/slic3r/GUI/FirmwareDialog.cpp index 136b17af6..f9aabacc0 100644 --- a/xs/src/slic3r/GUI/FirmwareDialog.cpp +++ b/xs/src/slic3r/GUI/FirmwareDialog.cpp @@ -182,8 +182,8 @@ void FirmwareDialog::priv::perform_upload() "-b", "115200", // XXX: is this ok to hardcode? "-D", "-u", // disable safe mode - "-U", (boost::format("flash:w:%1%:i") % filename_utf8.data()).str() -// "-v", "-v", "-v", "-v", "-v", // enable super verbose mode, logging each serial line exchange + "-U", (boost::format("flash:w:0:%1%:i") % filename_utf8.data()).str(), // FIXME + // "-vvvvv", //"-v", "-v", "-v", "-v", // enable super verbose mode, logging each serial line exchange }}; BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: " -- cgit v1.2.3