Create a gist now

Instantly share code, notes, and snippets.

@jscrane /fw.c
Last active Dec 27, 2015

What would you like to do?
#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);
}
@kalle
kalle commented Dec 30, 2013

Your script works great on Mac OS X too, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment