-
-
Save jscrane/7342807 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <sys/select.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <termios.h> | |
#include <string.h> | |
#include <unistd.h> | |
int p; | |
FILE *f; | |
void quit(int stat) | |
{ | |
if (p > 0) | |
close(p); | |
if (f) | |
fclose(f); | |
exit(stat); | |
} | |
void fail(const char *s) | |
{ | |
printf("%s\n", s); | |
quit(-1); | |
} | |
void perror_exit(const char *s) | |
{ | |
perror(s); | |
quit(-1); | |
} | |
int read_from_device(int p, unsigned char *buf, int len) | |
{ | |
fd_set rd; | |
int i, off; | |
FD_ZERO(&rd); | |
off = 0; | |
for (i = 0; i < 60; i++) { | |
struct timeval tv; | |
int n; | |
tv.tv_sec = 0; | |
tv.tv_usec = 50000; | |
FD_SET(p, &rd); | |
n = select(p+1, &rd, 0, 0, &tv); | |
if (0 > n) | |
perror_exit("select"); | |
if (n > 0) { | |
n = read(p, buf+off, len-off); | |
off += n; | |
} | |
if (buf[off-1] == '!' || buf[off-1] == '?') | |
return off; | |
} | |
return -1; | |
} | |
void read_request(int p, unsigned char *buf, int len) | |
{ | |
if (0 > read_from_device(p, buf, sizeof(buf))) | |
fail("got nothing from device"); | |
if (buf[0] != '?') { | |
fprintf(stderr, "expected request from device: %s\n", buf); | |
quit(-1); | |
} | |
} | |
int main(int argc, char *argv[]) | |
{ | |
const char *port, *file; | |
struct termios term; | |
unsigned char buf[256], ihex[65536]; | |
int n, i, off; | |
unsigned char fwstat; | |
unsigned int sig, maxaddr = 0; | |
unsigned short fwdate, psize, flash, eeprom; | |
#ifdef notdef | |
int jmpmode = 0, tinymega = 0; | |
#endif | |
int verbose = (strcmp(argv[1], "-v") == 0); | |
if (verbose) { | |
port = argv[2]; | |
file = argv[3]; | |
} else { | |
port = argv[1]; | |
file = argv[2]; | |
} | |
p = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK); | |
if (0 > p) | |
perror_exit(port); | |
f = fopen(file, "r"); | |
if (!f) | |
perror_exit(file); | |
if (0 > tcgetattr(p, &term)) | |
perror_exit("tcgetattr"); | |
tcflush(p, TCIOFLUSH); | |
cfsetspeed(&term, B9600); | |
cfmakeraw(&term); | |
if (0 > tcsetattr(p, 0, &term)) | |
perror_exit("tcsetattr"); | |
usleep(100000); | |
n = write(p, "@@@", 3); | |
if (0 > n) | |
perror_exit("write @@@"); | |
off = read_from_device(p, buf, sizeof(buf)); | |
if (0 > off) | |
fail("got nothing from device"); | |
if (buf[0] == 't' && buf[1] == 's' && buf[2] == 'b') { | |
fwdate = (buf[4] << 8) + buf[3]; | |
fwstat = buf[5]; | |
sig = (buf[6] << 16) + (buf[7] << 8) + buf[8]; | |
psize = 2 * buf[9]; | |
flash = 2*((buf[11] << 8) + buf[10]); | |
eeprom = (buf[13] << 8) + buf[12] + 1; | |
#ifdef notdef | |
jmpmode = 0, tinymega = 0; | |
if (buf[14] == 0x0c) | |
jmpmode = 1; | |
else if (buf[14] == 0xaa) | |
tinymega = 1; | |
#endif | |
if (verbose) | |
printf("fwdate: %2x\nfwstat: %1x\nsig: %x\npsize: %d\nflash: %d\neeprom: %d\n", fwdate, fwstat, sig, psize, flash, eeprom); | |
} else { | |
fprintf(stderr, "unexpected response: %s\n", buf); | |
quit(-1); | |
} | |
memset(ihex, 0xff, sizeof(ihex)); | |
for (;;) { | |
unsigned bytes, addr, type; | |
char data[64]; | |
int m = fscanf(f, ":%2x%4x%2x%[0-9A-F]\n", &bytes, &addr, &type, data); | |
if (m == EOF) | |
break; | |
if (type == 0) { | |
if (verbose) | |
printf("%02x %04x %s\n", bytes, addr, data); | |
for (i = 0; i < bytes; i++) { | |
unsigned x; | |
sscanf(data+(2*i), "%2x", &x); | |
ihex[addr+i] = x; | |
} | |
if (addr+i > maxaddr) | |
maxaddr = addr + i; | |
} | |
} | |
if ((maxaddr % psize) != 0) | |
maxaddr = ((maxaddr / psize) + 1) * psize; | |
if (verbose) | |
printf("maxaddr: %d flash: %d\n", maxaddr, flash); | |
n = write(p, "F", 1); | |
if (0 > n) | |
perror_exit("write F"); | |
read_request(p, buf, sizeof(buf)); | |
for (i = 0; i < maxaddr; i += psize) { | |
n = write(p, "!", 1); | |
if (0 > n) | |
perror_exit("write confirm"); | |
n = write(p, ihex+i, psize); | |
if (0 > n) | |
perror_exit("write page"); | |
read_request(p, buf, sizeof(buf)); | |
} | |
if (maxaddr < flash) { | |
n = write(p, "?", 1); | |
if (0 > n) | |
perror_exit("write request"); | |
n = read_from_device(p, buf, sizeof(buf)); | |
if (0 > n || buf[0] != '!') | |
fail("read confirm"); | |
} | |
n = write(p, "q", 1); | |
if (0 > n) | |
perror_exit("write quit"); | |
quit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Your script works great on Mac OS X too, thanks!