X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/blobdiff_plain/25870f587b45735699cc4479034cb864116b2f22..f0ed61ccc59824976a1ea45318b926bf75ebbe2d:/flash-ota.c diff --git a/flash-ota.c b/flash-ota.c index 46d3adb..4279aa9 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -41,7 +41,10 @@ #include "version.h" #include "hmcfgusb.h" +#define MAX_RETRIES 5 + uint32_t hmid = 0; +uint32_t my_hmid = 0; enum message_type { MESSAGE_TYPE_E, @@ -53,6 +56,7 @@ struct recv_data { enum message_type message_type; uint16_t status; int speed; + uint16_t hmcfgusb_version; }; static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) @@ -82,6 +86,10 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) case 'G': rdata->speed = buf[1]; break; + case 'H': + rdata->hmcfgusb_version = (buf[11] << 8) | buf[12]; + my_hmid = (buf[0x1b] << 16) | (buf[0x1c] << 8) | buf[0x1d]; + break; default: break; } @@ -121,7 +129,7 @@ int send_hm_message(struct hmcfgusb_dev *dev, struct recv_data *rdata, uint8_t * memcpy(&out[0x0f], msg, msg[0] + 1); memset(rdata, 0, sizeof(struct recv_data)); - hmcfgusb_send(dev, out, sizeof(out), 2); + hmcfgusb_send(dev, out, sizeof(out), 1); while (1) { if (rdata->message_type == MESSAGE_TYPE_R) { @@ -129,7 +137,13 @@ int send_hm_message(struct hmcfgusb_dev *dev, struct recv_data *rdata, uint8_t * ((rdata->status & 0xff) == 0x02)) { break; } else { - fprintf(stderr, "\n\nInvalid status: %04x\n\n", rdata->status); + if ((rdata->status & 0xff00) == 0x0400) { + fprintf(stderr, "\nOut of credits!\n"); + } else if ((rdata->status & 0xff) == 0x08) { + fprintf(stderr, "\nMissing ACK!\n"); + } else { + fprintf(stderr, "\nInvalid status: %04x\n", rdata->status); + } return 0; } } @@ -147,10 +161,39 @@ int send_hm_message(struct hmcfgusb_dev *dev, struct recv_data *rdata, uint8_t * return 1; } +static int switch_speed(struct hmcfgusb_dev *dev, struct recv_data *rdata, uint8_t speed) +{ + uint8_t out[0x40]; + int pfd; + + printf("Entering %uk-mode\n", speed); + + memset(out, 0, sizeof(out)); + out[0] = 'G'; + out[1] = speed; + + hmcfgusb_send(dev, out, sizeof(out), 1); + + while (1) { + errno = 0; + pfd = hmcfgusb_poll(dev, 1); + if ((pfd < 0) && errno) { + if (errno != ETIMEDOUT) { + perror("\n\nhmcfgusb_poll"); + exit(EXIT_FAILURE); + } + } + if (rdata->speed == speed) + break; + } + + return 1; +} + int main(int argc, char **argv) { const char twiddlie[] = { '-', '\\', '|', '/' }; - const uint8_t switch_msg[] = { 0x10, 0x5B, 0x11, 0xF8, 0x15, 0x47 }; + const uint8_t cc1101_regs[] = { 0x10, 0x5B, 0x11, 0xF8, 0x15, 0x47 }; struct hmcfgusb_dev *dev; struct recv_data rdata; uint8_t out[0x40]; @@ -162,6 +205,7 @@ int main(int argc, char **argv) int pfd; int debug = 0; int cnt; + int switchcnt = 0; int msgnum = 0; int switched = 0; @@ -192,18 +236,37 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if (dev->bootloader) { - fprintf(stderr, "\nHM-CFG-USB not in bootloader mode, aborting!\n"); - exit(EXIT_FAILURE); + printf("\nRebooting HM-CFG-USB to avoid running out of credits\n\n"); + + if (!dev->bootloader) { + printf("HM-CFG-USB not in bootloader mode, entering bootloader.\n"); + hmcfgusb_enter_bootloader(dev); + printf("Waiting for device to reappear...\n"); + + do { + if (dev) { + hmcfgusb_close(dev); + } + sleep(1); + } while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL) || (!dev->bootloader)); } - printf("\nHM-CFG-USB opened\n\n"); + if (dev->bootloader) { + printf("HM-CFG-USB in bootloader mode, rebooting\n"); + hmcfgusb_leave_bootloader(dev); - printf("Entering 10k-mode\n"); + do { + if (dev) { + hmcfgusb_close(dev); + } + sleep(1); + } while (((dev = hmcfgusb_init(parse_hmcfgusb, &rdata)) == NULL) || (dev->bootloader)); + } + + printf("\n\nHM-CFG-USB opened\n\n"); memset(out, 0, sizeof(out)); - out[0] = 'G'; - out[1] = 10; + out[0] = 'K'; hmcfgusb_send(dev, out, sizeof(out), 1); while (1) { @@ -215,10 +278,22 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } - if (rdata.speed == 10) + if (rdata.hmcfgusb_version) break; } + if (rdata.hmcfgusb_version < 0x3c7) { + fprintf(stderr, "HM-CFG-USB firmware too low: %u < 967\n", rdata.hmcfgusb_version); + exit(EXIT_FAILURE); + } + + printf("HM-CFG-USB firmware version: %u\n", rdata.hmcfgusb_version); + + if (!switch_speed(dev, &rdata, 10)) { + fprintf(stderr, "Can't switch speed!\n"); + exit(EXIT_FAILURE); + } + printf("Waiting for device with serial %s\n", argv[2]); while (1) { @@ -256,8 +331,9 @@ int main(int argc, char **argv) out[2] = (hmid >> 8) & 0xff; out[3] = hmid & 0xff; - hmcfgusb_send(dev, out, sizeof(out), 2); + hmcfgusb_send(dev, out, sizeof(out), 1); + switchcnt = 3; do { printf("Initiating remote switch to 100k\n"); @@ -266,35 +342,19 @@ int main(int argc, char **argv) out[MSGID] = msgid++; out[CTL] = 0x00; out[TYPE] = 0xCB; - SET_SRC(out, 0x000000); + SET_SRC(out, my_hmid); SET_DST(out, hmid); - memcpy(&out[PAYLOAD], switch_msg, sizeof(switch_msg)); - SET_LEN_FROM_PAYLOADLEN(out, sizeof(switch_msg)); + memcpy(&out[PAYLOAD], cc1101_regs, sizeof(cc1101_regs)); + SET_LEN_FROM_PAYLOADLEN(out, sizeof(cc1101_regs)); if (!send_hm_message(dev, &rdata, out)) { exit(EXIT_FAILURE); } - printf("Entering 100k-mode\n"); - - memset(out, 0, sizeof(out)); - out[0] = 'G'; - out[1] = 100; - - hmcfgusb_send(dev, out, sizeof(out), 2); - - while (1) { - errno = 0; - pfd = hmcfgusb_poll(dev, 1); - if ((pfd < 0) && errno) { - if (errno != ETIMEDOUT) { - perror("\n\nhmcfgusb_poll"); - exit(EXIT_FAILURE); - } - } - if (rdata.speed == 100) - break; + if (!switch_speed(dev, &rdata, 100)) { + fprintf(stderr, "Can't switch speed!\n"); + exit(EXIT_FAILURE); } printf("Has the device switched?\n"); @@ -304,11 +364,11 @@ int main(int argc, char **argv) out[MSGID] = msgid++; out[CTL] = 0x20; out[TYPE] = 0xCB; - SET_SRC(out, 0x000000); + SET_SRC(out, my_hmid); SET_DST(out, hmid); - memcpy(&out[PAYLOAD], switch_msg, sizeof(switch_msg)); - SET_LEN_FROM_PAYLOADLEN(out, sizeof(switch_msg)); + memcpy(&out[PAYLOAD], cc1101_regs, sizeof(cc1101_regs)); + SET_LEN_FROM_PAYLOADLEN(out, sizeof(cc1101_regs)); cnt = 3; do { @@ -321,30 +381,21 @@ int main(int argc, char **argv) } while (cnt--); if (!switched) { - printf("Entering 10k-mode\n"); + printf("No!\n"); - memset(out, 0, sizeof(out)); - out[0] = 'G'; - out[1] = 10; - hmcfgusb_send(dev, out, sizeof(out), 1); - - while (1) { - errno = 0; - pfd = hmcfgusb_poll(dev, 1); - if ((pfd < 0) && errno) { - if (errno != ETIMEDOUT) { - perror("\n\nhmcfgusb_poll"); - exit(EXIT_FAILURE); - } - } - if (rdata.speed == 10) - break; + if (!switch_speed(dev, &rdata, 10)) { + fprintf(stderr, "Can't switch speed!\n"); + exit(EXIT_FAILURE); } } - } while (!switched); + } while ((!switched) && (switchcnt--)); + if (!switched) { + fprintf(stderr, "Too many errors, giving up!\n"); + exit(EXIT_FAILURE); + } - printf("Initiating firmware upload!\n"); + printf("Yes!\n"); printf("Flashing %d blocks", fw->fw_blocks); if (debug) { @@ -388,11 +439,11 @@ int main(int argc, char **argv) memset(out, 0, sizeof(out)); - out[MSGID] = msgid++; + out[MSGID] = msgid; if (ack) out[CTL] = 0x20; out[TYPE] = 0xCA; - SET_SRC(out, 0x000000); + SET_SRC(out, my_hmid); SET_DST(out, hmid); memcpy(&out[PAYLOAD], pos, payloadlen); @@ -403,7 +454,7 @@ int main(int argc, char **argv) } else { pos = &(fw->fw[block][2]); cnt++; - if (cnt == 3) { + if (cnt == MAX_RETRIES) { fprintf(stderr, "\nToo many errors, giving up!\n"); exit(EXIT_FAILURE); } else { @@ -419,28 +470,16 @@ int main(int argc, char **argv) fflush(stdout); } } while((pos - &(fw->fw[block][2])) < len); + msgid++; } firmware_free(fw); - printf("Entering 10k-mode\n"); - - memset(out, 0, sizeof(out)); - out[0] = 'G'; - out[1] = 10; - hmcfgusb_send(dev, out, sizeof(out), 1); + printf("\n"); - while (1) { - errno = 0; - pfd = hmcfgusb_poll(dev, 1); - if ((pfd < 0) && errno) { - if (errno != ETIMEDOUT) { - perror("\n\nhmcfgusb_poll"); - exit(EXIT_FAILURE); - } - } - if (rdata.speed == 10) - break; + if (!switch_speed(dev, &rdata, 10)) { + fprintf(stderr, "Can't switch speed!\n"); + exit(EXIT_FAILURE); } printf("Waiting for device to reboot\n");