diff --git a/aqhome/0BUILD b/aqhome/0BUILD index 72785e0..4d2918d 100644 --- a/aqhome/0BUILD +++ b/aqhome/0BUILD @@ -61,6 +61,7 @@ ipc nodes mqtt + hexfile @@ -69,6 +70,7 @@ aqhipc aqhnodes aqhmqtt + aqhhexfile diff --git a/aqhome/hexfile/0BUILD b/aqhome/hexfile/0BUILD new file mode 100644 index 0000000..a127ddd --- /dev/null +++ b/aqhome/hexfile/0BUILD @@ -0,0 +1,85 @@ + + + + + + + + $(gwenhywfar_cflags) + -I$(topsrcdir) + -I$(topbuilddir) + + + + --include=$(builddir) + --include=$(srcdir) + + + + + + $(visibility_cflags) + + + + --api=AQHOME_API + + + + + + + + + + + + + + + + + + $(local/built_headers_pub) + + + + + hexfilerecord.h + hexfilerecord_p.h + hexfile.h + hexfile_p.h + flashrecord.h + flashrecord_p.h + + + + + + + + + $(local/typefiles) + + hexfile.c + hexfilerecord.c + flashrecord.c + + + + + + + + + + + + + + + + + + + diff --git a/aqhome/hexfile/flashrecord.c b/aqhome/hexfile/flashrecord.c new file mode 100644 index 0000000..2d7469e --- /dev/null +++ b/aqhome/hexfile/flashrecord.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + + +#include "./flashrecord_p.h" + +#include +#include + + + +GWEN_LIST_FUNCTIONS(AQH_FLASHRECORD, AQH_FlashRecord) + + +AQH_HEXFILERECORD *_sampleAdjacentHexfileRecords(AQH_FLASHRECORD *fr, AQH_HEXFILERECORD *hrStart); + + + + + +AQH_FLASHRECORD *AQH_FlashRecord_new() +{ + AQH_FLASHRECORD *fr; + + GWEN_NEW_OBJECT(AQH_FLASHRECORD, fr); + GWEN_LIST_INIT(AQH_FLASHRECORD, fr); + return fr; +} + + + +void AQH_FlashRecord_free(AQH_FLASHRECORD *fr) +{ + if (fr) { + GWEN_LIST_FINI(AQH_FLASHRECORD, fr); + if (fr->dataPointer) + free(fr->dataPointer); + fr->dataPointer=NULL; + GWEN_FREE_OBJECT(fr); + } +} + + + +uint32_t AQH_FlashRecord_GetAddress(const AQH_FLASHRECORD *fr) +{ + if (fr) + return fr->address; + return 0; +} + + + +void AQH_FlashRecord_SetAddress(AQH_FLASHRECORD *fr, uint32_t a) +{ + if (fr) + fr->address=a; +} + + + +uint32_t AQH_FlashRecord_GetDataLength(const AQH_FLASHRECORD *fr) +{ + if (fr) + return fr->dataLength; + return 0; +} + + + +uint8_t *AQH_FlashRecord_GetDataPointer(const AQH_FLASHRECORD *fr) +{ + if (fr) + return fr->dataPointer; + return NULL; +} + + + +void AQH_FlashRecord_DirectlySetData(AQH_FLASHRECORD *fr, uint32_t dataLength, uint8_t *dataPtr) +{ + if (fr->dataPointer) + free(fr->dataPointer); + fr->dataPointer=dataPtr; + fr->dataLength=dataLength; +} + + + +void AQH_FlashRecord_CopyAndSetData(AQH_FLASHRECORD *fr, uint32_t dataLength, const uint8_t *dataPtr) +{ + if (fr) { + if (fr->dataPointer) + free(fr->dataPointer); + if (dataLength) { + fr->dataPointer=(uint8_t*) malloc(dataLength); + if (fr->dataPointer) { + if (dataPtr) + memmove(fr->dataPointer, dataPtr, dataLength); + else + memset(fr->dataPointer, 0, dataLength); + } + else { + fr->dataPointer=NULL; + fr->dataLength=0; + } + } + else { + fr->dataPointer=NULL; + fr->dataLength=0; + } + } +} + + + +AQH_FLASHRECORD_LIST *AQH_FlashRecord_fromHexfileRecords(AQH_HEXFILERECORD_LIST *hexFileRecordList) +{ + AQH_FLASHRECORD_LIST *flashRecordList; + AQH_HEXFILERECORD *hr; + uint32_t currentOffset=0; + + flashRecordList=AQH_FlashRecord_List_new(); + hr=AQH_HexfileRecord_List_First(hexFileRecordList); + while(hr) { + uint8_t t; + + t=AQH_HexfileRecord_GetRecordType(hr); + if (t==AQH_HEXFILERECORD_TYPE_DATA) { + AQH_FLASHRECORD *fr; + + fr=AQH_FlashRecord_new(); + AQH_FlashRecord_SetAddress(fr, currentOffset+AQH_HexfileRecord_GetAddress(hr)); + hr=_sampleAdjacentHexfileRecords(fr, hr); + AQH_FlashRecord_List_Add(fr, flashRecordList); + } + else { + if (t==AQH_HEXFILERECORD_TYPE_EXTSEG) { + const uint8_t *ptr; + + if (AQH_HexfileRecord_GetByteCount(hr)<2) { + DBG_ERROR(AQH_LOGDOMAIN, "Invalid EXTSEG record (02) in file (too few data bytes)"); + AQH_FlashRecord_List_free(flashRecordList); + return NULL; + } + ptr=AQH_HexfileRecord_GetDataPointer(hr); + currentOffset=((ptr[0]<<8)+ptr[1])<<4; + } + else if (t==AQH_HEXFILERECORD_TYPE_EOF) { + break; + } + + hr=AQH_HexfileRecord_List_Next(hr); + } + } /* while */ + + if (AQH_FlashRecord_List_GetCount(flashRecordList)<1) { + AQH_FlashRecord_List_free(flashRecordList); + return NULL; + } + return flashRecordList; +} + + + +AQH_HEXFILERECORD *_sampleAdjacentHexfileRecords(AQH_FLASHRECORD *fr, AQH_HEXFILERECORD *hrStart) +{ + AQH_HEXFILERECORD *hrNext; + AQH_HEXFILERECORD *hr; + uint32_t len=0; + + hrNext=AQH_HexfileRecord_List_FindNonAdjacentDataRecord(hrStart); + /* sample number of contiguous bytes */ + hr=hrStart; + while(hr && hr!=hrNext) { + len+=AQH_HexfileRecord_GetByteCount(hr); + hr=AQH_HexfileRecord_List_Next(hr); + } + + if (len) { + uint8_t *ptr; + uint32_t offs=0; + + ptr=(uint8_t*) malloc(len); + hr=hrStart; + while(hr && hr!=hrNext) { + memmove(ptr+offs, AQH_HexfileRecord_GetDataPointer(hr), AQH_HexfileRecord_GetByteCount(hr)); + offs+=AQH_HexfileRecord_GetByteCount(hr); + hr=AQH_HexfileRecord_List_Next(hr); + } + AQH_FlashRecord_DirectlySetData(fr, len, ptr); + } + + return hrNext; +} + + + + + + + + + + diff --git a/aqhome/hexfile/flashrecord.h b/aqhome/hexfile/flashrecord.h new file mode 100644 index 0000000..1d485a4 --- /dev/null +++ b/aqhome/hexfile/flashrecord.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_FLASHRECORD_H +#define AQH_FLASHRECORD_H + + +#include +#include + +#include + + +typedef struct AQH_FLASHRECORD AQH_FLASHRECORD; +GWEN_LIST_FUNCTION_LIB_DEFS(AQH_FLASHRECORD, AQH_FlashRecord, AQHOME_API) + + +AQHOME_API AQH_FLASHRECORD *AQH_FlashRecord_new(); +AQHOME_API AQH_FLASHRECORD_LIST *AQH_FlashRecord_fromHexfileRecords(AQH_HEXFILERECORD_LIST *hexFileRecordList); + +AQHOME_API void AQH_FlashRecord_free(AQH_FLASHRECORD *fr); + +AQHOME_API uint32_t AQH_FlashRecord_GetAddress(const AQH_FLASHRECORD *fr); +AQHOME_API void AQH_FlashRecord_SetAddress(AQH_FLASHRECORD *fr, uint32_t a); + +AQHOME_API uint32_t AQH_FlashRecord_GetDataLength(const AQH_FLASHRECORD *fr); +AQHOME_API uint8_t *AQH_FlashRecord_GetDataPointer(const AQH_FLASHRECORD *fr); +AQHOME_API void AQH_FlashRecord_DirectlySetData(AQH_FLASHRECORD *fr, uint32_t dataLength, uint8_t *dataPtr); +AQHOME_API void AQH_FlashRecord_CopyAndSetData(AQH_FLASHRECORD *fr, uint32_t dataLength, const uint8_t *dataPtr); + + + + + +#endif + + diff --git a/aqhome/hexfile/flashrecord_p.h b/aqhome/hexfile/flashrecord_p.h new file mode 100644 index 0000000..7ac5fb4 --- /dev/null +++ b/aqhome/hexfile/flashrecord_p.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_FLASHRECORD_P_H +#define AQH_FLASHRECORD_P_H + + +#include "./flashrecord.h" + + + +struct AQH_FLASHRECORD +{ + GWEN_LIST_ELEMENT(AQH_FLASHRECORD) + + uint32_t address; + uint32_t dataLength; + uint8_t *dataPointer; +}; + + + +#endif + + diff --git a/aqhome/hexfile/hexfile.c b/aqhome/hexfile/hexfile.c new file mode 100644 index 0000000..20cd902 --- /dev/null +++ b/aqhome/hexfile/hexfile.c @@ -0,0 +1,318 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include "aqhome/hexfile/hexfile_p.h" + +#include +#include + +#include + + + + +static const char *_readRecord(AQH_HEXFILERECORD *hr, const char *s); +static void _writeRecord(AQH_HEXFILERECORD *hr, GWEN_BUFFER *buffer); +static int _sumValuesForChecksum(const AQH_HEXFILERECORD *hr); +static int _readWord(const char *s); +static int _readByte(const char *s); +static int _readNibble(const char *s); + + + + + +AQH_HEXFILE *AQH_Hexfile_new() +{ + AQH_HEXFILE *h; + + GWEN_NEW_OBJECT(AQH_HEXFILE, h); + h->recordList=AQH_HexfileRecord_List_new(); + return h; +} + + + +AQH_HEXFILE *AQH_Hexfile_fromString(const char *s) +{ + AQH_HEXFILE *h; + AQH_HEXFILERECORD_LIST *recordList; + + h=AQH_Hexfile_new(); + recordList=AQH_Hexfile_GetRecordList(h); + while(s && *s) { + AQH_HEXFILERECORD *hr; + uint8_t rt; + + while(s && *s && *s!=':') + s++; + hr=AQH_HexfileRecord_new(); + s=_readRecord(hr, s); + if (s==NULL) { + AQH_HexfileRecord_free(hr); + AQH_Hexfile_free(h); + return NULL; + } + rt=AQH_HexfileRecord_GetRecordType(hr); + DBG_INFO(AQH_LOGDOMAIN, "Adding record %02x", rt); + AQH_HexfileRecord_List_Add(hr, recordList); + if ((rt==AQH_HEXFILERECORD_TYPE_EOF) || + (rt==AQH_HEXFILERECORD_TYPE_DATA && AQH_HexfileRecord_GetByteCount(hr)==0)) { + DBG_INFO(AQH_LOGDOMAIN, "End record found"); + break; + } + } + + return h; +} + + + +AQH_HEXFILE *AQH_Hexfile_fromFile(const char *filename) +{ + GWEN_BUFFER *buffer; + int rv; + AQH_HEXFILE *h; + + buffer=GWEN_Buffer_new(0, 1024, 0, 1); + rv=GWEN_SyncIo_Helper_ReadFile(filename, buffer); + if (rv<0) { + DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); + GWEN_Buffer_free(buffer); + return NULL; + } + + h=AQH_Hexfile_fromString(GWEN_Buffer_GetStart(buffer)); + GWEN_Buffer_free(buffer); + if (h==NULL) { + DBG_INFO(AQH_LOGDOMAIN, "here"); + } + + return h; +} + + + +void AQH_Hexfile_toBuffer(const AQH_HEXFILE *h, GWEN_BUFFER *buffer) +{ + if (h && h->recordList) { + AQH_HEXFILERECORD *hr; + + hr=AQH_HexfileRecord_List_First(h->recordList); + while(hr) { + _writeRecord(hr, buffer); + GWEN_Buffer_AppendString(buffer, "\r\n"); + hr=AQH_HexfileRecord_List_Next(hr); + } + } +} + + + +void AQH_Hexfile_free(AQH_HEXFILE *h) +{ + if (h) { + AQH_HexfileRecord_List_free(h->recordList); + GWEN_FREE_OBJECT(h); + } +} + + + +AQH_HEXFILERECORD_LIST *AQH_Hexfile_GetRecordList(const AQH_HEXFILE *h) +{ + if (h) + return h->recordList; + return NULL; +} + + + + + + +const char *_readRecord(AQH_HEXFILERECORD *hr, const char *s) +{ + int v; + int dataLen; + + /* find ":" */ + s=strchr(s, ':'); + if (s==NULL) + return NULL; + s++; + + v=_readByte(s); + if (v<0) + return NULL; + AQH_HexfileRecord_SetByteCount(hr, (uint8_t) v); + dataLen=v; + s+=2; + + v=_readWord(s); + if (v<0) + return NULL; + AQH_HexfileRecord_SetAddress(hr, (uint16_t) v); + s+=4; + + v=_readByte(s); + if (v<0) + return NULL; + AQH_HexfileRecord_SetRecordType(hr, (uint8_t) v); + s+=2; + + if (dataLen) { + uint8_t *ptr; + int i; + + ptr=(uint8_t*) malloc(dataLen); + if (ptr==NULL) { + return NULL; + } + AQH_HexfileRecord_SetDataPointer(hr, ptr); + + for (i=0; i>8) & 0xff)+(AQH_HexfileRecord_GetAddress(hr) & 0xff)+ + AQH_HexfileRecord_GetRecordType(hr); + if (dataLen) { + const uint8_t *ptr; + int i; + + ptr=AQH_HexfileRecord_GetDataPointer(hr); + for(i=0; i='0' && c<='9') + c-='0'; + else if (c>='A' && c<='F') + c-='A'-10; + else if (c>='a' && c<='f') + c-='a'-10; + else + return -1; + return c; +} + + + diff --git a/aqhome/hexfile/hexfile.h b/aqhome/hexfile/hexfile.h new file mode 100644 index 0000000..216c79f --- /dev/null +++ b/aqhome/hexfile/hexfile.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_HEXFILE_H +#define AQH_HEXFILE_H + + +#include +#include + +#include +#include + + + +typedef struct AQH_HEXFILE AQH_HEXFILE; + + +AQHOME_API AQH_HEXFILE *AQH_Hexfile_new(); +AQHOME_API AQH_HEXFILE *AQH_Hexfile_fromString(const char *s); +AQHOME_API AQH_HEXFILE *AQH_Hexfile_fromFile(const char *filename); + +AQHOME_API void AQH_Hexfile_toBuffer(const AQH_HEXFILE *h, GWEN_BUFFER *buffer); + +AQHOME_API void AQH_Hexfile_free(AQH_HEXFILE *h); + +AQHOME_API AQH_HEXFILERECORD_LIST *AQH_Hexfile_GetRecordList(const AQH_HEXFILE *h); + + + + + + +#endif + + diff --git a/aqhome/hexfile/hexfile_p.h b/aqhome/hexfile/hexfile_p.h new file mode 100644 index 0000000..c2561e9 --- /dev/null +++ b/aqhome/hexfile/hexfile_p.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_HEXFILE_P_H +#define AQH_HEXFILE_P_H + + +#include "aqhome/hexfile/hexfile.h" + + + +struct AQH_HEXFILE { + AQH_HEXFILERECORD_LIST *recordList; +}; + + + + + +#endif + + diff --git a/aqhome/hexfile/hexfilerecord.c b/aqhome/hexfile/hexfilerecord.c new file mode 100644 index 0000000..25c11a1 --- /dev/null +++ b/aqhome/hexfile/hexfilerecord.c @@ -0,0 +1,175 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + + +#include "./hexfilerecord_p.h" + +#include +#include + + + +GWEN_LIST_FUNCTIONS(AQH_HEXFILERECORD, AQH_HexfileRecord) + + + + +AQH_HEXFILERECORD *AQH_HexfileRecord_new() +{ + AQH_HEXFILERECORD *hr; + + GWEN_NEW_OBJECT(AQH_HEXFILERECORD, hr); + GWEN_LIST_INIT(AQH_HEXFILERECORD, hr); + return hr; +} + + + +void AQH_HexfileRecord_free(AQH_HEXFILERECORD *hr) +{ + if (hr) { + GWEN_LIST_FINI(AQH_HEXFILERECORD, hr); + if (hr->dataPointer) + free(hr->dataPointer); + GWEN_FREE_OBJECT(hr); + } +} + + + +uint8_t AQH_HexfileRecord_GetByteCount(const AQH_HEXFILERECORD *hr) +{ + if (hr) + return hr->byteCount; + return 0; +} + + + +void AQH_HexfileRecord_SetByteCount(AQH_HEXFILERECORD *hr, uint8_t b) +{ + if (hr) + hr->byteCount=b; +} + + + +uint16_t AQH_HexfileRecord_GetAddress(const AQH_HEXFILERECORD *hr) +{ + if (hr) + return hr->address; + return 0; +} + + + +void AQH_HexfileRecord_SetAddress(AQH_HEXFILERECORD *hr, uint16_t a) +{ + if (hr) + hr->address=a; +} + + + +uint8_t AQH_HexfileRecord_GetRecordType(const AQH_HEXFILERECORD *hr) +{ + if (hr) + return hr->recordType; + return 0; +} + + + +void AQH_HexfileRecord_SetRecordType(AQH_HEXFILERECORD *hr, uint8_t t) +{ + if (hr) + hr->recordType=t; +} + + + +const uint8_t *AQH_HexfileRecord_GetDataPointer(const AQH_HEXFILERECORD *hr) +{ + if (hr) + return hr->dataPointer; + return NULL; +} + + + +void AQH_HexfileRecord_SetDataPointer(AQH_HEXFILERECORD *hr, uint8_t *ptr) +{ + if (hr) { + if (hr->dataPointer) + free(hr->dataPointer); + hr->dataPointer=ptr; + } +} + + + +void AQH_HexfileRecord_SetData(AQH_HEXFILERECORD *hr, const uint8_t *ptr, uint8_t len) +{ + if (hr) { + if (hr->dataPointer) + free(hr->dataPointer); + if (ptr && len) { + hr->dataPointer=(uint8_t*) malloc(len); + if (hr->dataPointer) { + memmove(hr->dataPointer, ptr, len); + hr->byteCount=len; + } + else { + hr->dataPointer=NULL; + hr->byteCount=0; + } + } + else { + hr->dataPointer=NULL; + hr->byteCount=0; + } + } +} + + + +AQH_HEXFILERECORD *AQH_HexfileRecord_List_FindNonAdjacentDataRecord(AQH_HEXFILERECORD *hr) +{ + uint16_t expectedAddr; + int cnt=0; + + expectedAddr=AQH_HexfileRecord_GetAddress(hr)+AQH_HexfileRecord_GetByteCount(hr); + hr=AQH_HexfileRecord_List_Next(hr); + while(hr && AQH_HexfileRecord_GetRecordType(hr)==AQH_HEXFILERECORD_TYPE_DATA) { + uint16_t addr; + + addr=AQH_HexfileRecord_GetAddress(hr); + if (addr!=expectedAddr) + break; + expectedAddr=addr+AQH_HexfileRecord_GetByteCount(hr); + cnt++; + hr=AQH_HexfileRecord_List_Next(hr); + } + + DBG_INFO(AQH_LOGDOMAIN, "- num of continuous records: %d", cnt); + return hr; +} + + + + + + + + + diff --git a/aqhome/hexfile/hexfilerecord.h b/aqhome/hexfile/hexfilerecord.h new file mode 100644 index 0000000..ba3f8ae --- /dev/null +++ b/aqhome/hexfile/hexfilerecord.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_HEXFILERECORD_H +#define AQH_HEXFILERECORD_H + + +#include + +#include + + +#define AQH_HEXFILERECORD_TYPE_DATA 0x00 +#define AQH_HEXFILERECORD_TYPE_EOF 0x01 +#define AQH_HEXFILERECORD_TYPE_EXTSEG 0x02 +#define AQH_HEXFILERECORD_TYPE_STARTSEGADDR 0x03 +#define AQH_HEXFILERECORD_TYPE_EXTLINEARADDR 0x04 +#define AQH_HEXFILERECORD_TYPE_STARTLINEARADDR 0x05 + + + +typedef struct AQH_HEXFILERECORD AQH_HEXFILERECORD; +GWEN_LIST_FUNCTION_LIB_DEFS(AQH_HEXFILERECORD, AQH_HexfileRecord, AQHOME_API) + + +AQHOME_API AQH_HEXFILERECORD *AQH_HexfileRecord_new(); +AQHOME_API void AQH_HexfileRecord_free(AQH_HEXFILERECORD *hr); + + +AQHOME_API uint8_t AQH_HexfileRecord_GetByteCount(const AQH_HEXFILERECORD *hr); +AQHOME_API void AQH_HexfileRecord_SetByteCount(AQH_HEXFILERECORD *hr, uint8_t b); + +AQHOME_API uint16_t AQH_HexfileRecord_GetAddress(const AQH_HEXFILERECORD *hr); +AQHOME_API void AQH_HexfileRecord_SetAddress(AQH_HEXFILERECORD *hr, uint16_t a); + +AQHOME_API uint8_t AQH_HexfileRecord_GetRecordType(const AQH_HEXFILERECORD *hr); +AQHOME_API void AQH_HexfileRecord_SetRecordType(AQH_HEXFILERECORD *hr, uint8_t t); + +AQHOME_API const uint8_t *AQH_HexfileRecord_GetDataPointer(const AQH_HEXFILERECORD *hr); +AQHOME_API void AQH_HexfileRecord_SetDataPointer(AQH_HEXFILERECORD *hr, uint8_t *ptr); + +AQHOME_API void AQH_HexfileRecord_SetData(AQH_HEXFILERECORD *hr, const uint8_t *ptr, uint8_t len); + + +/** + * Find the first record whose address is non-contiguous with the given record. + * This can be used to reduce the number of data records. + * This function stops at the next record whose address is non-continuous or whose type is not 00. + * + * @return next non-contiguous or non-data record (NULL if none) + * @param hr record to start with (i.e. whose successor are checked for continuity) + */ +AQHOME_API AQH_HEXFILERECORD *AQH_HexfileRecord_List_FindNonAdjacentDataRecord(AQH_HEXFILERECORD *hr); + + + + +#endif + + diff --git a/aqhome/hexfile/hexfilerecord_p.h b/aqhome/hexfile/hexfilerecord_p.h new file mode 100644 index 0000000..7135cef --- /dev/null +++ b/aqhome/hexfile/hexfilerecord_p.h @@ -0,0 +1,31 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_HEXFILERECORD_P_H +#define AQH_HEXFILERECORD_P_H + + +#include "./hexfilerecord.h" + + + +struct AQH_HEXFILERECORD +{ + GWEN_LIST_ELEMENT(AQH_HEXFILERECORD) + + uint8_t byteCount; + uint16_t address; + uint8_t recordType; + uint8_t *dataPointer; +}; + + + +#endif + + diff --git a/aqhome/libtest.c b/aqhome/libtest.c index 32b7d14..0163cb8 100644 --- a/aqhome/libtest.c +++ b/aqhome/libtest.c @@ -19,6 +19,8 @@ #include "aqhome/mqtt/msg_mqtt_publish.h" #include "aqhome/mqtt/msg_mqtt_pubresponse.h" #include "aqhome/msgmanager.h" +#include "aqhome/hexfile/hexfile.h" +#include "aqhome/hexfile/flashrecord.h" #include "aqhome/aqhome.h" @@ -342,6 +344,105 @@ int testIpcConnection() +int testHexfile(int argc, char **argv) +{ + const char *inFilename; + const char *outFilename; + AQH_HEXFILE *h; + int rv; + + if (argc<3) { + fprintf(stderr, "Missing filenames (in, out)\n"); + return 1; + } + + rv=AQH_Init(); + if (rv<0) { + } + + inFilename=argv[1]; + outFilename=argv[2]; + h=AQH_Hexfile_fromFile(inFilename); + if (h==NULL) { + fprintf(stderr, "Error reading hexfile \"%s\".\n", inFilename); + return 2; + } + else { + AQH_HEXFILERECORD_LIST *recordList; + GWEN_BUFFER *buffer; + + recordList=AQH_Hexfile_GetRecordList(h); + fprintf(stdout, "INTEL Hexfile read with %d records\n", AQH_HexfileRecord_List_GetCount(recordList)); + + buffer=GWEN_Buffer_new(0, 1024, 0, 1); + AQH_Hexfile_toBuffer(h, buffer); + rv=GWEN_SyncIo_Helper_WriteFile(outFilename, (const uint8_t*) GWEN_Buffer_GetStart(buffer), GWEN_Buffer_GetUsedBytes(buffer)); + GWEN_Buffer_free(buffer); + if (rv<0) { + fprintf(stderr, "ERROR writing outfile \"%s\": %d", outFilename, rv); + AQH_Hexfile_free(h); + return 3; + } + AQH_Hexfile_free(h); + } + + return 0; +} + + + +int testFlashRecords(int argc, char **argv) +{ + const char *inFilename; + AQH_HEXFILE *h; + int rv; + + if (argc<2) { + fprintf(stderr, "Missing filename\n"); + return 1; + } + + rv=AQH_Init(); + if (rv<0) { + } + + inFilename=argv[1]; + h=AQH_Hexfile_fromFile(inFilename); + if (h==NULL) { + fprintf(stderr, "Error reading hexfile \"%s\".\n", inFilename); + return 2; + } + else { + AQH_HEXFILERECORD_LIST *recordList; + AQH_FLASHRECORD_LIST *flashRecordList; + + recordList=AQH_Hexfile_GetRecordList(h); + fprintf(stdout, "INTEL Hexfile read with %d records\n", AQH_HexfileRecord_List_GetCount(recordList)); + + flashRecordList=AQH_FlashRecord_fromHexfileRecords(recordList); + if (flashRecordList==NULL) { + fprintf(stderr, "ERROR creating flash record list\n"); + AQH_Hexfile_free(h); + return 3; + } + else { + AQH_FLASHRECORD *fr; + + fprintf(stdout, "Flash record list created with %d records\n", AQH_FlashRecord_List_GetCount(flashRecordList)); + fr=AQH_FlashRecord_List_First(flashRecordList); + while(fr) { + fprintf(stdout, "- %08x (%d bytes)\n", AQH_FlashRecord_GetAddress(fr), AQH_FlashRecord_GetDataLength(fr)); + fr=AQH_FlashRecord_List_Next(fr); + } + } + + AQH_Hexfile_free(h); + } + + return 0; +} + + int main(int argc, char **argv) @@ -349,7 +450,10 @@ int main(int argc, char **argv) //return testEndpoints(); //return testMsgMqttConnect(); //return testMqttConnection(); - return testIpcConnection(); + + //return testIpcConnection(); + //return testHexfile(argc, argv); + return testFlashRecords(argc, argv); }