|
|
@ -1,7 +1,7 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* reporting.c
|
|
|
|
* reporting.c
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Copyright 2013-2023 Michael Zillgith
|
|
|
|
* Copyright 2013-2024 Michael Zillgith
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
*
|
|
|
|
*
|
|
|
@ -185,7 +185,8 @@ purgeBuf(ReportControl* rc)
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
deleteDataSetValuesShadowBuffer(ReportControl* self)
|
|
|
|
deleteDataSetValuesShadowBuffer(ReportControl* self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->bufferedDataSetValues != NULL) {
|
|
|
|
if (self->bufferedDataSetValues != NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(self->dataSet != NULL);
|
|
|
|
assert(self->dataSet != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
int dataSetSize = DataSet_getSize(self->dataSet);
|
|
|
|
int dataSetSize = DataSet_getSize(self->dataSet);
|
|
|
@ -2911,13 +2912,14 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
int dataBlockSize = 0;
|
|
|
|
int dataBlockSize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (isIntegrity || isGI) {
|
|
|
|
if (isIntegrity || isGI)
|
|
|
|
|
|
|
|
{
|
|
|
|
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
|
|
|
|
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
|
|
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++) {
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* don't need reason for inclusion in GI or integrity report */
|
|
|
|
/* don't need reason for inclusion in GI or integrity report */
|
|
|
|
|
|
|
|
|
|
|
|
int encodedSize;
|
|
|
|
int encodedSize;
|
|
|
@ -2925,7 +2927,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
if (dataSetEntry->value) {
|
|
|
|
if (dataSetEntry->value) {
|
|
|
|
encodedSize = MmsValue_encodeMmsData(dataSetEntry->value, NULL, 0, false);
|
|
|
|
encodedSize = MmsValue_encodeMmsData(dataSetEntry->value, NULL, 0, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
MmsValue _errVal;
|
|
|
|
MmsValue _errVal;
|
|
|
|
_errVal.type = MMS_DATA_ACCESS_ERROR;
|
|
|
|
_errVal.type = MMS_DATA_ACCESS_ERROR;
|
|
|
|
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
|
|
|
|
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
|
|
|
@ -2940,17 +2943,19 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
bufferEntrySize += MemoryAllocator_getAlignedSize(sizeof(int) + dataBlockSize); /* add aligned_size(LEN + DATA) */
|
|
|
|
bufferEntrySize += MemoryAllocator_getAlignedSize(sizeof(int) + dataBlockSize); /* add aligned_size(LEN + DATA) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* other trigger reason */
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* other trigger reason */
|
|
|
|
bufferEntrySize += inclusionFieldSize;
|
|
|
|
bufferEntrySize += inclusionFieldSize;
|
|
|
|
|
|
|
|
|
|
|
|
int reasonForInclusionSize = 0;
|
|
|
|
int reasonForInclusionSize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++) {
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
reasonForInclusionSize++;
|
|
|
|
reasonForInclusionSize++;
|
|
|
|
|
|
|
|
|
|
|
|
assert(reportControl->bufferedDataSetValues[i] != NULL);
|
|
|
|
assert(reportControl->bufferedDataSetValues[i] != NULL);
|
|
|
@ -2985,13 +2990,15 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
if (DEBUG_IED_SERVER)
|
|
|
|
printf("IED_SERVER: number of reports in report buffer: %i\n", buffer->reportsCount);
|
|
|
|
printf("IED_SERVER: number of reports in report buffer: %i\n", buffer->reportsCount);
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->lastEnqueuedReport == NULL) { /* buffer is empty - we start at the beginning of the memory block */
|
|
|
|
if (buffer->lastEnqueuedReport == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* buffer is empty - we start at the beginning of the memory block */
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->nextToTransmit = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->nextToTransmit = (ReportBufferEntry*) entryBufPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(buffer->lastEnqueuedReport != NULL);
|
|
|
|
assert(buffer->lastEnqueuedReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
|
|
|
|
|
|
|
@ -3003,12 +3010,16 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
if (DEBUG_IED_SERVER) printf ("IED_SERVER: Last buffer offset: %i\n", (int) ((uint8_t*) buffer->lastEnqueuedReport - buffer->memoryBlock));
|
|
|
|
if (DEBUG_IED_SERVER) printf ("IED_SERVER: Last buffer offset: %i\n", (int) ((uint8_t*) buffer->lastEnqueuedReport - buffer->memoryBlock));
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->lastEnqueuedReport == buffer->oldestReport) { /* --> buffer->reportsCount == 1 */
|
|
|
|
if (buffer->lastEnqueuedReport == buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* --> buffer->reportsCount == 1 */
|
|
|
|
assert(buffer->reportsCount == 1);
|
|
|
|
assert(buffer->reportsCount == 1);
|
|
|
|
|
|
|
|
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
|
|
|
|
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* buffer overflow */
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
|
|
|
|
|
|
|
|
#if (DEBUG_IED_SERVER == 1)
|
|
|
|
#if (DEBUG_IED_SERVER == 1)
|
|
|
@ -3022,7 +3033,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
buffer->oldestReport->next = NULL;
|
|
|
|
buffer->oldestReport->next = NULL;
|
|
|
|
buffer->nextToTransmit = NULL;
|
|
|
|
buffer->nextToTransmit = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport)
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport)
|
|
|
|
buffer->nextToTransmit = buffer->lastEnqueuedReport;
|
|
|
|
buffer->nextToTransmit = buffer->lastEnqueuedReport;
|
|
|
|
|
|
|
|
|
|
|
@ -3031,17 +3043,22 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (buffer->lastEnqueuedReport > buffer->oldestReport) {
|
|
|
|
else if (buffer->lastEnqueuedReport > buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
|
|
|
|
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* buffer overflow */
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
|
|
|
|
|
|
|
|
/* remove old reports until enough space for new entry is available */
|
|
|
|
/* remove old reports until enough space for new entry is available */
|
|
|
|
while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) {
|
|
|
|
while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport) {
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
overflow = true;
|
|
|
|
overflow = true;
|
|
|
@ -3056,7 +3073,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
buffer->reportsCount--;
|
|
|
|
buffer->reportsCount--;
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->oldestReport == NULL) {
|
|
|
|
if (buffer->oldestReport == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->oldestReport = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->oldestReport->next = NULL;
|
|
|
|
buffer->oldestReport->next = NULL;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -3066,14 +3084,18 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
buffer->lastEnqueuedReport->next = (ReportBufferEntry*) entryBufPos;
|
|
|
|
buffer->lastEnqueuedReport->next = (ReportBufferEntry*) entryBufPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (buffer->lastEnqueuedReport < buffer->oldestReport) {
|
|
|
|
else if (buffer->lastEnqueuedReport < buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
|
|
|
|
|
|
|
|
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
|
|
|
|
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* buffer overflow */
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
entryBufPos = buffer->memoryBlock;
|
|
|
|
|
|
|
|
|
|
|
|
/* remove older reports in upper buffer part */
|
|
|
|
/* remove older reports in upper buffer part */
|
|
|
|
while ((uint8_t*) buffer->oldestReport > buffer->memoryBlock) {
|
|
|
|
while ((uint8_t*) buffer->oldestReport > buffer->memoryBlock)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport) {
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport) {
|
|
|
@ -3093,13 +3115,15 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* remove older reports in lower buffer part that will be overwritten by new report */
|
|
|
|
/* remove older reports in lower buffer part that will be overwritten by new report */
|
|
|
|
while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) {
|
|
|
|
while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (buffer->oldestReport == NULL)
|
|
|
|
if (buffer->oldestReport == NULL)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport) {
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
overflow = true;
|
|
|
|
overflow = true;
|
|
|
@ -3115,15 +3139,17 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
buffer->reportsCount--;
|
|
|
|
buffer->reportsCount--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
while (((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) && ((uint8_t*) buffer->oldestReport != buffer->memoryBlock)) {
|
|
|
|
{
|
|
|
|
|
|
|
|
while (((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) && ((uint8_t*) buffer->oldestReport != buffer->memoryBlock))
|
|
|
|
|
|
|
|
{
|
|
|
|
if (buffer->oldestReport == NULL)
|
|
|
|
if (buffer->oldestReport == NULL)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
assert(buffer->oldestReport != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport) {
|
|
|
|
if (buffer->nextToTransmit == buffer->oldestReport)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->nextToTransmit = buffer->oldestReport->next;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
buffer->isOverflow = true;
|
|
|
|
overflow = true;
|
|
|
|
overflow = true;
|
|
|
@ -3154,7 +3180,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
entry->timeOfEntry = timeOfEntry;
|
|
|
|
entry->timeOfEntry = timeOfEntry;
|
|
|
|
|
|
|
|
|
|
|
|
if (isBuffered) {
|
|
|
|
if (isBuffered)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* ENTRY_ID is set to system time in ms! */
|
|
|
|
/* ENTRY_ID is set to system time in ms! */
|
|
|
|
uint64_t entryId = timeOfEntry;
|
|
|
|
uint64_t entryId = timeOfEntry;
|
|
|
|
|
|
|
|
|
|
|
@ -3173,7 +3200,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
printf(" at pos %p\n", entryStartPos);
|
|
|
|
printf(" at pos %p\n", entryStartPos);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (reportControl->enabled == false) {
|
|
|
|
if (reportControl->enabled == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
Semaphore_wait(reportControl->rcbValuesLock);
|
|
|
|
Semaphore_wait(reportControl->rcbValuesLock);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@ -3200,7 +3228,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
entryBufPos += MemoryAllocator_getAlignedSize(sizeof(ReportBufferEntry));
|
|
|
|
entryBufPos += MemoryAllocator_getAlignedSize(sizeof(ReportBufferEntry));
|
|
|
|
|
|
|
|
|
|
|
|
if (isIntegrity || isGI) {
|
|
|
|
if (isIntegrity || isGI)
|
|
|
|
|
|
|
|
{
|
|
|
|
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
|
|
|
|
DataSetEntry* dataSetEntry = reportControl->dataSet->fcdas;
|
|
|
|
|
|
|
|
|
|
|
|
/* encode LEN */
|
|
|
|
/* encode LEN */
|
|
|
@ -3210,12 +3239,13 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
/* encode DATA */
|
|
|
|
/* encode DATA */
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++) {
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (dataSetEntry->value) {
|
|
|
|
if (dataSetEntry->value) {
|
|
|
|
entryBufPos += MmsValue_encodeMmsData(dataSetEntry->value, entryBufPos, 0, true);
|
|
|
|
entryBufPos += MmsValue_encodeMmsData(dataSetEntry->value, entryBufPos, 0, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
MmsValue _errVal;
|
|
|
|
MmsValue _errVal;
|
|
|
|
_errVal.type = MMS_DATA_ACCESS_ERROR;
|
|
|
|
_errVal.type = MMS_DATA_ACCESS_ERROR;
|
|
|
|
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
|
|
|
|
_errVal.value.dataAccessError = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
|
|
|
@ -3225,9 +3255,9 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
dataSetEntry = dataSetEntry->sibling;
|
|
|
|
dataSetEntry = dataSetEntry->sibling;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
/* encode inclusion bit string */
|
|
|
|
/* encode inclusion bit string */
|
|
|
|
inclusionFieldStatic.value.bitString.buf = entryBufPos;
|
|
|
|
inclusionFieldStatic.value.bitString.buf = entryBufPos;
|
|
|
|
memset(entryBufPos, 0, inclusionFieldSize);
|
|
|
|
memset(entryBufPos, 0, inclusionFieldSize);
|
|
|
@ -3240,10 +3270,10 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
/* encode DATA */
|
|
|
|
/* encode DATA */
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++) {
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* update inclusion bit string for report entry */
|
|
|
|
/* update inclusion bit string for report entry */
|
|
|
|
MmsValue_setBitStringBit(inclusionField, i, true);
|
|
|
|
MmsValue_setBitStringBit(inclusionField, i, true);
|
|
|
|
|
|
|
|
|
|
|
@ -3251,13 +3281,14 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
|
|
|
|
|
|
|
|
|
|
|
|
entryBufPos += MmsValue_encodeMmsData(reportControl->bufferedDataSetValues[i], entryBufPos, 0, true);
|
|
|
|
entryBufPos += MmsValue_encodeMmsData(reportControl->bufferedDataSetValues[i], entryBufPos, 0, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* encode REASON */
|
|
|
|
/* encode REASON */
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++) {
|
|
|
|
for (i = 0; i < inclusionBitStringSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE) {
|
|
|
|
if (reportControl->inclusionFlags[i] != REPORT_CONTROL_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
*entryBufPos = (uint8_t) reportControl->inclusionFlags[i];
|
|
|
|
*entryBufPos = (uint8_t) reportControl->inclusionFlags[i];
|
|
|
|
entryBufPos ++;
|
|
|
|
entryBufPos ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3286,10 +3317,12 @@ exit_function:
|
|
|
|
Semaphore_post(buffer->lock);
|
|
|
|
Semaphore_post(buffer->lock);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (reportControl->server) {
|
|
|
|
if (reportControl->server)
|
|
|
|
|
|
|
|
{
|
|
|
|
MmsMapping* mmsMapping = reportControl->server->mmsMapping;
|
|
|
|
MmsMapping* mmsMapping = reportControl->server->mmsMapping;
|
|
|
|
|
|
|
|
|
|
|
|
if (mmsMapping->rcbEventHandler) {
|
|
|
|
if (mmsMapping->rcbEventHandler)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (overflow) {
|
|
|
|
if (overflow) {
|
|
|
|
mmsMapping->rcbEventHandler(mmsMapping->rcbEventHandlerParameter, reportControl->rcb, NULL, RCB_EVENT_OVERFLOW, NULL, DATA_ACCESS_ERROR_SUCCESS);
|
|
|
|
mmsMapping->rcbEventHandler(mmsMapping->rcbEventHandlerParameter, reportControl->rcb, NULL, RCB_EVENT_OVERFLOW, NULL, DATA_ACCESS_ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -3980,11 +4013,12 @@ Reporting_activateBufferedReports(MmsMapping* self)
|
|
|
|
static void
|
|
|
|
static void
|
|
|
|
processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if ((rc->enabled) || (rc->isBuffering)) {
|
|
|
|
if ((rc->enabled) || (rc->isBuffering))
|
|
|
|
|
|
|
|
{
|
|
|
|
if (rc->triggerOps & TRG_OPT_GI) {
|
|
|
|
if (rc->triggerOps & TRG_OPT_GI)
|
|
|
|
if (rc->gi) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (rc->gi)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* send current events in event buffer before GI report */
|
|
|
|
/* send current events in event buffer before GI report */
|
|
|
|
if (rc->triggered) {
|
|
|
|
if (rc->triggered) {
|
|
|
|
rc->triggered = false;
|
|
|
|
rc->triggered = false;
|
|
|
@ -3999,12 +4033,12 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rc->triggerOps & TRG_OPT_INTEGRITY) {
|
|
|
|
if (rc->triggerOps & TRG_OPT_INTEGRITY)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (rc->intgPd > 0) {
|
|
|
|
if (rc->intgPd > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (currentTimeInMs >= rc->nextIntgReportTime) {
|
|
|
|
if (currentTimeInMs >= rc->nextIntgReportTime)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* send current events in event buffer before integrity report */
|
|
|
|
/* send current events in event buffer before integrity report */
|
|
|
|
if (rc->triggered) {
|
|
|
|
if (rc->triggered) {
|
|
|
|
enqueueReport(rc, false, false, currentTimeInMs);
|
|
|
|
enqueueReport(rc, false, false, currentTimeInMs);
|
|
|
@ -4019,8 +4053,8 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* check for system time change effects */
|
|
|
|
/* check for system time change effects */
|
|
|
|
if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd)) {
|
|
|
|
if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd))
|
|
|
|
|
|
|
|
{
|
|
|
|
if (rc->server->syncIntegrityReportTimes) {
|
|
|
|
if (rc->server->syncIntegrityReportTimes) {
|
|
|
|
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
|
|
|
|
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -4033,9 +4067,11 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
|
|
|
|
|
|
|
|
rc->triggered = false;
|
|
|
|
rc->triggered = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
/* check for system time change effects */
|
|
|
|
/* check for system time change effects */
|
|
|
|
if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd)) {
|
|
|
|
if ((rc->nextIntgReportTime < currentTimeInMs) || (rc->nextIntgReportTime > currentTimeInMs + rc->intgPd))
|
|
|
|
|
|
|
|
{
|
|
|
|
if (rc->server->syncIntegrityReportTimes) {
|
|
|
|
if (rc->server->syncIntegrityReportTimes) {
|
|
|
|
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
|
|
|
|
rc->nextIntgReportTime = getNextRoundedStartTime(currentTimeInMs, rc->intgPd);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -4047,9 +4083,10 @@ processEventsForReport(ReportControl* rc, uint64_t currentTimeInMs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rc->triggered) {
|
|
|
|
if (rc->triggered)
|
|
|
|
if (currentTimeInMs >= rc->reportTime) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (currentTimeInMs >= rc->reportTime)
|
|
|
|
|
|
|
|
{
|
|
|
|
enqueueReport(rc, false, false, currentTimeInMs);
|
|
|
|
enqueueReport(rc, false, false, currentTimeInMs);
|
|
|
|
|
|
|
|
|
|
|
|
rc->triggered = false;
|
|
|
|
rc->triggered = false;
|
|
|
@ -4065,11 +4102,12 @@ Reporting_processReportEvents(MmsMapping* self, uint64_t currentTimeInMs)
|
|
|
|
Semaphore_wait(self->isModelLockedMutex);
|
|
|
|
Semaphore_wait(self->isModelLockedMutex);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (self->isModelLocked == false) {
|
|
|
|
if (self->isModelLocked == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
LinkedList element = self->reportControls;
|
|
|
|
LinkedList element = self->reportControls;
|
|
|
|
|
|
|
|
|
|
|
|
while ((element = LinkedList_getNext(element)) != NULL ) {
|
|
|
|
while ((element = LinkedList_getNext(element)) != NULL )
|
|
|
|
|
|
|
|
{
|
|
|
|
ReportControl* rc = (ReportControl*) element->data;
|
|
|
|
ReportControl* rc = (ReportControl*) element->data;
|
|
|
|
|
|
|
|
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
@ -4093,11 +4131,12 @@ Reporting_sendReports(MmsMapping* self, MmsServerConnection connection)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LinkedList element = LinkedList_getNext(self->reportControls);
|
|
|
|
LinkedList element = LinkedList_getNext(self->reportControls);
|
|
|
|
|
|
|
|
|
|
|
|
while (element) {
|
|
|
|
while (element)
|
|
|
|
|
|
|
|
{
|
|
|
|
ReportControl* rc = (ReportControl*) LinkedList_getData(element);
|
|
|
|
ReportControl* rc = (ReportControl*) LinkedList_getData(element);
|
|
|
|
|
|
|
|
|
|
|
|
if (rc->clientConnection == connection) {
|
|
|
|
if (rc->clientConnection == connection)
|
|
|
|
|
|
|
|
{
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
|
|
|
|
|
|
|
|
|
if (rc->enabled) {
|
|
|
|
if (rc->enabled) {
|
|
|
@ -4124,8 +4163,10 @@ static void
|
|
|
|
copyValuesToReportBuffer(ReportControl* self)
|
|
|
|
copyValuesToReportBuffer(ReportControl* self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < self->dataSet->elementCount; i++) {
|
|
|
|
for (i = 0; i < self->dataSet->elementCount; i++)
|
|
|
|
if (self->inclusionFlags[i] & REPORT_CONTROL_NOT_UPDATED) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (self->inclusionFlags[i] & REPORT_CONTROL_NOT_UPDATED)
|
|
|
|
|
|
|
|
{
|
|
|
|
copySingleValueToReportBuffer(self, i);
|
|
|
|
copySingleValueToReportBuffer(self, i);
|
|
|
|
|
|
|
|
|
|
|
|
/* clear not-updated flag */
|
|
|
|
/* clear not-updated flag */
|
|
|
@ -4142,13 +4183,14 @@ Reporting_processReportEventsAfterUnlock(MmsMapping* self)
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t currentTime = Hal_getTimeInMs();
|
|
|
|
uint64_t currentTime = Hal_getTimeInMs();
|
|
|
|
|
|
|
|
|
|
|
|
while ((element = LinkedList_getNext(element)) != NULL ) {
|
|
|
|
while ((element = LinkedList_getNext(element)) != NULL )
|
|
|
|
|
|
|
|
{
|
|
|
|
ReportControl* rc = (ReportControl*) element->data;
|
|
|
|
ReportControl* rc = (ReportControl*) element->data;
|
|
|
|
|
|
|
|
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
|
ReportControl_lockNotify(rc);
|
|
|
|
|
|
|
|
|
|
|
|
if ((rc->enabled) || (rc->isBuffering)) {
|
|
|
|
if ((rc->enabled) || (rc->isBuffering))
|
|
|
|
|
|
|
|
{
|
|
|
|
if (rc->triggered) {
|
|
|
|
if (rc->triggered) {
|
|
|
|
copyValuesToReportBuffer(rc);
|
|
|
|
copyValuesToReportBuffer(rc);
|
|
|
|
|
|
|
|
|
|
|
@ -4166,10 +4208,13 @@ ReportControl_valueUpdated(ReportControl* self, int dataSetEntryIndex, int flag,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ReportControl_lockNotify(self);
|
|
|
|
ReportControl_lockNotify(self);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->inclusionFlags[dataSetEntryIndex] & flag) { /* report for this data set entry is already pending (bypass BufTm) */
|
|
|
|
if (self->inclusionFlags[dataSetEntryIndex] & flag)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* report for this data set entry is already pending (bypass BufTm and send report immediately) */
|
|
|
|
self->reportTime = Hal_getTimeInMs();
|
|
|
|
self->reportTime = Hal_getTimeInMs();
|
|
|
|
|
|
|
|
|
|
|
|
if (modelLocked) {
|
|
|
|
if (modelLocked)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* buffer all relevant values */
|
|
|
|
/* buffer all relevant values */
|
|
|
|
copyValuesToReportBuffer(self);
|
|
|
|
copyValuesToReportBuffer(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -4177,19 +4222,21 @@ ReportControl_valueUpdated(ReportControl* self, int dataSetEntryIndex, int flag,
|
|
|
|
processEventsForReport(self, self->reportTime);
|
|
|
|
processEventsForReport(self, self->reportTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (modelLocked) {
|
|
|
|
if (modelLocked)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* set flag to update values when report is to be sent or data model unlocked */
|
|
|
|
/* set flag to update values when report is to be sent or data model unlocked */
|
|
|
|
self->inclusionFlags[dataSetEntryIndex] = self->inclusionFlags[dataSetEntryIndex] | flag | REPORT_CONTROL_NOT_UPDATED;
|
|
|
|
self->inclusionFlags[dataSetEntryIndex] = self->inclusionFlags[dataSetEntryIndex] | flag | REPORT_CONTROL_NOT_UPDATED;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
self->inclusionFlags[dataSetEntryIndex] = flag;
|
|
|
|
self->inclusionFlags[dataSetEntryIndex] = flag;
|
|
|
|
|
|
|
|
|
|
|
|
/* buffer value for report */
|
|
|
|
/* buffer value for report */
|
|
|
|
copySingleValueToReportBuffer(self, dataSetEntryIndex);
|
|
|
|
copySingleValueToReportBuffer(self, dataSetEntryIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (self->triggered == false) {
|
|
|
|
if (self->triggered == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
uint64_t currentTime = Hal_getTimeInMs();
|
|
|
|
uint64_t currentTime = Hal_getTimeInMs();
|
|
|
|
|
|
|
|
|
|
|
|
MmsValue_setBinaryTime(self->timeOfEntry, currentTime);
|
|
|
|
MmsValue_setBinaryTime(self->timeOfEntry, currentTime);
|
|
|
@ -4218,7 +4265,8 @@ ReportControlBlock_getRptEna(ReportControlBlock* self)
|
|
|
|
char*
|
|
|
|
char*
|
|
|
|
ReportControlBlock_getRptID(ReportControlBlock* self)
|
|
|
|
ReportControlBlock_getRptID(ReportControlBlock* self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->trgOps & 64) {
|
|
|
|
if (self->trgOps & 64)
|
|
|
|
|
|
|
|
{
|
|
|
|
ReportControl* rc = (ReportControl*)(self->sibling);
|
|
|
|
ReportControl* rc = (ReportControl*)(self->sibling);
|
|
|
|
|
|
|
|
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
|
|
|