From 867564c59f3e0687e581efe822365d3ef599c76f Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 00:57:50 +0200 Subject: [PATCH 01/16] Add support for printing the transfer status --- hmcfgusb.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hmcfgusb.c b/hmcfgusb.c index bcb85a4..b9b0f23 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -99,6 +99,28 @@ static char * usb_strerror(int e) return unknerr; } +static char * usb_str_transfer_status(int e) +{ + static char unknerr[256]; + + switch (e) { + case LIBUSB_TRANSFER_COMPLETED: + return "Transfer completed"; + case LIBUSB_TRANSFER_ERROR: + return "Transfer error"; + case LIBUSB_TRANSFER_TIMED_OUT: + return "Transfer timed out"; + case LIBUSB_TRANSFER_CANCELLED: + return "Transfer cancelled"; + case LIBUSB_TRANSFER_STALL: + return "No device"; + case LIBUSB_TRANSFER_OVERFLOW: + return "Transfer overflow"; + }; + snprintf(unknerr, sizeof(unknerr), "Unknown transfer status %d / 0x%02x", e, e); + return unknerr; +} + static libusb_device_handle *hmcfgusb_find(int vid, int pid, char *serial) { libusb_device_handle *devh = NULL; libusb_device **list; @@ -279,7 +301,7 @@ static void LIBUSB_CALL hmcfgusb_interrupt(struct libusb_transfer *transfer) if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_TIMED_OUT) { if (transfer->status != LIBUSB_TRANSFER_CANCELLED) - fprintf(stderr, "Interrupt transfer not completed: %s!\n", usb_strerror(transfer->status)); + fprintf(stderr, "Interrupt transfer not completed: %s!\n", usb_str_transfer_status(transfer->status)); quit = EIO; goto out; -- 2.39.2 From b8d1d0c3fc27e563273a0c6d0a10ebe673ea2904 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:33:08 +0200 Subject: [PATCH 02/16] Cleanup: Improve const correctness --- culfw.c | 2 +- culfw.h | 2 +- hexdump.h | 4 ++-- hmcfgusb.c | 4 ++-- hmland.c | 2 +- hmsniff.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/culfw.c b/culfw.c index 34d3eba..99b20cb 100644 --- a/culfw.c +++ b/culfw.c @@ -110,7 +110,7 @@ out: return NULL; } -int culfw_send(struct culfw_dev *dev, char *cmd, int cmdlen) +int culfw_send(struct culfw_dev *dev, const char *cmd, int cmdlen) { int w = 0; int ret; diff --git a/culfw.h b/culfw.h index bbe64f5..9c98eb7 100644 --- a/culfw.h +++ b/culfw.h @@ -32,7 +32,7 @@ struct culfw_dev { }; struct culfw_dev *culfw_init(char *device, uint32_t speed, culfw_cb_fn cb, void *data); -int culfw_send(struct culfw_dev *dev, char *cmd, int cmdlen); +int culfw_send(struct culfw_dev *dev, const 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/hexdump.h b/hexdump.h index d3d4f3b..127bfb0 100644 --- a/hexdump.h +++ b/hexdump.h @@ -21,7 +21,7 @@ * IN THE SOFTWARE. */ -static void asciishow(unsigned char *buf, int len) +static void asciishow(const unsigned char *buf, int len) { int i; @@ -35,7 +35,7 @@ static void asciishow(unsigned char *buf, int len) } } -static void hexdump(unsigned char *buf, int len, char *prefix) +static void hexdump(const unsigned char *buf, int len, const char *prefix) { int i, j; diff --git a/hmcfgusb.c b/hmcfgusb.c index b9b0f23..9473382 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -61,7 +61,7 @@ static int debug = 0; static int libusb_initialized = 0; /* Not in all libusb-1.0 versions, so we have to roll our own :-( */ -static char * usb_strerror(int e) +static const char* usb_strerror(int e) { static char unknerr[256]; @@ -99,7 +99,7 @@ static char * usb_strerror(int e) return unknerr; } -static char * usb_str_transfer_status(int e) +static const char* usb_str_transfer_status(int e) { static char unknerr[256]; diff --git a/hmland.c b/hmland.c index 38e4d6b..380c99a 100644 --- a/hmland.c +++ b/hmland.c @@ -100,7 +100,7 @@ static void print_timestamp(FILE *f) fprintf(f, "%s.%06ld: ", ts, tv.tv_usec); } -static void write_log(char *buf, int len, char *fmt, ...) +static void write_log(const char *buf, int len, const char *fmt, ...) { va_list ap; int i; diff --git a/hmsniff.c b/hmsniff.c index 01afe05..2ffb9e1 100644 --- a/hmsniff.c +++ b/hmsniff.c @@ -42,7 +42,7 @@ static int verbose = 0; /* See HMConfig.pm */ -char *hm_message_types(uint8_t type, uint8_t subtype) +const char *hm_message_types(uint8_t type, uint8_t subtype) { switch(type) { case 0x00: -- 2.39.2 From 5aa2bb3eb67f181638ac7c0243beba7974e2b0b0 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:33:39 +0200 Subject: [PATCH 03/16] Cleanup: Add missing 'void' --- aes.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aes.h b/aes.h index 25721c8..1b08590 100644 --- a/aes.h +++ b/aes.h @@ -114,10 +114,10 @@ int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, th /////////////////// // Test functions /////////////////// -int aes_test(); -int aes_ecb_test(); -int aes_cbc_test(); -int aes_ctr_test(); -int aes_ccm_test(); +int aes_test(void); +int aes_ecb_test(void); +int aes_cbc_test(void); +int aes_ctr_test(void); +int aes_ccm_test(void); #endif // AES_H -- 2.39.2 From 515b169a1b32c42eee2ddadee04ebc361303e0ee Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:56:04 +0200 Subject: [PATCH 04/16] Cleanup: Cast explicitly where integers of different sign are compared --- flash-ota.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flash-ota.c b/flash-ota.c index 3963b4f..94e9372 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -201,7 +201,7 @@ static int parse_culfw(uint8_t *buf, int buf_len, void *data) rpos++; } - if (hmid && (SRC(rdata->message) != hmid)) + if (hmid && (SRC(rdata->message) != (int)hmid)) return 0; rdata->message_type = MESSAGE_TYPE_E; @@ -1094,7 +1094,7 @@ int main(int argc, char **argv) if (serial && !strncmp((char*)&(rdata.message[0x0b]), serial, 10)) { hmid = SRC(rdata.message); break; - } else if (!serial && SRC(rdata.message) == hmid) { + } else if (!serial && SRC(rdata.message) == (int)hmid) { serial = (char*)&(rdata.message[0x0b]); break; } -- 2.39.2 From 915b783358b0f140fe44d0aeb4295a071f4e0054 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:57:56 +0200 Subject: [PATCH 05/16] Add missing case in switch --- hmcfgusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hmcfgusb.c b/hmcfgusb.c index 9473382..90e82f2 100644 --- a/hmcfgusb.c +++ b/hmcfgusb.c @@ -113,6 +113,8 @@ static const char* usb_str_transfer_status(int e) case LIBUSB_TRANSFER_CANCELLED: return "Transfer cancelled"; case LIBUSB_TRANSFER_STALL: + return "For bulk/interrupt endpoints: endpoint stalled. For control endpoints: control request not supported."; + case LIBUSB_TRANSFER_NO_DEVICE: return "No device"; case LIBUSB_TRANSFER_OVERFLOW: return "Transfer overflow"; -- 2.39.2 From ee8d07d894fa10e47b4441a4db473496c701cb0f Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:58:20 +0200 Subject: [PATCH 06/16] Add missing break in switch --- hmland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hmland.c b/hmland.c index 380c99a..210893d 100644 --- a/hmland.c +++ b/hmland.c @@ -431,6 +431,7 @@ static int hmlan_parse_one(uint8_t *cmd, int last, void *data) 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; -- 2.39.2 From 88312881242f20e35ed0e0544749945c9538ed02 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:59:13 +0200 Subject: [PATCH 07/16] Cleanup: Use correct format string --- hmland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmland.c b/hmland.c index 210893d..c1ba714 100644 --- a/hmland.c +++ b/hmland.c @@ -654,7 +654,7 @@ static int socket_server(char *iface, int port, int flags) exit(EXIT_FAILURE); } - if (fscanf(pidfile, "%u", &old_pid) != 1) { + if (fscanf(pidfile, "%d", &old_pid) != 1) { fclose(pidfile); fprintf(stderr, "Can't read old PID from " PID_FILE ", already running?\n"); exit(EXIT_FAILURE); -- 2.39.2 From 4fd904dfbdea0d4bc3dd901a5feb9338ffa4e25d Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 16:59:43 +0200 Subject: [PATCH 08/16] Cleanup: Use size_t for len --- hmland.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hmland.c b/hmland.c index c1ba714..35f8192 100644 --- a/hmland.c +++ b/hmland.c @@ -142,12 +142,12 @@ static void write_log(const char *buf, int len, const char *fmt, ...) fflush(logfile); } -static int format_part_out(uint8_t **inpos, int inlen, uint8_t **outpos, int outlen, int len, int flags) +static int format_part_out(uint8_t **inpos, int inlen, uint8_t **outpos, int outlen, size_t len, int flags) { uint8_t *buf_out = *outpos; uint8_t *outend = *outpos + outlen; uint8_t *inend = *inpos + inlen; - int i; + size_t i; if (flags & FLAG_COMMA_BEFORE) { CHECK_SPACE(1); @@ -202,7 +202,7 @@ static int parse_part_in(uint8_t **inpos, int inlen, uint8_t **outpos, int outle uint8_t *inend = *inpos + inlen; if (flags & FLAG_LENGTH_BYTE) { - int len = 0; + size_t len = 0; uint8_t *ip; ip = *inpos; -- 2.39.2 From fcb2ff43a40299234d4bd454bee38b5b9754d2c0 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 17:00:50 +0200 Subject: [PATCH 09/16] Increase compiler-warning level --- Makefile | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ffe9673..cb9fe48 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,24 @@ ifeq ($(OPENWRT_BUILD),) #Normal system -CFLAGS=-MMD -O2 -Wall -I/opt/local/include -g +CFLAGS=-Wall -Wextra -Wno-unused-parameter -pedantic +CFLAGS+= -Wno-unknown-warning-option +CFLAGS+= -Wformat=2 +CFLAGS+= -Wformat-truncation=2 +CFLAGS+= -Wwrite-strings +CFLAGS+= -Wnull-dereference +CFLAGS+= -Wuninitialized +CFLAGS+= -Wstrict-overflow +CFLAGS+= -Wdate-time +CFLAGS+= -Wundef +CFLAGS+= -Wpacked +CFLAGS+= -Wduplicated-branches +CFLAGS+= -Wduplicated-cond +CFLAGS+= -Wstrict-prototypes +CFLAGS+= -Wbad-function-cast +CFLAGS+= -Wold-style-definition +CFLAGS+= -MMD -O2 -I/opt/local/include -g + LDFLAGS=-L/opt/local/lib LDLIBS=-lusb-1.0 -lrt CC=gcc -- 2.39.2 From 6e621012d68aaa1b28c9c14eeeec6987d093c02f Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 17:02:46 +0200 Subject: [PATCH 10/16] Cleanup: Use := for assignment --- Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index cb9fe48..0bc8272 100644 --- a/Makefile +++ b/Makefile @@ -19,21 +19,21 @@ CFLAGS+= -Wbad-function-cast CFLAGS+= -Wold-style-definition CFLAGS+= -MMD -O2 -I/opt/local/include -g -LDFLAGS=-L/opt/local/lib -LDLIBS=-lusb-1.0 -lrt -CC=gcc +LDFLAGS:=-L/opt/local/lib +LDLIBS:=-lusb-1.0 -lrt +CC:=gcc -HMLAN_OBJS=hmcfgusb.o hmland.o util.o -HMSNIFF_OBJS=hmcfgusb.o hmuartlgw.o hmsniff.o -FLASH_HMCFGUSB_OBJS=hmcfgusb.o firmware.o util.o flash-hmcfgusb.o -FLASH_HMMODUART_OBJS=hmuartlgw.o firmware.o util.o flash-hmmoduart.o -FLASH_OTA_OBJS=hmcfgusb.o culfw.o hmuartlgw.o firmware.o util.o flash-ota.o hm.o aes.o +HMLAN_OBJS:=hmcfgusb.o hmland.o util.o +HMSNIFF_OBJS:=hmcfgusb.o hmuartlgw.o hmsniff.o +FLASH_HMCFGUSB_OBJS:=hmcfgusb.o firmware.o util.o flash-hmcfgusb.o +FLASH_HMMODUART_OBJS:=hmuartlgw.o firmware.o util.o flash-hmmoduart.o +FLASH_OTA_OBJS:=hmcfgusb.o culfw.o hmuartlgw.o firmware.o util.o flash-ota.o hm.o aes.o -OBJS=$(HMLAN_OBJS) $(HMSNIFF_OBJS) $(FLASH_HMCFGUSB_OBJS) $(FLASH_HMMODUART_OBJS) $(FLASH_OTA_OBJS) +OBJS:=$(HMLAN_OBJS) $(HMSNIFF_OBJS) $(FLASH_HMCFGUSB_OBJS) $(FLASH_HMMODUART_OBJS) $(FLASH_OTA_OBJS) all: hmland hmsniff flash-hmcfgusb flash-hmmoduart flash-ota -DEPEND=$(OBJS:.o=.d) +DEPEND:=$(OBJS:.o=.d) -include $(DEPEND) hmland: $(HMLAN_OBJS) -- 2.39.2 From 256adf553a043566b5131e718060b918d2075943 Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 18:03:08 +0200 Subject: [PATCH 11/16] Allow the user to specify the compiler via environment variable --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 0bc8272..bb05507 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,10 @@ CFLAGS+= -MMD -O2 -I/opt/local/include -g LDFLAGS:=-L/opt/local/lib LDLIBS:=-lusb-1.0 -lrt + +ifeq ($(firstword $(origin CC)),default) CC:=gcc +endif HMLAN_OBJS:=hmcfgusb.o hmland.o util.o HMSNIFF_OBJS:=hmcfgusb.o hmuartlgw.o hmsniff.o -- 2.39.2 From f276a46cb9b1387aed1542882f6341c1510c955f Mon Sep 17 00:00:00 2001 From: Florian Franzmann Date: Sat, 5 Sep 2020 18:03:31 +0200 Subject: [PATCH 12/16] Suppress warnings about non-literal format strings --- hmland.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hmland.c b/hmland.c index 35f8192..8651957 100644 --- a/hmland.c +++ b/hmland.c @@ -116,12 +116,18 @@ static void write_log(const char *buf, int len, const char *fmt, ...) if (fmt) { if (logfile) { va_start(ap, fmt); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" vfprintf(logfile, fmt, ap); +#pragma GCC diagnostic pop va_end(ap); } if (verbose) { va_start(ap, fmt); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" vprintf(fmt, ap); +#pragma GCC diagnostic pop va_end(ap); } } -- 2.39.2 From 2f47f304d1ffbed3869066b0cb335b7bf32a9e8d Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sat, 5 Sep 2020 18:57:56 +0200 Subject: [PATCH 13/16] Revert "Increase compiler-warning level" This breaks compilation with older compilers. This reverts commit fcb2ff43a40299234d4bd454bee38b5b9754d2c0. --- Makefile | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index bb05507..d994a7a 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,10 @@ ifeq ($(OPENWRT_BUILD),) #Normal system -CFLAGS=-Wall -Wextra -Wno-unused-parameter -pedantic -CFLAGS+= -Wno-unknown-warning-option -CFLAGS+= -Wformat=2 -CFLAGS+= -Wformat-truncation=2 -CFLAGS+= -Wwrite-strings -CFLAGS+= -Wnull-dereference -CFLAGS+= -Wuninitialized -CFLAGS+= -Wstrict-overflow -CFLAGS+= -Wdate-time -CFLAGS+= -Wundef -CFLAGS+= -Wpacked -CFLAGS+= -Wduplicated-branches -CFLAGS+= -Wduplicated-cond -CFLAGS+= -Wstrict-prototypes -CFLAGS+= -Wbad-function-cast -CFLAGS+= -Wold-style-definition -CFLAGS+= -MMD -O2 -I/opt/local/include -g - -LDFLAGS:=-L/opt/local/lib -LDLIBS:=-lusb-1.0 -lrt +CFLAGS=-MMD -O2 -Wall -I/opt/local/include -g + +LDFLAGS=-L/opt/local/lib +LDLIBS=-lusb-1.0 -lrt ifeq ($(firstword $(origin CC)),default) CC:=gcc -- 2.39.2 From e9b66bd166d33ade31b5b89179fbafa84bcf0541 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 6 Sep 2020 12:23:01 +0200 Subject: [PATCH 14/16] Revert "Add missing break in switch" and add comment that there should not be a break at this point. This reverts commit ee8d07d894fa10e47b4441a4db473496c701cb0f. --- hmland.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmland.c b/hmland.c index 8651957..fd17e85 100644 --- a/hmland.c +++ b/hmland.c @@ -437,7 +437,7 @@ static int hmlan_parse_one(uint8_t *cmd, int last, void *data) 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; + // Fallthrough to default expected, no break here default: parse_part_in(&inpos, (last-(inpos-cmd)), &outpos, (sizeof(out)-(outpos-out)), FLAG_IGNORE_COMMAS); break; -- 2.39.2 From 4bb67041fd977e1d7de7020cdcfe6845bc313f5d Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Mon, 14 Sep 2020 23:29:43 +0200 Subject: [PATCH 15/16] flash-ota: add support for directly flashing AsksinPP .hex-files When flashing AsksinPP .hex-files the Atmel Atmega type needs to be specified (-3 or -6) for correct memory-layout and flash page sizes. --- firmware.c | 230 +++++++++++++++++++++++++++++++++++++++++++++- firmware.h | 10 +- flash-hmcfgusb.c | 4 +- flash-hmmoduart.c | 4 +- flash-ota.c | 18 +++- 5 files changed, 253 insertions(+), 13 deletions(-) diff --git a/firmware.c b/firmware.c index 6a544a3..36ef435 100644 --- a/firmware.c +++ b/firmware.c @@ -1,6 +1,6 @@ /* generic firmware-functions for HomeMatic * - * Copyright (c) 2014-16 Michael Gernoth + * Copyright (c) 2014-20 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 @@ -32,18 +32,223 @@ #include #include #include +#include #include "util.h" #include "firmware.h" +#define CRC16_INIT 0xFFFF +#define CRC16_POLY 0x1021 + /* This might be wrong, but it works for current fw */ #define MAX_BLOCK_LENGTH 2048 -struct firmware* firmware_read_firmware(char *filename, int debug) +#define HEX_BLOCK_LENGTH_328P 128 +#define HEX_BLOCK_LENGTH_644P 256 +#define HEX_IMAGE_SIZE_328P 0x7000 +#define HEX_IMAGE_SIZE_644P 0xF000 +#define HEX_IMAGE_SIZE_MAX 0xFFFF + +static uint16_t crc16(uint8_t* buf, int length, uint16_t crc) +{ + int i; + uint16_t flag; + + while (length--) { + for (i = 0; i < 8; i++) { + flag = crc & 0x8000; + crc <<= 1; + if (*buf & 0x80) { + crc |= 1; + } + if (flag) { + crc ^= CRC16_POLY; + } + *buf <<= 1; + } + buf++; + } + + return crc; +} + +static struct firmware* firmware_read_ihex(int fd, struct firmware *fw, int atmega, int debug) +{ + uint8_t buf[2*MAX_BLOCK_LENGTH]; + uint8_t image[HEX_IMAGE_SIZE_MAX]; + uint16_t len = 0; + uint16_t addr = 0; + uint16_t type = 0; + uint32_t offset = 0; + uint32_t image_size = HEX_IMAGE_SIZE_328P; + uint32_t block_length = HEX_BLOCK_LENGTH_328P; + int r; + int i; + + switch (atmega) { + case ATMEGA_644P: + printf("Using Atmega644P values for direct hex flashing\n"); + image_size = HEX_IMAGE_SIZE_644P; + block_length = HEX_BLOCK_LENGTH_644P; + break; + case ATMEGA_328P: + printf("Using Atmega328P values for direct hex flashing\n"); + image_size = HEX_IMAGE_SIZE_328P; + block_length = HEX_BLOCK_LENGTH_328P; + break; + default: + fprintf(stderr, "Atmega-type (328P/644P) not specified for flashing hex files\n"); + exit(EXIT_FAILURE); + break; + } + + memset(image, 0xff, sizeof(image)); + + while (1) { + memset(buf, 0, sizeof(buf)); + len = 2 /* len */ + 4 /* len */ + 2 /* type */; + r = read(fd, buf, len); + if (r < 0) { + perror("read"); + exit(EXIT_FAILURE); + } else if (r == 0) { + fprintf(stderr, "EOF without EOF record, Firmware file not valid!\n"); + exit(EXIT_FAILURE); + } else if (r != len) { + printf("can't get record information!\n"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < r; i++) { + if (!validate_nibble(buf[i])) { + fprintf(stderr, "Firmware file not valid!\n"); + exit(EXIT_FAILURE); + } + } + + len = (ascii_to_nibble(buf[0]) & 0xf)<< 4; + len |= ascii_to_nibble(buf[1]) & 0xf; + + addr = (ascii_to_nibble(buf[2]) & 0xf)<< 4; + addr |= ascii_to_nibble(buf[3]) & 0xf; + addr <<= 8; + addr |= (ascii_to_nibble(buf[4]) & 0xf)<< 4; + addr |= ascii_to_nibble(buf[5]) & 0xf; + + type = (ascii_to_nibble(buf[6]) & 0xf)<< 4; + type |= ascii_to_nibble(buf[7]) & 0xf; + + if (debug) + printf("Length: %d, Address: 0x%04x, Type: 0x%02x\n", len, addr, type); + + if (len > MAX_BLOCK_LENGTH) { + fprintf(stderr, "Invalid block-length %u > %u for block %d!\n", len, MAX_BLOCK_LENGTH, fw->fw_blocks+1); + exit(EXIT_FAILURE); + } + + if (type == 0x00) { + r = read(fd, buf, (len * 2) + 2 /* crc */); + if (r < 0) { + perror("read"); + exit(EXIT_FAILURE); + } else if (r == 0) { + break; + } else if (r < ((len * 2) + 2)) { + fprintf(stderr, "short read, aborting (%d < %d)\n", r, (len * 2) + 2); + exit(EXIT_FAILURE); + } + + for (i = 0; i < len * 2; i+=2) { + if ((!validate_nibble(buf[i])) || + (!validate_nibble(buf[i+1]))) { + fprintf(stderr, "Firmware file not valid!\n"); + exit(EXIT_FAILURE); + } + + image[addr + (i/2)] = (ascii_to_nibble(buf[i]) & 0xf)<< 4; + image[addr + (i/2)] |= ascii_to_nibble(buf[i+1]) & 0xf; + } + + while (1) { + r = read(fd, buf, 1); + if (r < 0) { + perror("read"); + exit(EXIT_FAILURE); + } else if (r == 0) { + break; + } else { + if (buf[0] == ':') { + break; + } + } + } + } else if (type == 0x01) { + break; + } else { + fprintf(stderr, "Can't handle iHex type 0x%02x\n", type); + exit(EXIT_FAILURE); + } + } + + image[image_size-2] = 0x00; + image[image_size-1] = 0x00; + + while (offset < image_size) { + fw->fw = realloc(fw->fw, sizeof(uint8_t*) * (fw->fw_blocks + 1)); + if (fw->fw == NULL) { + perror("Can't reallocate fw->fw-blocklist"); + exit(EXIT_FAILURE); + } + + len = block_length; + + fw->fw[fw->fw_blocks] = malloc(len + 4); + if (fw->fw[fw->fw_blocks] == NULL) { + perror("Can't allocate memory for fw->fw-block"); + exit(EXIT_FAILURE); + } + + fw->fw[fw->fw_blocks][0] = (fw->fw_blocks >> 8) & 0xff; + fw->fw[fw->fw_blocks][1] = fw->fw_blocks & 0xff; + fw->fw[fw->fw_blocks][2] = (len >> 8) & 0xff; + fw->fw[fw->fw_blocks][3] = len & 0xff; + + memcpy(fw->fw[fw->fw_blocks] + 4, image + offset, len); + + if ((len + offset) == image_size) { + uint16_t crc; + + crc = crc16(image, image_size, CRC16_INIT); + + if (debug) + printf("CRC: %04x\n", crc); + + fw->fw[fw->fw_blocks][len+3] = (crc >> 8) & 0xff; + fw->fw[fw->fw_blocks][len+2] = crc & 0xff; + } + + fw->fw_blocks++; + if (debug) + printf("Firmware block %d with length %u read.\n", fw->fw_blocks, len); + + offset += len; + } + + if (fw->fw_blocks == 0) { + fprintf(stderr, "Firmware file not valid!\n"); + exit(EXIT_FAILURE); + } + + printf("Firmware with %d blocks successfully read.\n", fw->fw_blocks); + + return fw; +} + +struct firmware* firmware_read_firmware(char *filename, int atmega, int debug) { struct firmware *fw; struct stat stat_buf; - uint8_t buf[4096]; + uint8_t buf[2*MAX_BLOCK_LENGTH]; uint16_t len; int fd; int r; @@ -69,6 +274,25 @@ struct firmware* firmware_read_firmware(char *filename, int debug) } printf("Reading firmware from %s...\n", filename); + + memset(buf, 0, sizeof(buf)); + r = read(fd, buf, 1); + if (r != 1) { + perror("read"); + exit(EXIT_FAILURE); + } + + //Intel hex? + if (buf[0] == ':') { + printf("HEX file detected (AsksinPP)\n"); + return firmware_read_ihex(fd, fw, atmega, debug); + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + perror("lseek"); + exit(EXIT_FAILURE); + } + do { memset(buf, 0, sizeof(buf)); r = read(fd, buf, 4); diff --git a/firmware.h b/firmware.h index 5905489..4850b1b 100644 --- a/firmware.h +++ b/firmware.h @@ -1,6 +1,6 @@ /* generic firmware-functions for HomeMatic * - * Copyright (c) 2014-16 Michael Gernoth + * Copyright (c) 2014-20 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 @@ -26,5 +26,11 @@ struct firmware { int fw_blocks; }; -struct firmware* firmware_read_firmware(char *filename, int debug); +enum atmega_device { + ATMEGA_UNKNOWN, + ATMEGA_328P, + ATMEGA_644P, +}; + +struct firmware* firmware_read_firmware(char *filename, int atmega, int debug); void firmware_free(struct firmware *fw); diff --git a/flash-hmcfgusb.c b/flash-hmcfgusb.c index 8c858f2..78a7a80 100644 --- a/flash-hmcfgusb.c +++ b/flash-hmcfgusb.c @@ -1,6 +1,6 @@ /* flasher for HM-CFG-USB * - * Copyright (c) 2013-16 Michael Gernoth + * Copyright (c) 2013-20 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 @@ -110,7 +110,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - fw = firmware_read_firmware(filename, debug); + fw = firmware_read_firmware(filename, ATMEGA_UNKNOWN, debug); if (!fw) exit(EXIT_FAILURE); diff --git a/flash-hmmoduart.c b/flash-hmmoduart.c index aa772bb..60f73f5 100644 --- a/flash-hmmoduart.c +++ b/flash-hmmoduart.c @@ -1,6 +1,6 @@ /* flasher for HM-MOD-UART * - * Copyright (c) 2016-17 Michael Gernoth + * Copyright (c) 2016-20 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 @@ -117,7 +117,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - fw = firmware_read_firmware(filename, debug); + fw = firmware_read_firmware(filename, ATMEGA_UNKNOWN, debug); if (!fw) exit(EXIT_FAILURE); diff --git a/flash-ota.c b/flash-ota.c index 94e9372..b7930fc 100644 --- a/flash-ota.c +++ b/flash-ota.c @@ -1,6 +1,6 @@ /* flasher for HomeMatic-devices supporting OTA updates * - * Copyright (c) 2014-17 Michael Gernoth + * Copyright (c) 2014-20 Michael Gernoth * Copyright (c) 2017 noansi (TSCULFW-support) * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -618,7 +618,8 @@ void flash_ota_syntax(char *prog) { fprintf(stderr, "Syntax: %s parameters options\n\n", prog); fprintf(stderr, "Mandatory parameters:\n"); - fprintf(stderr, "\t-f firmware.eq3\tfirmware file to flash\n"); + fprintf(stderr, "\t-f firmware.eq3\teq3 firmware file to flash\n"); + fprintf(stderr, "or\t-f firmware.hex\thex firmware file to flash (AsksinPP), needs -3 or -6\n"); fprintf(stderr, "\t-s SERIAL\tserial of device to flash (optional when using -D)\n"); fprintf(stderr, "\nOptional parameters:\n"); fprintf(stderr, "\t-c device\tenable CUL-mode with CUL at path \"device\"\n"); @@ -626,6 +627,8 @@ void flash_ota_syntax(char *prog) fprintf(stderr, "\t-l\t\tlower payloadlen (required for devices with little RAM, e.g. CUL v2 and CUL v4)\n"); fprintf(stderr, "\t-S serial\tuse HM-CFG-USB with given serial\n"); fprintf(stderr, "\t-U device\tuse HM-MOD-UART on given device\n"); + fprintf(stderr, "\t-3\t\tuse Atmega328P configuration when directly flashing AsksinPP hex\n"); + fprintf(stderr, "\t-6\t\tuse Atmega644P configuration when directly flashing AsksinPP hex\n"); fprintf(stderr, "\t-h\t\tthis help\n"); fprintf(stderr, "\nOptional parameters for automatically sending device to bootloader\n"); fprintf(stderr, "\t-C\t\tHMID of central (3 hex-bytes, no prefix, e.g. ABCDEF)\n"); @@ -651,6 +654,7 @@ int main(int argc, char **argv) struct firmware *fw; char *hmcfgusb_serial = NULL; char *uart = NULL; + int atmega = ATMEGA_UNKNOWN; int block; int pfd; int debug = 0; @@ -662,7 +666,7 @@ int main(int argc, char **argv) printf("HomeMatic OTA flasher version " VERSION "\n\n"); - while((opt = getopt(argc, argv, "b:c:f:hls:C:D:K:S:U:")) != -1) { + while((opt = getopt(argc, argv, "b:c:f:hls:C:D:K:S:U:36")) != -1) { switch (opt) { case 'b': bps = atoi(optarg); @@ -722,6 +726,12 @@ int main(int argc, char **argv) case 'U': uart = optarg; break; + case '3': + atmega = ATMEGA_328P; + break; + case '6': + atmega = ATMEGA_644P; + break; case 'h': case ':': case '?': @@ -738,7 +748,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - fw = firmware_read_firmware(fw_file, debug); + fw = firmware_read_firmware(fw_file, atmega, debug); if (!fw) exit(EXIT_FAILURE); -- 2.39.2 From 715728607ae77bebf3ac50fdbdb46639551995e4 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Tue, 15 Sep 2020 08:54:22 +0200 Subject: [PATCH 16/16] firmware: fix maximum size --- firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware.c b/firmware.c index 36ef435..e1cf34e 100644 --- a/firmware.c +++ b/firmware.c @@ -47,7 +47,7 @@ #define HEX_BLOCK_LENGTH_644P 256 #define HEX_IMAGE_SIZE_328P 0x7000 #define HEX_IMAGE_SIZE_644P 0xF000 -#define HEX_IMAGE_SIZE_MAX 0xFFFF +#define HEX_IMAGE_SIZE_MAX 0x10000 static uint16_t crc16(uint8_t* buf, int length, uint16_t crc) { -- 2.39.2