From 9f0bab377660d3855af785c5ddbc19f69818468e Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 5 Mar 2014 02:35:28 +0100 Subject: [PATCH 01/16] fix poll --- culfw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/culfw.c b/culfw.c index 1904bb7..72c5c6a 100644 --- a/culfw.c +++ b/culfw.c @@ -167,7 +167,8 @@ int culfw_poll(struct culfw_dev *dev, int timeout) dev->cb(buf, r, dev->cb_data); - return pfds[0].fd; + errno = 0; + return -1; } void culfw_close(struct culfw_dev *dev) -- 2.39.2 From cda220240e89e21e8b7dd76ab6b6a56000ce20e6 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 5 Mar 2014 08:26:09 +0100 Subject: [PATCH 02/16] increase hm-buffer for culfw-devices --- flash-ota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flash-ota.c b/flash-ota.c index 9126768..7afab13 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -207,7 +207,7 @@ int send_hm_message(struct ota_dev *dev, struct recv_data *rdata, uint8_t *msg) break; case DEVICE_TYPE_CULFW: { - char buf[128]; + char buf[256]; int i; memset(buf, 0, sizeof(buf)); -- 2.39.2 From 0edcd7f291b728aee5e0c99434d2d8d9d81f6af6 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 5 Mar 2014 08:56:19 +0100 Subject: [PATCH 03/16] fix variable assignment, copyright year --- culfw.c | 2 +- culfw.h | 2 +- flash-ota.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/culfw.c b/culfw.c index 72c5c6a..0dfb807 100644 --- a/culfw.c +++ b/culfw.c @@ -1,6 +1,6 @@ /* culfw driver * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2014 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 diff --git a/culfw.h b/culfw.h index 8f64433..29aacaf 100644 --- a/culfw.h +++ b/culfw.h @@ -1,6 +1,6 @@ /* culfw driver * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2014 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 diff --git a/flash-ota.c b/flash-ota.c index 7afab13..fdd5936 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -450,8 +450,8 @@ int main(int argc, char **argv) printf("Waiting for device with serial %s\n", serial); while (1) { + errno = 0; switch (dev.type) { - errno = 0; case DEVICE_TYPE_CULFW: pfd = culfw_poll(dev.culfw, 1); break; -- 2.39.2 From a65c08fc834ac57cb4aab5470ca144d13076a2bd Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 5 Mar 2014 11:41:00 +0100 Subject: [PATCH 04/16] add culfw firmware version-check --- culfw.c | 31 ++++++++++++++++ culfw.h | 1 + flash-ota.c | 105 +++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 116 insertions(+), 21 deletions(-) diff --git a/culfw.c b/culfw.c index 0dfb807..a4c949b 100644 --- a/culfw.c +++ b/culfw.c @@ -175,3 +175,34 @@ void culfw_close(struct culfw_dev *dev) { close(dev->fd); } + +void culfw_flush(struct culfw_dev *dev) +{ + struct pollfd pfds[1]; + int ret; + int r = 0; + uint8_t buf[1024]; + + tcflush(dev->fd, TCIOFLUSH); + + while(1) { + memset(pfds, 0, sizeof(struct pollfd) * 1); + + pfds[0].fd = dev->fd; + pfds[0].events = POLLIN; + + ret = poll(pfds, 1, 100); + if (ret <= 0) + break; + + if (!(pfds[0].revents & POLLIN)) + break; + + memset(buf, 0, sizeof(buf)); + r = read(dev->fd, buf, sizeof(buf)); + if (r <= 0) + break; + } + + return; +} diff --git a/culfw.h b/culfw.h index 29aacaf..6f310fc 100644 --- a/culfw.h +++ b/culfw.h @@ -35,3 +35,4 @@ struct culfw_dev *culfw_init(char *device, uint32_t speed, culfw_cb_fn cb, void int culfw_send(struct culfw_dev *dev, char *cmd, int cmdlen); int culfw_poll(struct culfw_dev *dev, int timeout); void culfw_close(struct culfw_dev *dev); +void culfw_flush(struct culfw_dev *dev); diff --git a/flash-ota.c b/flash-ota.c index fdd5936..31e2ab5 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -71,7 +71,7 @@ struct recv_data { enum message_type message_type; uint16_t status; int speed; - uint16_t hmcfgusb_version; + uint16_t version; }; static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) @@ -102,7 +102,7 @@ static int parse_hmcfgusb(uint8_t *buf, int buf_len, void *data) rdata->speed = buf[1]; break; case 'H': - rdata->hmcfgusb_version = (buf[11] << 8) | buf[12]; + rdata->version = (buf[11] << 8) | buf[12]; my_hmid = (buf[0x1b] << 16) | (buf[0x1c] << 8) | buf[0x1d]; break; default: @@ -125,25 +125,57 @@ static int parse_culfw(uint8_t *buf, int buf_len, void *data) if (buf_len <= 3) return 0; - if (buf[0] != 'A') - return 0; + switch(buf[0]) { + case 'A': + if (buf[1] == 's') + return 0; + + while(validate_nibble(buf[(pos * 2) + 1]) && + validate_nibble(buf[(pos * 2) + 2]) && + (pos + 1 < buf_len)) { + rdata->message[pos] = ascii_to_nibble(buf[(pos * 2) + 1]) << 4; + rdata->message[pos] |= ascii_to_nibble(buf[(pos * 2) + 2]); + pos++; + } - if (buf[1] == 's') - return 0; + if (hmid && (SRC(rdata->message) != hmid)) + return 0; - while(validate_nibble(buf[(pos * 2) + 1]) && - validate_nibble(buf[(pos * 2) + 2]) && - (pos + 1 < buf_len)) { - rdata->message[pos] = ascii_to_nibble(buf[(pos * 2) + 1]) << 4; - rdata->message[pos] |= ascii_to_nibble(buf[(pos * 2) + 2]); - pos++; + rdata->message_type = MESSAGE_TYPE_E; + break; + case 'V': + { + uint8_t v; + char *s; + char *e; + + s = ((char*)buf) + 2; + e = strchr(s, '.'); + if (!e) { + fprintf(stderr, "Unknown response from CUL: %s", buf); + return 0; + } + *e = '\0'; + v = atoi(s); + rdata->version = v << 8; + + s = e + 1; + e = strchr(s, ' '); + if (!e) { + fprintf(stderr, "Unknown response from CUL: %s", buf); + return 0; + } + *e = '\0'; + v = atoi(s); + rdata->version |= v; + } + break; + default: + fprintf(stderr, "Unknown response from CUL: %s", buf); + return 0; + break; } - if (hmid && (SRC(rdata->message) != hmid)) - return 0; - - rdata->message_type = MESSAGE_TYPE_E; - return 1; } @@ -372,12 +404,43 @@ int main(int argc, char **argv) memset(&dev, 0, sizeof(struct ota_dev)); if (culfw_dev) { + printf("Opening culfw-device at path %s with speed %u\n", culfw_dev, bps); dev.culfw = culfw_init(culfw_dev, bps, parse_culfw, &rdata); if (!dev.culfw) { fprintf(stderr, "Can't initialize CUL at %s with rate %u\n", culfw_dev, bps); exit(EXIT_FAILURE); } dev.type = DEVICE_TYPE_CULFW; + + printf("Requesting firmware-version\n"); + culfw_send(dev.culfw, "\r\n", 2); + culfw_flush(dev.culfw); + + while (1) { + culfw_send(dev.culfw, "V\r\n", 3); + + errno = 0; + pfd = culfw_poll(dev.culfw, 1); + if ((pfd < 0) && errno) { + if (errno != ETIMEDOUT) { + perror("\n\nhmcfgusb_poll"); + exit(EXIT_FAILURE); + } + } + if (rdata.version) + break; + } + + printf("culfw-device firmware version: %u.%02u\n", + (rdata.version >> 8) & 0xff, + rdata.version & 0xff); + + if (rdata.version < 0x0139) { + fprintf(stderr, "\nThis version does _not_ support firmware upgrade mode!\n"); + exit(EXIT_FAILURE); + } else if (rdata.version < 0x0140) { + printf("\n*** This version probably not supports firmware upgrade mode! ***\n\n"); + } } else { hmcfgusb_set_debug(debug); @@ -430,16 +493,16 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } - if (rdata.hmcfgusb_version) + if (rdata.version) break; } - if (rdata.hmcfgusb_version < 0x3c7) { - fprintf(stderr, "HM-CFG-USB firmware too low: %u < 967\n", rdata.hmcfgusb_version); + if (rdata.version < 0x3c7) { + fprintf(stderr, "HM-CFG-USB firmware too low: %u < 967\n", rdata.version); exit(EXIT_FAILURE); } - printf("HM-CFG-USB firmware version: %u\n", rdata.hmcfgusb_version); + printf("HM-CFG-USB firmware version: %u\n", rdata.version); } if (!switch_speed(&dev, &rdata, 10)) { -- 2.39.2 From 3b35a8c145cb567b625d32030ba3a287b478dd43 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Thu, 6 Mar 2014 22:37:49 +0100 Subject: [PATCH 05/16] increase timeout granularity to handle missing acks on culfw-devices --- culfw.c | 2 +- flash-hmcfgusb.c | 2 +- flash-ota.c | 18 +++++++++--------- hmcfgusb.c | 8 +++----- hmland.c | 2 +- hmsniff.c | 2 +- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/culfw.c b/culfw.c index a4c949b..6cfa975 100644 --- a/culfw.c +++ b/culfw.c @@ -141,7 +141,7 @@ int culfw_poll(struct culfw_dev *dev, int timeout) pfds[0].fd = dev->fd; pfds[0].events = POLLIN; - ret = poll(pfds, 1, timeout * 1000); + ret = poll(pfds, 1, timeout); if (ret == -1) return -1; diff --git a/flash-hmcfgusb.c b/flash-hmcfgusb.c index 45d467f..0f0b9ce 100644 --- a/flash-hmcfgusb.c +++ b/flash-hmcfgusb.c @@ -134,7 +134,7 @@ int main(int argc, char **argv) printf("Waiting for ack...\n"); do { errno = 0; - pfd = hmcfgusb_poll(dev, 1); + pfd = hmcfgusb_poll(dev, 1000); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nhmcfgusb_poll"); diff --git a/flash-ota.c b/flash-ota.c index 31e2ab5..634e19b 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -228,7 +228,7 @@ int send_hm_message(struct ota_dev *dev, struct recv_data *rdata, uint8_t *msg) } } errno = 0; - pfd = hmcfgusb_poll(dev->hmcfgusb, 1); + pfd = hmcfgusb_poll(dev->hmcfgusb, 1000); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nhmcfgusb_poll"); @@ -263,7 +263,7 @@ int send_hm_message(struct ota_dev *dev, struct recv_data *rdata, uint8_t *msg) int pfd; do { errno = 0; - pfd = culfw_poll(dev->culfw, 1); + pfd = culfw_poll(dev->culfw, 200); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nculfw_poll"); @@ -305,7 +305,7 @@ static int switch_speed(struct ota_dev *dev, struct recv_data *rdata, uint8_t sp while (1) { errno = 0; - pfd = hmcfgusb_poll(dev->hmcfgusb, 1); + pfd = hmcfgusb_poll(dev->hmcfgusb, 1000); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nhmcfgusb_poll"); @@ -420,7 +420,7 @@ int main(int argc, char **argv) culfw_send(dev.culfw, "V\r\n", 3); errno = 0; - pfd = culfw_poll(dev.culfw, 1); + pfd = culfw_poll(dev.culfw, 1000); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nhmcfgusb_poll"); @@ -486,7 +486,7 @@ int main(int argc, char **argv) while (1) { errno = 0; - pfd = hmcfgusb_poll(dev.hmcfgusb, 1); + pfd = hmcfgusb_poll(dev.hmcfgusb, 1000); if ((pfd < 0) && errno) { if (errno != ETIMEDOUT) { perror("\n\nhmcfgusb_poll"); @@ -516,11 +516,11 @@ int main(int argc, char **argv) errno = 0; switch (dev.type) { case DEVICE_TYPE_CULFW: - pfd = culfw_poll(dev.culfw, 1); + pfd = culfw_poll(dev.culfw, 1000); break; case DEVICE_TYPE_HMCFGUSB: default: - pfd = hmcfgusb_poll(dev.hmcfgusb, 1); + pfd = hmcfgusb_poll(dev.hmcfgusb, 1000); break; } @@ -713,11 +713,11 @@ int main(int argc, char **argv) errno = 0; switch(dev.type) { case DEVICE_TYPE_CULFW: - pfd = culfw_poll(dev.culfw, 1); + pfd = culfw_poll(dev.culfw, 1000); break; case DEVICE_TYPE_HMCFGUSB: default: - pfd = hmcfgusb_poll(dev.hmcfgusb, 1); + pfd = hmcfgusb_poll(dev.hmcfgusb, 1000); break; } if ((pfd < 0) && errno) { diff --git a/hmcfgusb.c b/hmcfgusb.c index c90410a..0e11866 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -433,13 +433,11 @@ int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout) return -1; } else if (err == 0) { /* No pending timeout or a sane platform */ - tv.tv_sec = timeout; } else { if ((tv.tv_sec == 0) && (tv.tv_usec == 0)) { usb_event = 1; - } else if (tv.tv_sec > timeout) { - tv.tv_sec = timeout; - tv.tv_usec = 0; + } else if ((tv.tv_sec * 1000) < timeout) { + timeout = tv.tv_sec * 1000; } } @@ -448,7 +446,7 @@ int hmcfgusb_poll(struct hmcfgusb_dev *dev, int timeout) dev->pfd[i].revents = 0; } - n = poll(dev->pfd, dev->n_pfd, tv.tv_sec * 1000); + n = poll(dev->pfd, dev->n_pfd, timeout); if (n < 0) { perror("poll"); errno = 0; diff --git a/hmland.c b/hmland.c index fd2d09e..38cd7a3 100644 --- a/hmland.c +++ b/hmland.c @@ -508,7 +508,7 @@ static int comm(int fd_in, int fd_out, int master_socket, int flags) while(!quit) { int fd; - fd = hmcfgusb_poll(dev, 1); /* Wakeup device/bus at least once a second */ + fd = hmcfgusb_poll(dev, 1000); /* Wakeup device/bus at least once a second */ if (fd >= 0) { if (fd == master_socket) { int client; diff --git a/hmsniff.c b/hmsniff.c index 39133d3..a3cbe7a 100644 --- a/hmsniff.c +++ b/hmsniff.c @@ -201,7 +201,7 @@ int main(int argc, char **argv) rdata.wrong_hmid = 0; hmcfgusb_send(dev, (unsigned char*)"K", 1, 1); } - fd = hmcfgusb_poll(dev, 1); + fd = hmcfgusb_poll(dev, 1000); if (fd >= 0) { fprintf(stderr, "activity on unknown fd %d!\n", fd); continue; -- 2.39.2 From 57b387cefd9d05e3c44db6386b171f84b2dc66bb Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Fri, 14 Mar 2014 20:55:37 +0100 Subject: [PATCH 06/16] fix culfw version-check --- flash-ota.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/flash-ota.c b/flash-ota.c index 634e19b..5efd027 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -435,11 +435,9 @@ int main(int argc, char **argv) (rdata.version >> 8) & 0xff, rdata.version & 0xff); - if (rdata.version < 0x0139) { - fprintf(stderr, "\nThis version does _not_ support firmware upgrade mode!\n"); + if (rdata.version < 0x013a) { + fprintf(stderr, "\nThis version does _not_ support firmware upgrade mode, you need at least 1.58!\n"); exit(EXIT_FAILURE); - } else if (rdata.version < 0x0140) { - printf("\n*** This version probably not supports firmware upgrade mode! ***\n\n"); } } else { hmcfgusb_set_debug(debug); -- 2.39.2 From 6703483b89043091ff28ca2c1ebfd93aedc3d3db Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 16 Mar 2014 17:57:26 +0100 Subject: [PATCH 07/16] bump version to 0.096-git --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index 417afbb..cccf8c8 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "0.095-git" +#define VERSION "0.096-git" -- 2.39.2 From c8cafbead818c84304552d269535e7342852522d Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Wed, 14 May 2014 10:08:36 +0200 Subject: [PATCH 08/16] only reboot by default when firmware-version is < 0.967 --- hmland.c | 25 ++++++++++++++++++++++--- version.h | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/hmland.c b/hmland.c index 38cd7a3..6dc2cac 100644 --- a/hmland.c +++ b/hmland.c @@ -55,6 +55,7 @@ static int verbose = 0; static int reboot_seconds = 0; static int reboot_at_hour = -1; static int reboot_at_minute = -1; +static int reboot_set = 0; struct queued_rx { char *rx; @@ -211,6 +212,7 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) uint8_t out[1024]; uint8_t *outpos; uint8_t *inpos; + uint16_t version; int fd = *((int*)data); int w; @@ -230,6 +232,8 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) buf[7] = 'N'; } format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 0, FLAG_LENGTH_BYTE); + version = inpos[0] << 8; + version |= inpos[1]; format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 2, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE); format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 0, FLAG_COMMA_BEFORE | FLAG_LENGTH_BYTE); format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 3, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE); @@ -237,6 +241,22 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 4, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE); format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 2, FLAG_FORMAT_HEX | FLAG_COMMA_BEFORE | FLAG_NL); + if (!reboot_set) { + int new_reboot_seconds; + + if (version < 0x03c7) { + new_reboot_seconds = DEFAULT_REBOOT_SECONDS; + } else { + new_reboot_seconds = 0; + } + + if (verbose && new_reboot_seconds && (reboot_seconds != new_reboot_seconds)) + printf("Rebooting in %u seconds due to old firmware (0.%d)\n", + new_reboot_seconds, version); + + reboot_seconds = new_reboot_seconds; + } + break; case 'E': format_part_out(&inpos, (buf_len-(inpos-buf)), &outpos, (sizeof(out)-(outpos-out)), 3, FLAG_FORMAT_HEX); @@ -744,7 +764,7 @@ void hmlan_syntax(char *prog) fprintf(stderr, "\t-l ip\t\tlisten on given IP address only (for example 127.0.0.1)\n"); fprintf(stderr, "\t-P\t\tcreate PID file " PID_FILE " in daemon mode\n"); fprintf(stderr, "\t-p n\t\tlisten on port n (default: 1000)\n"); - fprintf(stderr, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u)\n", DEFAULT_REBOOT_SECONDS); + fprintf(stderr, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u if FW < 0.967, 0 otherwise)\n", DEFAULT_REBOOT_SECONDS); fprintf(stderr, "\t hh:mm\treboot HM-CFG-USB daily at hh:mm\n"); fprintf(stderr, "\t-v\t\tverbose mode\n"); fprintf(stderr, "\t-V\t\tshow version (" VERSION ")\n"); @@ -760,8 +780,6 @@ int main(int argc, char **argv) char *ep; int opt; - reboot_seconds = DEFAULT_REBOOT_SECONDS; - while((opt = getopt(argc, argv, "DdhiPp:Rr:l:vV")) != -1) { switch (opt) { case 'D': @@ -805,6 +823,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } + reboot_set = 1; break; case 'l': iface = optarg; diff --git a/version.h b/version.h index cccf8c8..0680b90 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "0.096-git" +#define VERSION "0.097-git" -- 2.39.2 From 18e63b25f26a448e310adfca9fea89e4212a2cf4 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Thu, 29 May 2014 18:19:42 +0200 Subject: [PATCH 09/16] add possibility to log network communication --- hmland.c | 108 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/hmland.c b/hmland.c index 6dc2cac..6b89ece 100644 --- a/hmland.c +++ b/hmland.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ extern char *optarg; static int impersonate_hmlanif = 0; static int debug = 0; static int verbose = 0; +static FILE *logfile = NULL; static int reboot_seconds = 0; static int reboot_at_hour = -1; static int reboot_at_minute = -1; @@ -89,6 +91,48 @@ static void print_timestamp(FILE *f) fprintf(f, "%s.%06ld: ", ts, tv.tv_usec); } +static void write_log(char *buf, int len, char *fmt, ...) +{ + va_list ap; + int i; + + if ((!logfile) && (!verbose)) + return; + + if (logfile) + print_timestamp(logfile); + if (verbose) + print_timestamp(stdout); + + if (fmt) { + if (logfile) { + va_start(ap, fmt); + vfprintf(logfile, fmt, ap); + va_end(ap); + } + if (verbose) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } + } + + if (buf && len) { + for (i = 0; i < len; i++) { + if (logfile) + fprintf(logfile, "%c", buf[i]); + if (verbose) + printf("%c", buf[i]); + } + if (logfile) + fprintf(logfile, "\n"); + if (verbose) + printf("\n"); + } + if (logfile) + fflush(logfile); +} + static int format_part_out(uint8_t **inpos, int inlen, uint8_t **outpos, int outlen, int len, int flags) { const uint8_t nibble[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', @@ -319,15 +363,7 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) return 1; } - if (verbose) { - int i; - - print_timestamp(stdout); - printf("LAN < "); - for (i = 0; i < outpos-out-2; i++) - printf("%c", out[i]); - printf("\n"); - } + write_log((char*)out, outpos-out-2, "LAN < "); w = write(fd, out, outpos-out); if (w <= 0) { @@ -341,15 +377,7 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) struct queued_rx *last_rx; while (curr_rx) { - if (verbose) { - int i; - - print_timestamp(stdout); - printf("LAN < "); - for (i = 0; i < curr_rx->len-2; i++) - printf("%c", curr_rx->rx[i]); - printf("\n"); - } + write_log(curr_rx->rx, curr_rx->len-2, "LAN < "); w = write(fd, curr_rx->rx, curr_rx->len); if (w <= 0) { @@ -411,13 +439,7 @@ static int hmlan_parse_in(int fd, void *data) if (last == 0) continue; - if (verbose) { - print_timestamp(stdout); - printf("LAN > "); - for (i = 0; i < last; i++) - printf("%c", instart[i]); - printf("\n"); - } + write_log((char*)instart, last, "LAN > "); memset(out, 0, sizeof(out)); *outpos++ = *inpos++; @@ -717,28 +739,22 @@ static int socket_server(char *iface, int port, int flags) /* FIXME: getnameinfo... */ client_addr = ntohl(csin.sin_addr.s_addr); - if (verbose) { - print_timestamp(stdout); - printf("Client %d.%d.%d.%d connected!\n", - (client_addr & 0xff000000) >> 24, - (client_addr & 0x00ff0000) >> 16, - (client_addr & 0x0000ff00) >> 8, - (client_addr & 0x000000ff)); - } + write_log(NULL, 0, "Client %d.%d.%d.%d connected!\n", + (client_addr & 0xff000000) >> 24, + (client_addr & 0x00ff0000) >> 16, + (client_addr & 0x0000ff00) >> 8, + (client_addr & 0x000000ff)); comm(client, client, sock, flags); shutdown(client, SHUT_RDWR); close(client); - if (verbose) { - print_timestamp(stdout); - printf("Connection to %d.%d.%d.%d closed!\n", - (client_addr & 0xff000000) >> 24, - (client_addr & 0x00ff0000) >> 16, - (client_addr & 0x0000ff00) >> 8, - (client_addr & 0x000000ff)); - } + write_log(NULL, 0, "Connection to %d.%d.%d.%d closed!\n", + (client_addr & 0xff000000) >> 24, + (client_addr & 0x00ff0000) >> 16, + (client_addr & 0x0000ff00) >> 8, + (client_addr & 0x000000ff)); sleep(1); } @@ -762,6 +778,7 @@ void hmlan_syntax(char *prog) fprintf(stderr, "\t-h\t\tthis help\n"); fprintf(stderr, "\t-i\t\tinteractive mode (connect HM-CFG-USB to terminal)\n"); fprintf(stderr, "\t-l ip\t\tlisten on given IP address only (for example 127.0.0.1)\n"); + fprintf(stderr, "\t-L logfile\tlog network-communication to logfile\n"); fprintf(stderr, "\t-P\t\tcreate PID file " PID_FILE " in daemon mode\n"); fprintf(stderr, "\t-p n\t\tlisten on port n (default: 1000)\n"); fprintf(stderr, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u if FW < 0.967, 0 otherwise)\n", DEFAULT_REBOOT_SECONDS); @@ -780,7 +797,7 @@ int main(int argc, char **argv) char *ep; int opt; - while((opt = getopt(argc, argv, "DdhiPp:Rr:l:vV")) != -1) { + while((opt = getopt(argc, argv, "DdhiPp:Rr:l:L:vV")) != -1) { switch (opt) { case 'D': debug = 1; @@ -828,6 +845,13 @@ int main(int argc, char **argv) case 'l': iface = optarg; break; + case 'L': + logfile = fopen(optarg, "a"); + if (!logfile) { + perror("fopen(logfile)"); + exit(EXIT_FAILURE); + } + break; case 'v': verbose = 1; break; -- 2.39.2 From 325ed7030d39536af863e9c49b5fa04ac0a28d5d Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 1 Feb 2015 00:57:30 +0100 Subject: [PATCH 10/16] avoid possible null-pointer dereference in error-path --- hmcfgusb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hmcfgusb.c b/hmcfgusb.c index 0e11866..83c9719 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -285,8 +285,11 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer) if (err != 0) { fprintf(stderr, "Can't re-submit transfer: %s\n", usb_strerror(err)); libusb_free_transfer(transfer); - cb_data->dev->transfer = NULL; - free(cb_data); + if (cb_data) { + if (cb_data->dev) + cb_data->dev->transfer = NULL; + free(cb_data); + } } } -- 2.39.2 From fcb129773e3b12a6393ae12f34a059cb9ff2dba4 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 24 May 2015 21:29:47 +0200 Subject: [PATCH 11/16] hmland: increase receive-buffer for lan-messages --- hmland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmland.c b/hmland.c index 6b89ece..04bb752 100644 --- a/hmland.c +++ b/hmland.c @@ -401,7 +401,7 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) static int hmlan_parse_in(int fd, void *data) { struct hmcfgusb_dev *dev = data; - uint8_t buf[1025]; + uint8_t buf[131073]; uint8_t out[0x40]; //FIXME!!! uint8_t *outpos; uint8_t *inpos; -- 2.39.2 From ad206f3949d76660d334a9e27d75bc239273d452 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 24 May 2015 21:30:26 +0200 Subject: [PATCH 12/16] bump version --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index 0680b90..0050bc2 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "0.097-git" +#define VERSION "0.098-git" -- 2.39.2 From b229c8789d8ad902ebc32da0e6f0ec95871b45e8 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 25 May 2015 16:17:17 +0200 Subject: [PATCH 13/16] hmland: handle commands spanning packet-boundaries Previously each command which crossed packet boundaries (because there were many commands in a packet) was wrongly executed as 2 seperate commands. This is now fixed by reading from the network until a \r or \n is seen and only then executing the command. Fixes crashes of the hmcfgusb when fhem reconnects and sends a huge list of known devices ('+'-packets). --- hmland.c | 136 +++++++++++++++++++++++++++++++++--------------------- version.h | 2 +- 2 files changed, 85 insertions(+), 53 deletions(-) diff --git a/hmland.c b/hmland.c index 04bb752..fb6f630 100644 --- a/hmland.c +++ b/hmland.c @@ -1,6 +1,6 @@ /* HM-CFG-LAN emulation for HM-CFG-USB * - * Copyright (c) 2013 Michael Gernoth + * Copyright (c) 2013-15 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 @@ -47,6 +47,10 @@ #define PID_FILE "/var/run/hmland.pid" #define DEFAULT_REBOOT_SECONDS 86400 +#define LAN_READ_CHUNK_SIZE 2048 +/* Don't allow remote clients to consume all of our memory */ +#define LAN_MAX_LINE_LENGTH 4096 +#define LAN_MAX_BUF_LENGTH 1048576 extern char *optarg; @@ -58,6 +62,8 @@ static int reboot_seconds = 0; static int reboot_at_hour = -1; static int reboot_at_minute = -1; static int reboot_set = 0; +static uint8_t *lan_read_buf = NULL; +static int lan_read_buflen = 0; struct queued_rx { char *rx; @@ -398,72 +404,93 @@ static int hmlan_format_out(uint8_t *buf, int buf_len, void *data) return 1; } -static int hmlan_parse_in(int fd, void *data) +static int hmlan_parse_one(uint8_t *cmd, int last, void *data) { struct hmcfgusb_dev *dev = data; - uint8_t buf[131073]; uint8_t out[0x40]; //FIXME!!! uint8_t *outpos; - uint8_t *inpos; - int i; - int last; - int r; + uint8_t *inpos = cmd; + + outpos = out; - memset(buf, 0, sizeof(buf)); + if (last == 0) + return 1; - r = read(fd, buf, sizeof(buf)-1); - if (r > 0) { - uint8_t *inend = buf + r; + write_log((char*)cmd, last, "LAN > "); - inpos = buf; + memset(out, 0, sizeof(out)); + *outpos++ = *inpos++; + + switch(*cmd) { + case 'S': + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE); + break; + case 'Y': + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), 0); + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE); + break; + default: + parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_IGNORE_COMMAS); + break; + } - while (inpos < inend) { - uint8_t *instart = inpos; + hmcfgusb_send(dev, out, sizeof(out), 1); - if ((*inpos == '\r') || (*inpos == '\n')) { - inpos++; - continue; - } - - outpos = out; + return 1; +} - last = inend - inpos; +static int hmlan_parse_in(int fd, void *data) +{ + uint8_t *newbuf; + int r; + int i; - for (i = 0; i < last; i++) { - if ((inpos[i] == '\r') || (inpos[i] == '\n')) { - last = i; + newbuf = realloc(lan_read_buf, lan_read_buflen + LAN_READ_CHUNK_SIZE); + if (!newbuf) { + perror("realloc"); + return 0; + } + lan_read_buf = newbuf; + r = read(fd, lan_read_buf + lan_read_buflen, LAN_READ_CHUNK_SIZE); + if (r > 0) { + lan_read_buflen += r; + if (lan_read_buflen > LAN_MAX_BUF_LENGTH) { + if (verbose) + printf("Our buffer is bigger than %d bytes (%d bytes), closing connection!\n", LAN_MAX_BUF_LENGTH, lan_read_buflen); + return -1; + } + while(lan_read_buflen > 0) { + int found = 0; + + for (i = 0; i < lan_read_buflen; i++) { + if ((lan_read_buf[i] == '\r') || (lan_read_buf[i] == '\n')) { + if (i > 0) + hmlan_parse_one(lan_read_buf, i, data); + memmove(lan_read_buf, lan_read_buf + i + 1, lan_read_buflen - (i + 1)); + lan_read_buflen -= (i + 1); + found = 1; break; } + if (i > LAN_MAX_LINE_LENGTH) { + if (verbose) + printf("Client sent more than %d bytes without newline, closing connection!\n", LAN_MAX_LINE_LENGTH); + return -1; + } } - - if (last == 0) - continue; - - write_log((char*)instart, last, "LAN > "); - - memset(out, 0, sizeof(out)); - *outpos++ = *inpos++; - - switch(*instart) { - case 'S': - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE); - break; - case 'Y': - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), 0); - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_LENGTH_BYTE); - break; - default: - parse_part_in(&inpos, (last-(inpos-instart)), &outpos, (sizeof(out)-(outpos-out)), FLAG_IGNORE_COMMAS); - break; + if (!found) + break; + newbuf = realloc(lan_read_buf, lan_read_buflen); + if (lan_read_buflen && !newbuf) { + perror("realloc"); + return 0; } - - hmcfgusb_send(dev, out, sizeof(out), 1); + lan_read_buf = newbuf; } } else if (r < 0) { if (errno != ECONNRESET) @@ -750,6 +777,11 @@ static int socket_server(char *iface, int port, int flags) shutdown(client, SHUT_RDWR); close(client); + if (lan_read_buf) + free(lan_read_buf); + lan_read_buf = NULL; + lan_read_buflen = 0; + write_log(NULL, 0, "Connection to %d.%d.%d.%d closed!\n", (client_addr & 0xff000000) >> 24, (client_addr & 0x00ff0000) >> 16, diff --git a/version.h b/version.h index 0050bc2..492b119 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define VERSION "0.098-git" +#define VERSION "0.099-git" -- 2.39.2 From a3182fa5d08df74707260035704abdbb6ca919e2 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 25 May 2015 17:29:09 +0200 Subject: [PATCH 14/16] README: add README.md --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5ba7ad --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +This repository contains utilities to use the [HM-CFG-USB(2)](http://www.elv.de/homematic-usb-konfigurations-adapter-1.html) (HomeMatic USB Konfigurations-Adapter) from [ELV](http://www.elv.de/) on Linux/Unix by using [libusb 1.0](http://www.libusb.org/). + +The HM-CFG-USB can be used to send and receive [BidCoS-Packets](https://sathya.de/HMCWiki/index.php/BidCoS_Packets) to control [HomeMatic](http://www.homematic.com/) home automation devices (like remote controllable sockets, switches, sensors, ...). + +This repository contains, amongst others, an application, which emulates the HomeMatic LAN configuration adapter-protocol to make it possible to use the HM-CFG-USB in [Fhem](http://fhem.de/) or as a lan configuration tool for the CCU or the HomeMatic windows configuration software, also supporting devices using AES-signing like [KeyMatic](http://www.elv.de/homematic-funk-tuerschlossantrieb-keymatic-silber-inkl-funk-handsender.html). + +### Short hmland HowTo: ### + +1. Install prerequisites: `apt-get install libusb-1.0-0-dev build-essential git` +2. Get the current version of this software (choose **one** option): + * Get the current version via git (can be easily updated with `git pull`): + 1. `git clone git://git.zerfleddert.de/hmcfgusb` + 2. Change into the new directory: `cd hmcfgusb` + * Get the current version as an archive: + 1. [hmcfgusb-HEAD-xxxxxxx.tar.gz](https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/snapshot/HEAD.tar.gz) (xxxxxxx is part of the commit-id. xxxxxxx is just a placeholder for this HowTo, use your value) + 2. Extract the archive: `tar xzf hmcfgusb-HEAD-xxxxxxx.tar.gz` + 3. Change into the new directory: `cd hmcfgusb-HEAD-xxxxxxx` +3. Build the code: `make` +4. Optional: Install udev-rules so normal users can access the device: `sudo cp hmcfgusb.rules /etc/udev/rules.d/` +5. Plug in the HM-CFG-USB +6. Run hmland (with debugging the first time, see `-h` switch): `./hmland -p 1234 -D` +7. Configure Fhem to use your new HMLAN device: + ``define hmusb HMLAN 127.0.0.1:1234`` + ``attr hmusb hmId `` + +### Updating the HM-CFG-USB firmware to version 0.967: ### + +1. Compile the hmcfgusb utilities like in the hmland HowTo above (steps 1 to 5) and stay in the directory +2. Download the new firmware: [hmusbif.03c7.enc](https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc): `wget https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc` +3. Make sure that hmland is not running +4. Flash the update to the USB-stick: `./flash-hmcfgusb hmusbif.03c7.enc` (You might need to use `sudo` for this) + +### Updating HomemMatic devices over the air (OTA): ### + +1. Compile the hmcfgusb utilities like in the hmland HowTo above (steps 1 to 5) and stay in the directory +2. Download the new firmware from [eQ-3](http://www.eq-3.de/downloads.html), in this example the HM-CC-RT-DN firmware version 1.4 +3. Extract the tgz-file: `tar xvzf hm_cc_rt_dn_update_V1_4_001_141020.tgz` +4. Make sure that hmland is not running +* When using the **HM-CFG-USB**, flash the new firmware to the device with serial KEQ0123456: + `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456` +* When using a **culfw**-based device (**CUL/COC/...**), flash the new firmware to the device with serial KEQ0123456: + `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456 -c /dev/ttyACM0` -- 2.39.2 From c3850e2d9b66999d4105c46ca68065bfb5e9b7ea Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 25 May 2015 17:37:05 +0200 Subject: [PATCH 15/16] README: fix link to BidCoS packet documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5ba7ad..26acc33 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ This repository contains utilities to use the [HM-CFG-USB(2)](http://www.elv.de/homematic-usb-konfigurations-adapter-1.html) (HomeMatic USB Konfigurations-Adapter) from [ELV](http://www.elv.de/) on Linux/Unix by using [libusb 1.0](http://www.libusb.org/). -The HM-CFG-USB can be used to send and receive [BidCoS-Packets](https://sathya.de/HMCWiki/index.php/BidCoS_Packets) to control [HomeMatic](http://www.homematic.com/) home automation devices (like remote controllable sockets, switches, sensors, ...). +The HM-CFG-USB can be used to send and receive [BidCoS-Packets](http://homegear.eu/index.php/BidCoS%C2%AE_Packets) to control [HomeMatic](http://www.homematic.com/) home automation devices (like remote controllable sockets, switches, sensors, ...). This repository contains, amongst others, an application, which emulates the HomeMatic LAN configuration adapter-protocol to make it possible to use the HM-CFG-USB in [Fhem](http://fhem.de/) or as a lan configuration tool for the CCU or the HomeMatic windows configuration software, also supporting devices using AES-signing like [KeyMatic](http://www.elv.de/homematic-funk-tuerschlossantrieb-keymatic-silber-inkl-funk-handsender.html). -- 2.39.2 From 54b55f0f87eb956f32f5de3e62ec961e97777a12 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 25 May 2015 17:58:38 +0200 Subject: [PATCH 16/16] README: formatting --- README.md | 60 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 26acc33..fd6cc03 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,74 @@ -This repository contains utilities to use the [HM-CFG-USB(2)](http://www.elv.de/homematic-usb-konfigurations-adapter-1.html) (HomeMatic USB Konfigurations-Adapter) from [ELV](http://www.elv.de/) on Linux/Unix by using [libusb 1.0](http://www.libusb.org/). +This repository contains utilities to use the [HM-CFG-USB(2)][] (HomeMatic USB +Konfigurations-Adapter) from [ELV][] on Linux/Unix by using [libusb 1.0][]. -The HM-CFG-USB can be used to send and receive [BidCoS-Packets](http://homegear.eu/index.php/BidCoS%C2%AE_Packets) to control [HomeMatic](http://www.homematic.com/) home automation devices (like remote controllable sockets, switches, sensors, ...). +The HM-CFG-USB can be used to send and receive [BidCoS-Packets][] to control +[HomeMatic][] home automation devices (like remote controllable sockets, +switches, sensors, ...). -This repository contains, amongst others, an application, which emulates the HomeMatic LAN configuration adapter-protocol to make it possible to use the HM-CFG-USB in [Fhem](http://fhem.de/) or as a lan configuration tool for the CCU or the HomeMatic windows configuration software, also supporting devices using AES-signing like [KeyMatic](http://www.elv.de/homematic-funk-tuerschlossantrieb-keymatic-silber-inkl-funk-handsender.html). +This repository contains, amongst others, an application, which emulates the +HomeMatic LAN configuration adapter-protocol to make it possible to use the +HM-CFG-USB in [Fhem][] or as a lan configuration tool for the CCU or the +HomeMatic windows configuration software, also supporting devices using +AES-signing like [KeyMatic][]. + +[HM-CFG-USB(2)]: http://www.elv.de/homematic-usb-konfigurations-adapter-1.html +[ELV]: http://www.elv.de/ +[libusb 1.0]: http://www.libusb.org/ +[BidCoS-Packets]: http://homegear.eu/index.php/BidCoS%C2%AE_Packets +[HomeMatic]: http://www.homematic.com/ +[Fhem]: http://fhem.de/ +[KeyMatic]: http://www.elv.de/homematic-funk-tuerschlossantrieb-keymatic-silber-inkl-funk-handsender.html ### Short hmland HowTo: ### -1. Install prerequisites: `apt-get install libusb-1.0-0-dev build-essential git` +1. Install prerequisites: + `apt-get install libusb-1.0-0-dev build-essential git` 2. Get the current version of this software (choose **one** option): * Get the current version via git (can be easily updated with `git pull`): 1. `git clone git://git.zerfleddert.de/hmcfgusb` 2. Change into the new directory: `cd hmcfgusb` * Get the current version as an archive: - 1. [hmcfgusb-HEAD-xxxxxxx.tar.gz](https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/snapshot/HEAD.tar.gz) (xxxxxxx is part of the commit-id. xxxxxxx is just a placeholder for this HowTo, use your value) + 1. [hmcfgusb-HEAD-xxxxxxx.tar.gz][] (xxxxxxx is part of the commit-id. + xxxxxxx is just a placeholder for this HowTo, use your value) 2. Extract the archive: `tar xzf hmcfgusb-HEAD-xxxxxxx.tar.gz` 3. Change into the new directory: `cd hmcfgusb-HEAD-xxxxxxx` 3. Build the code: `make` -4. Optional: Install udev-rules so normal users can access the device: `sudo cp hmcfgusb.rules /etc/udev/rules.d/` +4. Optional: Install udev-rules so normal users can access the device: + `sudo cp hmcfgusb.rules /etc/udev/rules.d/` 5. Plug in the HM-CFG-USB -6. Run hmland (with debugging the first time, see `-h` switch): `./hmland -p 1234 -D` +6. Run hmland (with debugging the first time, see `-h` switch): + `./hmland -p 1234 -D` 7. Configure Fhem to use your new HMLAN device: ``define hmusb HMLAN 127.0.0.1:1234`` ``attr hmusb hmId `` +[hmcfgusb-HEAD-xxxxxxx.tar.gz]: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/hmcfgusb/snapshot/HEAD.tar.gz + ### Updating the HM-CFG-USB firmware to version 0.967: ### -1. Compile the hmcfgusb utilities like in the hmland HowTo above (steps 1 to 5) and stay in the directory -2. Download the new firmware: [hmusbif.03c7.enc](https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc): `wget https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc` +1. Compile the hmcfgusb utilities like in the hmland HowTo above + (steps 1 to 5) and stay in the directory +2. Download the new firmware: [hmusbif.03c7.enc][]: + `wget https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc` 3. Make sure that hmland is not running -4. Flash the update to the USB-stick: `./flash-hmcfgusb hmusbif.03c7.enc` (You might need to use `sudo` for this) +4. Flash the update to the USB-stick: + `./flash-hmcfgusb hmusbif.03c7.enc` (You might need to use `sudo` for this) + +[hmusbif.03c7.enc]: https://git.zerfleddert.de/hmcfgusb/firmware/hmusbif.03c7.enc ### Updating HomemMatic devices over the air (OTA): ### -1. Compile the hmcfgusb utilities like in the hmland HowTo above (steps 1 to 5) and stay in the directory -2. Download the new firmware from [eQ-3](http://www.eq-3.de/downloads.html), in this example the HM-CC-RT-DN firmware version 1.4 +1. Compile the hmcfgusb utilities like in the hmland HowTo above + (steps 1 to 5) and stay in the directory +2. Download the new firmware from [eQ-3][], in this example the HM-CC-RT-DN + firmware version 1.4 3. Extract the tgz-file: `tar xvzf hm_cc_rt_dn_update_V1_4_001_141020.tgz` 4. Make sure that hmland is not running -* When using the **HM-CFG-USB**, flash the new firmware to the device with serial KEQ0123456: +* When using the **HM-CFG-USB**, flash the new firmware to the device with + serial *KEQ0123456*: `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456` -* When using a **culfw**-based device (**CUL/COC/...**), flash the new firmware to the device with serial KEQ0123456: +* When using a **culfw**-based device (**CUL/COC/...**), flash the new + firmware to the device with serial *KEQ0123456*: `./flash-ota -f hm_cc_rt_dn_update_V1_4_001_141020.eq3 -s KEQ0123456 -c /dev/ttyACM0` + +[eQ-3]: http://www.eq-3.de/downloads.html -- 2.39.2