diff --git a/avrprog.c b/avrprog.c index af00d821..4a0db623 100644 --- a/avrprog.c +++ b/avrprog.c @@ -71,6 +71,9 @@ char * version = "$Id$"; char * progname; +char progbuf[PATH_MAX]; /* temporary buffer of spaces the same + length as progname; used for lining up + multiline messages */ /* @@ -153,6 +156,26 @@ enum { }; +int cmd_dump(int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_write(int fd, struct avrpart * p, int argc, char *argv[]); +int cmd_quit(int fd, struct avrpart * p, int argc, char *argv[]); + +struct command { + char * name; + int (*func)(int fd, struct avrpart * p, int argc, char *argv[]); +}; + + +struct command cmd[] = { + { "dump", cmd_dump }, + { "write", cmd_write }, + { "quit", cmd_quit } +}; + +#define NCMDS (sizeof(cmd)/sizeof(struct command)) + + + #define MAX_LINE_LEN 256 /* max line length for ASCII format input files */ @@ -1235,6 +1258,482 @@ char * memtypestr ( AVRMEM memtype ) } +int nexttok ( char * buf, char ** tok, char ** next ) +{ + char * q, * n; + + q = buf; + while (isspace(*q)) + q++; + + /* isolate first token */ + n = q+1; + while (*n && !isspace(*n)) + n++; + + if (*n) { + *n = 0; + n++; + } + + /* find start of next token */ + while (isspace(*n)) + n++; + + *tok = q; + *next = n; + + return 0; +} + + +int hexdump_line ( char * buffer, unsigned char * p, int n, int pad ) +{ + char * hexdata = "0123456789abcdef"; + char * b; + int i, j; + + b = buffer; + + j = 0; + for (i=0; i> 4]; + b[j++] = hexdata[(p[i] & 0x0f)]; + if (i < 15) + b[j++] = ' '; + } + + for (i=j; i len) + n = len; + hexdump_line(dst1, p, n, 48); + chardump_line(dst2, p, n, 16); + fprintf(stdout, "%04x %s |%s|\n", addr, dst1, dst2); + len -= n; + addr += n; + p += n; + } + + return 0; +} + + +int cmd_dump ( int fd, struct avrpart * p, int argc, char * argv[] ) +{ + char * e; + int i, j; + int len, maxsize; + AVRMEM memtype; + unsigned short addr, daddr; + char * buf; + + if (argc != 4) { + fprintf(stderr, "Usage: dump flash|eeprom \n"); + return -1; + } + + if (strcmp(argv[1],"flash")==0) { + memtype = AVR_FLASH; + maxsize = p->flash_size; + } + else if (strcmp(argv[1],"eeprom")==0) { + memtype = AVR_EEPROM; + maxsize = p->eeprom_size; + } + else { + fprintf(stderr, "%s (dump): invalid memory type \"%s\"\n", + progname, argv[1]); + return -1; + } + + addr = strtoul(argv[2], &e, 0); + if (*e || (e == argv[2])) { + fprintf(stderr, "%s (dump): can't parse address \"%s\"\n", + progname, argv[2]); + return -1; + } + + len = strtol(argv[3], &e, 0); + if (*e || (e == argv[3])) { + fprintf(stderr, "%s (dump): can't parse length \"%s\"\n", + progname, argv[3]); + return -1; + } + + if (addr > maxsize) { + fprintf(stderr, + "%s (dump): address 0x%04x is out of range for %s memory\n", + progname, addr, memtypestr(memtype)); + return -1; + } + + if ((addr + len) > maxsize) { + fprintf(stderr, + "%s (dump): selected address and length exceed " + "range for %s memory\n", + progname, memtypestr(memtype)); + return -1; + } + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "%s (dump): out of memory\n", progname); + return -1; + } + + j = 0; + daddr = addr; + if (memtype == AVR_FLASH) { + daddr = addr / 2; + if (addr & 0x01) { + buf[j++] = avr_read_byte( fd, p, AVR_FLASH_HI, daddr); + daddr++; + } + } + + i = daddr; + while (j < len) { + if (memtype == AVR_FLASH) { + buf[j++] = avr_read_byte( fd, p, AVR_FLASH_LO, i); + if (j < len) { + buf[j++] = avr_read_byte( fd, p, AVR_FLASH_HI, i); + } + } + else { + buf[j++] = avr_read_byte( fd, p, AVR_EEPROM, i); + } + i++; + } + + hexdump_buf(stdout, addr, buf, len); + + fprintf(stdout, "\n"); + + free(buf); + + return 0; +} + +int cmd_write ( int fd, struct avrpart * p, int argc, char * argv[] ) +{ + char * e; + int i, j; + int len, maxsize; + AVRMEM memtype; + unsigned short addr, daddr; + char * buf; + int rc; + + if (argc < 4) { + fprintf(stderr, + "Usage: write flash|eeprom ... byteN>\n"); + return -1; + } + + if (strcmp(argv[1],"flash")==0) { + memtype = AVR_FLASH; + maxsize = p->flash_size; + } + else if (strcmp(argv[1],"eeprom")==0) { + memtype = AVR_EEPROM; + maxsize = p->eeprom_size; + } + else { + fprintf(stderr, "%s (write): invalid memory type \"%s\"\n", + progname, argv[1]); + return -1; + } + + addr = strtoul(argv[2], &e, 0); + if (*e || (e == argv[2])) { + fprintf(stderr, "%s (write): can't parse address \"%s\"\n", + progname, argv[2]); + return -1; + } + + if (addr > maxsize) { + fprintf(stderr, + "%s (write): address 0x%04x is out of range for %s memory\n", + progname, addr, memtypestr(memtype)); + return -1; + } + + /* number of bytes to write at the specified address */ + len = argc - 3; + + if ((addr + len) > maxsize) { + fprintf(stderr, + "%s (write): selected address and # bytes exceed " + "range for %s memory\n", + progname, memtypestr(memtype)); + return -1; + } + + buf = malloc(len); + if (buf == NULL) { + fprintf(stderr, "%s (write): out of memory\n", progname); + return -1; + } + + for (i=3; i "); + while (fgets(cmdbuf, MAX_LINE_LEN, stdin) != NULL) { + len = strlen(cmdbuf); + if (cmdbuf[len-1] == '\n') + cmdbuf[--len] = 0; + + /* + * find the start of the command, skipping any white space + */ + q = cmdbuf; + while (*q && isspace(*q)) + q++; + + /* skip blank lines and comments */ + if (!*q || (*q == '#')) + continue; + + /* tokenize command line */ + argc = tokenize(q, &argv); + + fprintf(stdout, ">>> "); + for (i=0; i 0) { + rc = 0; + break; + } +#endif + + fprintf(stdout, "avrprog> "); + } + + return rc; +} + + + /* * main routine */ @@ -1247,7 +1746,6 @@ int main ( int argc, char * argv [] ) int ch; /* options flag */ int size; /* size of memory region */ int len; /* length for various strings */ - char pbuf[PATH_MAX]; /* temporary buffer */ char * p1; /* used to parse CVS Id */ char * p2; /* used to parse CVS Ed */ unsigned char sig[4]; /* AVR signature bytes */ @@ -1286,8 +1784,8 @@ int main ( int argc, char * argv [] ) len = strlen(progname) + 2; for (i=0; ipartdesc, - pbuf, p->flash_size, - pbuf, p->eeprom_size, - pbuf, p->min_write_delay, p->max_write_delay, - pbuf, p->chip_erase_delay, - pbuf, p->f_readback, - pbuf, p->e_readback[0], p->e_readback[1]); + progbuf, p->partdesc, + progbuf, p->flash_size, + progbuf, p->eeprom_size, + progbuf, p->min_write_delay, p->max_write_delay, + progbuf, p->chip_erase_delay, + progbuf, p->f_readback, + progbuf, p->e_readback[0], p->e_readback[1]); fprintf(stderr, "\n"); p->flash = (unsigned char *) malloc(p->flash_size); @@ -1532,7 +2030,7 @@ int main ( int argc, char * argv [] ) fprintf(stderr, "%sDouble check connections and try again, or use -F to override\n" "%sthis check.\n\n", - pbuf, pbuf ); + progbuf, progbuf ); exit(1); } } @@ -1551,7 +2049,7 @@ int main ( int argc, char * argv [] ) } - if ((inputf==NULL) && (outputf==NULL)) { + if (!interactive && ((inputf==NULL) && (outputf==NULL))) { /* * Check here to see if any other operations were selected and * generate an error message because if they were, we need either @@ -1566,8 +2064,13 @@ int main ( int argc, char * argv [] ) goto main_exit; } - - if (doread) { + if (interactive) { + /* + * interactive command mode + */ + exitrc = go_interactive(fd, p); + } + else if (doread) { /* * read out the specified device memory and write it to a file */ @@ -1636,7 +2139,7 @@ int main ( int argc, char * argv [] ) close(fd); - fprintf(stderr, "\n" ); + fprintf(stderr, "\n%s done. Thank you.\n\n", progname); return exitrc; }