X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/blobdiff_plain/04e76de638c84c3cb88a7178764b700d5097e607..f276a46cb9b1387aed1542882f6341c1510c955f:/flash-hmcfgusb.c diff --git a/flash-hmcfgusb.c b/flash-hmcfgusb.c index c7781a0..8c858f2 100644 --- a/flash-hmcfgusb.c +++ b/flash-hmcfgusb.c @@ -1,6 +1,6 @@ -/* (not working) flasher for HM-CFG-USB +/* flasher for HM-CFG-USB * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2013-16 Michael Gernoth * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -36,129 +36,170 @@ #include #include "hexdump.h" +#include "firmware.h" +#include "version.h" #include "hmcfgusb.h" struct recv_data { + int ack; }; static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) { - if (buf_len < 1) + struct recv_data *rdata = data; + + if (buf_len != 1) return 1; - switch(buf[0]) { - case 'E': - case 'H': - case 'R': - case 'I': - break; - default: - hexdump(buf, buf_len, "Unknown> "); - break; - } + rdata->ack = buf[0]; return 1; } -static uint8_t ascii_to_nibble(uint8_t a) +void flash_hmcfgusb_syntax(char *prog) { - uint8_t c = 0x00; - - if ((a >= '0') && (a <= '9')) { - c = a - '0'; - } else if ((a >= 'A') && (a <= 'F')) { - c = (a - 'A') + 10; - } else if ((a >= 'a') && (a <= 'f')) { - c = (a - 'a') + 10; - } + fprintf(stderr, "Syntax: %s [options] filename.enc\n\n", prog); + fprintf(stderr, "Possible options:\n"); + fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n"); + fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); - return c; } int main(int argc, char **argv) { + const char twiddlie[] = { '-', '\\', '|', '/' }; struct hmcfgusb_dev *dev; struct recv_data rdata; - uint8_t out[4096]; - uint8_t buf[4096]; - uint8_t *outp; - int fd; - int r; - int i; - int cnt; - int pkt; + uint16_t len; + struct firmware *fw; + char *serial = NULL; + char *filename = NULL; + int block; + int pfd; + int opt; + int debug = 0; + + while((opt = getopt(argc, argv, "S:V")) != -1) { + switch (opt) { + case 'S': + serial = optarg; + break; + case 'V': + printf("flash-hmcfgusb " VERSION "\n"); + printf("Copyright (c) 2013-16 Michael Gernoth\n\n"); + exit(EXIT_SUCCESS); + case 'h': + case ':': + case '?': + default: + flash_hmcfgusb_syntax(argv[0]); + exit(EXIT_FAILURE); + break; + } + } + + if (optind == argc - 1) { + filename = argv[optind]; + } + + printf("HM-CFG-USB flasher version " VERSION "\n\n"); + + if (!filename) { + fprintf(stderr, "Missing firmware filename!\n\n"); + flash_hmcfgusb_syntax(argv[0]); + exit(EXIT_FAILURE); + } + + fw = firmware_read_firmware(filename, debug); + if (!fw) + exit(EXIT_FAILURE); - hmcfgusb_set_debug(0); + hmcfgusb_set_debug(debug); memset(&rdata, 0, sizeof(rdata)); - dev = hmcfgusb_init(parse_hmcfgusb, &rdata); + dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial); if (!dev) { fprintf(stderr, "Can't initialize HM-CFG-USB\n"); exit(EXIT_FAILURE); } - printf("HM-CFG-USB opened!\n"); - fd = open("hmusbif.enc", O_RDONLY); - if (fd < 0) { - perror("Can't open hmusbif.enc"); - exit(EXIT_FAILURE); + if (!dev->bootloader) { + fprintf(stderr, "\nHM-CFG-USB not in bootloader mode, entering bootloader.\n"); + fprintf(stderr, "\nWaiting for device to reappear...\n"); + + do { + if (dev) { + if (!dev->bootloader) + hmcfgusb_enter_bootloader(dev); + hmcfgusb_close(dev); + } + sleep(1); + } while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata, serial)) == NULL) || (!dev->bootloader)); } - cnt = 0; - pkt = 0; - do { - int len; + printf("\nHM-CFG-USB opened.\n\n"); - memset(buf, 0, sizeof(buf)); - r = read(fd, buf, 4); - if (r < 0) { - perror("read"); - exit(EXIT_FAILURE); - } else if (r == 0) { - break; - } else if (r != 4) { - printf("can't get length information!\n"); - exit(EXIT_FAILURE); - } - len = (ascii_to_nibble(buf[0]) & 0xf)<< 4; - len |= ascii_to_nibble(buf[1]) & 0xf; - len <<= 8; - len |= (ascii_to_nibble(buf[2]) & 0xf)<< 4; - len |= ascii_to_nibble(buf[3]) & 0xf; + printf("Flashing %d blocks", fw->fw_blocks); + if (debug) { + printf("\n"); + } else { + printf(": %c", twiddlie[0]); + fflush(stdout); + } + + for (block = 0; block < fw->fw_blocks; block++) { + len = fw->fw[block][2] << 8; + len |= fw->fw[block][3]; + + len += 4; /* block nr., length */ - printf("packet length: %x\n", len); + if (debug) + hexdump(fw->fw[block], len, "F> "); - r = read(fd, buf, len * 2); - if (r < 0) { - perror("read"); + rdata.ack = 0; + if (!hmcfgusb_send(dev, fw->fw[block], len, 0)) { + perror("\n\nhmcfgusb_send"); exit(EXIT_FAILURE); - } else if (r < len * 2) { - printf("short read, aborting (%d < %d)\n", r, len * 2); + } + + if (debug) + printf("Waiting for ack...\n"); + do { + errno = 0; + pfd = hmcfgusb_poll(dev, 1000); + if ((pfd < 0) && errno) { + if (errno != ETIMEDOUT) { + perror("\n\nhmcfgusb_poll"); + exit(EXIT_FAILURE); + } + } + if (rdata.ack) { + break; + } + } while (pfd < 0); + + if (rdata.ack == 2) { + printf("\n\nFirmware update successfull!\n"); break; } - memset(out, 0, sizeof(out)); - outp = out; - *outp++ = 'W'; - *outp++ = (pkt >> 8) & 0xff; - *outp++ = pkt & 0xff; - *outp++ = (len >> 8) & 0xff; - *outp++ = len & 0xff; - for (i = 0; i < r; i+=2) { - *outp = (ascii_to_nibble(buf[i]) & 0xf)<< 4; - *outp |= ascii_to_nibble(buf[i+1]) & 0xf; - outp++; + if (rdata.ack != 1) { + fprintf(stderr, "\n\nError flashing block %d, status: %u\n", block, rdata.ack); + exit(EXIT_FAILURE); } - cnt += r/2; - printf("Flashing %d bytes...\n", cnt); - hexdump(out, outp-out, "F> "); - //hmcfgusb_send(dev, out, r/2, 1); - pkt++; - } while (r > 0); + + if (!debug) { + printf("\b%c", twiddlie[block % sizeof(twiddlie)]); + fflush(stdout); + } + } + + firmware_free(fw); hmcfgusb_close(dev); + hmcfgusb_exit(); return EXIT_SUCCESS; }