aqhome: added lib for hexfiles and flash records.

This commit is contained in:
Martin Preuss
2023-04-18 19:41:56 +02:00
parent 93e89e801e
commit 4e409851f6
12 changed files with 1136 additions and 1 deletions

85
aqhome/hexfile/0BUILD Normal file
View File

@@ -0,0 +1,85 @@
<?xml?>
<gwbuild>
<target type="ConvenienceLibrary" name="aqhhexfile" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)
-I$(topbuilddir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
</includes>
<define name="BUILDING_AQHOME" />
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
--api=AQHOME_API
</setVar>
<setVar name="local/typefiles" >
</setVar>
<setVar name="local/built_sources" >
</setVar>
<setVar name="local/built_headers_pub">
</setVar>
<setVar name="local/built_headers_priv" >
</setVar>
<headers dist="false" install="$(pkgincludedir)/hexfile" >
$(local/built_headers_pub)
</headers>
<headers dist="true" install="$(pkgincludedir)/hexfile" >
hexfilerecord.h
hexfilerecord_p.h
hexfile.h
hexfile_p.h
flashrecord.h
flashrecord_p.h
</headers>
<headers dist="true" >
</headers>
<sources>
$(local/typefiles)
hexfile.c
hexfilerecord.c
flashrecord.c
</sources>
<extradist>
</extradist>
<useTargets>
</useTargets>
<subdirs>
</subdirs>
</target>
</gwbuild>

View File

@@ -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 <config.h>
#endif
#include "./flashrecord_p.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/misc.h>
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;
}

View File

@@ -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 <aqhome/api.h>
#include <aqhome/hexfile/hexfilerecord.h>
#include <gwenhywfar/list.h>
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

View File

@@ -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

318
aqhome/hexfile/hexfile.c Normal file
View File

@@ -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 <config.h>
#endif
#include "aqhome/hexfile/hexfile_p.h"
#include <gwenhywfar/syncio.h>
#include <gwenhywfar/debug.h>
#include <string.h>
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<dataLen; i++) {
v=_readByte(s);
if (v<0)
return NULL;
ptr[i]=(uint8_t) v;
s+=2;
}
}
/* checksum */
v=_readByte(s);
if (v<0)
return NULL;
s+=2;
v+=_sumValuesForChecksum(hr);
if (v & 0xff) {
DBG_ERROR(AQH_LOGDOMAIN, "Invalid checksum (%d, %d)", (v & 0xff), -(v & 0xff));
return NULL;
}
return s;
}
void _writeRecord(AQH_HEXFILERECORD *hr, GWEN_BUFFER *buffer)
{
uint8_t len;
int v;
len=AQH_HexfileRecord_GetByteCount(hr);
GWEN_Buffer_AppendArgs(buffer, ":%02X%04X%02X",
AQH_HexfileRecord_GetByteCount(hr),
AQH_HexfileRecord_GetAddress(hr),
AQH_HexfileRecord_GetRecordType(hr));
if (len) {
const uint8_t *ptr;
int i;
ptr=AQH_HexfileRecord_GetDataPointer(hr);
for(i=0; i<len; i++)
GWEN_Buffer_AppendArgs(buffer, "%02X", ptr[i]);
}
v=_sumValuesForChecksum(hr);
GWEN_Buffer_AppendArgs(buffer, "%02X", (-v) & 0xff);
}
int _sumValuesForChecksum(const AQH_HEXFILERECORD *hr)
{
int v;
int dataLen;
dataLen=AQH_HexfileRecord_GetByteCount(hr);
v=AQH_HexfileRecord_GetByteCount(hr)+
((AQH_HexfileRecord_GetAddress(hr)>>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<dataLen; i++)
v+=ptr[i];
}
return v;
}
int _readWord(const char *s)
{
uint16_t result;
int b;
b=_readByte(s);
if (b<0)
return -1;
result=(uint16_t)(b & 0xff);
s+=2;
b=_readByte(s++);
if (b<0)
return -1;
result<<=8;
result|=(uint16_t)(b & 0xff);
return (int) result;
}
int _readByte(const char *s)
{
uint8_t result;
int c;
c=_readNibble(s++);
if (c<0)
return -1;
result=(uint8_t) (c & 0xf);
c=_readNibble(s);
if (c<0)
return -1;
result<<=4;
result|=(uint8_t) (c & 0xf);
return (int) result;
}
int _readNibble(const char *s)
{
uint8_t c;
c=*s;
if (c==0)
return -1;
if (c>='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;
}

41
aqhome/hexfile/hexfile.h Normal file
View File

@@ -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 <aqhome/api.h>
#include <aqhome/hexfile/hexfilerecord.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/buffer.h>
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

View File

@@ -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

View File

@@ -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 <config.h>
#endif
#include "./hexfilerecord_p.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/misc.h>
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;
}

View File

@@ -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 <aqhome/api.h>
#include <gwenhywfar/list.h>
#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

View File

@@ -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