/**************************************************************************** * 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); /* big endian */ 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; }