save work

This commit is contained in:
Nanosonde 2020-07-15 16:32:04 +02:00
parent c70e552991
commit 255ee7f1c4
7 changed files with 184 additions and 119 deletions

View File

@ -18,13 +18,21 @@ Bau091A::Bau091A(Platform& platform)
_cemiServer(*this)
#endif
{
_rtObjPrimary.property(PID_MEDIUM)->write((uint8_t) DptMedium::KNX_IP);
_rtObjSecondary.property(PID_MEDIUM)->write((uint8_t) DptMedium::KNX_TP1);
_rtObjPrimary.property(PID_OBJECT_INDEX)->write((uint8_t) 1);
_rtObjSecondary.property(PID_OBJECT_INDEX)->write((uint8_t) 2);
_netLayer.getEntity(0).dataLinkLayer(_dlLayerPrimary);
_netLayer.getEntity(1).dataLinkLayer(_dlLayerSecondary);
#ifdef USE_CEMI_SERVER
_cemiServer.dataLinkLayer(_dlLayerSecondary); // Secondary I/F is the important one!
_dlLayer.cemiServer(_cemiServer);
_memory.addSaveRestore(&_cemiServerObject);
#endif
_memory.addSaveRestore(&_ipParameters);
// Set Mask Version in Device Object depending on the BAU
@ -35,18 +43,17 @@ Bau091A::Bau091A(Platform& platform)
// See PID_IO_LIST
Property* prop = _deviceObj.property(PID_IO_LIST);
prop->write(1, (uint16_t) OT_DEVICE);
prop->write(2, (uint16_t) OT_ADDR_TABLE);
prop->write(3, (uint16_t) OT_ASSOC_TABLE);
prop->write(4, (uint16_t) OT_GRP_OBJ_TABLE);
prop->write(5, (uint16_t) OT_APPLICATION_PROG);
prop->write(6, (uint16_t) OT_IP_PARAMETER);
prop->write(2, (uint16_t) OT_ROUTER);
prop->write(3, (uint16_t) OT_ROUTER);
prop->write(3, (uint16_t) OT_APPLICATION_PROG);
prop->write(4, (uint16_t) OT_IP_PARAMETER);
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_SECURITY);
prop->write(8, (uint16_t) OT_CEMI_SERVER);
prop->write(5, (uint16_t) OT_SECURITY);
prop->write(6, (uint16_t) OT_CEMI_SERVER);
#elif defined(USE_DATASECURE)
prop->write(7, (uint16_t) OT_SECURITY);
prop->write(5, (uint16_t) OT_SECURITY);
#elif defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_CEMI_SERVER);
prop->write(5, (uint16_t) OT_CEMI_SERVER);
#endif
}
@ -57,9 +64,9 @@ InterfaceObject* Bau091A::getInterfaceObject(uint8_t idx)
case 0:
return &_deviceObj;
case 1:
return nullptr; // TODO: Router Object Primary IF
return &_rtObjPrimary;
case 2:
return nullptr; // TODO: Router Object Secondary IF
return &_rtObjSecondary;
case 3:
return &_appProgram;
case 4:
@ -91,6 +98,8 @@ InterfaceObject* Bau091A::getInterfaceObject(ObjectType objectType, uint8_t obje
{
case OT_DEVICE:
return &_deviceObj;
case OT_ROUTER:
return objectInstance == 0 ? &_rtObjPrimary : &_rtObjSecondary;
case OT_APPLICATION_PROG:
return &_appProgram;
case OT_IP_PARAMETER:

View File

@ -6,6 +6,8 @@
BauSystemBCoupler::BauSystemBCoupler(Platform& platform) :
BauSystemB(platform),
_platform(platform),
_rtObjPrimary(),
_rtObjSecondary(memory()),
#ifdef USE_DATASECURE
_appLayer(_deviceObj, _secIfObj, *this),
#else

View File

@ -8,6 +8,8 @@
#include "group_object_table_object.h"
#include "security_interface_object.h"
#include "application_program_object.h"
#include "router_object.h"
#include "router_object_filtertable.h"
#include "application_layer.h"
#include "secure_application_layer.h"
#include "transport_layer.h"
@ -29,6 +31,9 @@ class BauSystemBCoupler : public BauSystemB
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override;
Platform& _platform;
RouterObject _rtObjPrimary;
RouterObjectFilterTable _rtObjSecondary;
#ifdef USE_DATASECURE
SecureApplicationLayer _appLayer;
SecurityInterfaceObject _secIfObj;

View File

@ -228,3 +228,13 @@ enum EraseCode
ResetLinks = 0x06,
FactoryResetWithoutIA = 0x07
};
enum DptMedium
{
// DPT_Medium (20.1004), range 0-255
// All other values are reserved.
KNX_TP1 = 0x00,
KNX_PL110 = 0x01,
KNX_RF = 0x02,
KNX_IP = 0x05
};

View File

@ -15,11 +15,11 @@ void RouterObject::initializeProperties(size_t propertiesSize, Property** proper
Property* ownProperties[] =
{
new DataProperty( PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) OT_ROUTER ),
new DataProperty( PID_OBJECT_INDEX, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
new DataProperty( PID_MEDIUM_STATUS, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
new DataProperty( PID_MAX_APDU_LENGTH_ROUTER, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 254 ),
new DataProperty( PID_HOP_COUNT, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 5),
new DataProperty( PID_MEDIUM, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint16_t) 0) , // TODO
new DataProperty( PID_OBJECT_INDEX, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0 ), // Must be set by concrete BAUxxxx
new DataProperty( PID_MEDIUM_STATUS, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // For now: communication on medium is always possible
new DataProperty( PID_MAX_APDU_LENGTH_ROUTER, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 254 ), // For now: fixed size
new DataProperty( PID_HOP_COUNT, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 5), // TODO: Primary side: 5 for line coupler, 4 for backbone coupler, only exists if secondary is open medium without hop count
new DataProperty( PID_MEDIUM, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 ), // Must be set by concrete BAUxxxx
};
uint8_t ownPropertiesCount = sizeof(ownProperties) / sizeof(Property*);

View File

@ -8,6 +8,14 @@
#include "callback_property.h"
#include "function_property.h"
enum RouteTableServices
{
ClearRoutingTable = 0x01, // no info bytes
SetRoutingTable = 0x02, // no info bytes
ClearGroupAddress = 0x03, // 4 bytes: start address and end address
SetGroupAddress = 0x04, // 4 bytes: start address and end address
};
RouterObjectFilterTable::RouterObjectFilterTable(Memory& memory)
: _memory(memory)
{
@ -48,121 +56,24 @@ RouterObjectFilterTable::RouterObjectFilterTable(Memory& memory)
new FunctionProperty<RouterObjectFilterTable>(this, PID_ROUTETABLE_CONTROL,
// Command Callback of PID_ROUTETABLE_CONTROL
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
if (length != 3)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
uint8_t id = data[1];
uint8_t info = data[2];
if (id == 0 && info == 0)
{
//obj->clearFailureLog();
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
obj->functionRouteTableControl(true, data, length, resultData, resultLength);
},
// State Callback of PID_ROUTETABLE_CONTROL
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
if (length != 3)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
uint8_t id = data[1];
uint8_t info = data[2];
// failure counters
if (id == 0 && info == 0)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultData[2] = info;
//obj->getFailureCounters(&resultData[3]); // Put 8 bytes in the buffer
resultLength = 3 + 8;
return;
}
// query latest failure by index
else if(id == 1)
{
uint8_t maxBufferSize = resultLength; // Remember the maximum buffer size of the buffer that is provided to us
uint8_t index = info;
uint8_t numBytes = 0;//obj->getFromFailureLogByIndex(index, &resultData[2], maxBufferSize);
if ( numBytes > 0)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultData[2] = index;
resultLength += numBytes;
resultLength = 3 + numBytes;
return;
}
resultData[0] = ReturnCodes::DataVoid;
resultData[1] = id;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
obj->functionRouteTableControl(false, data, length, resultData, resultLength);
}),
new DataProperty( PID_FILTER_TABLE_USE, false, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
/*
new FunctionProperty<RouterObjectFilterTable>(this, PID_RF_ENABLE_SBC,
// Command Callback of PID_RF_ENABLE_SBC
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
uint8_t serviceId = data[1] & 0xff;
if (serviceId != 0)
{
resultData[0] = ReturnCodes::InvalidCommand;
resultLength = 1;
return;
}
if (length == 3)
{
uint8_t mode = data[2];
if (mode > 1)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
//obj->setSecurityMode(mode == 1);
resultData[0] = ReturnCodes::Success;
resultData[1] = serviceId;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
obj->functionRfEnableSbc(true, data, length, resultData, resultLength);
},
// State Callback of PID_RF_ENABLE_SBC
[](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
uint8_t serviceId = data[1] & 0xff;
if (serviceId != 0)
{
resultData[0] = ReturnCodes::InvalidCommand;
resultLength = 1;
return;
}
if (length == 2)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = serviceId;
resultData[2] = 0;//obj->isSecurityModeEnabled() ? 1 : 0;
resultLength = 3;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
obj->functionRfEnableSbc(false, data, length, resultData, resultLength);
}),
*/
};
RouterObject::initializeProperties(sizeof(properties), properties);
@ -202,11 +113,103 @@ uint16_t RouterObjectFilterTable::saveSize()
return 1 + 4 + RouterObject::saveSize();
}
void RouterObjectFilterTable::functionRouteTableControl(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
{
bool isError = false;
RouteTableServices srvId = (RouteTableServices) data[1];
// Filter Table Realization Type 3
// The Filter Table Realisation Type 3 shall be organised as a memory mapped bit-field of
// 65536 bits and thus 8 192 octets. Each bit shall uniquely correspond to one Group Address.
// The full 16 bit KNX GA encoding range shall be supported.
//
// octet_address = GA_value div 8
// bit_position = GA_value mod 8
// The CRC of the Memory Control Block Table Property is a CRC16-CCITT with the following
// parameters:
// Width = 16 bit
// Truncated polynomial = 1021h
// Initial value = FFFFh
// Input date is NOT reflected.
// Output CRC is NOT reflected.
// No XOR is performed on the output CRC.
// EXAMPLE The correct CRC16-CCITT of the string 123456789 is E5CCh.
if (isCommand)
{
switch(srvId)
{
case ClearRoutingTable:
case SetRoutingTable:
case ClearGroupAddress:
case SetGroupAddress: break;
default: isError = true;
}
}
else
{
switch(srvId)
{
case ClearRoutingTable:
case SetRoutingTable:
case ClearGroupAddress:
case SetGroupAddress: break;
default: isError = true;
}
}
if (isError)
{
resultData[0] = ReturnCodes::GenericError;
resultData[1] = srvId;
resultLength = 2;
}
}
void RouterObjectFilterTable::functionRfEnableSbc(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
{
if (isCommand)
{
_rfSbcRoutingEnabled = (data[0] == 1) ? true : false;
}
resultData[0] = ReturnCodes::Success;
resultData[1] = _rfSbcRoutingEnabled ? 1 : 0;
resultLength = 2;
}
bool RouterObjectFilterTable::isRfSbcRoutingEnabled()
{
return _rfSbcRoutingEnabled;
}
uint32_t RouterObjectFilterTable::tableReference()
{
return (uint32_t)_memory.toRelative(_data);
}
bool RouterObjectFilterTable::allocTable(uint32_t size, bool doFill, uint8_t fillByte)
{
if (_data)
{
_memory.freeMemory(_data);
_data = 0;
}
if (size == 0)
return true;
_data = _memory.allocMemory(size);
if (!_data)
return false;
if (doFill)
memset(_data, fillByte, size);
return true;
}
bool RouterObjectFilterTable::isLoaded()
{
return _state == LS_LOADED;
@ -272,7 +275,9 @@ void RouterObjectFilterTable::loadEventLoading(const uint8_t* data)
case LE_UNLOAD:
loadState(LS_UNLOADED);
break;
case LE_ADDITIONAL_LOAD_CONTROLS: // Not supported here
case LE_ADDITIONAL_LOAD_CONTROLS:
additionalLoadControls(data);
break;
default:
loadState(LS_ERROR);
errorCode(E_GOT_UNDEF_LOAD_CMD);
@ -292,6 +297,12 @@ void RouterObjectFilterTable::loadEventLoaded(const uint8_t* data)
break;
case LE_UNLOAD:
loadState(LS_UNLOADED);
//free nv memory
if (_data)
{
_memory.freeMemory(_data);
_data = 0;
}
break;
case LE_ADDITIONAL_LOAD_CONTROLS:
loadState(LS_ERROR);
@ -322,6 +333,25 @@ void RouterObjectFilterTable::loadEventError(const uint8_t* data)
}
}
void RouterObjectFilterTable::additionalLoadControls(const uint8_t* data)
{
if (data[1] != 0x0B) // Data Relative Allocation
{
loadState(LS_ERROR);
errorCode(E_INVALID_OPCODE);
return;
}
size_t size = ((data[2] << 24) | (data[3] << 16) | (data[4] << 8) | data[5]);
bool doFill = data[6] == 0x1;
uint8_t fillByte = data[7];
if (!allocTable(size, doFill, fillByte))
{
loadState(LS_ERROR);
errorCode(E_MAX_TABLE_LENGTH_EXEEDED);
}
}
void RouterObjectFilterTable::loadState(LoadState newState)
{
if (newState == _state)

View File

@ -12,6 +12,8 @@ class RouterObjectFilterTable: public RouterObject
public:
RouterObjectFilterTable(Memory& memory);
bool isRfSbcRoutingEnabled();
virtual void masterReset(EraseCode eraseCode, uint8_t channel) override;
bool isLoaded();
@ -22,7 +24,12 @@ public:
uint16_t saveSize() override;
private:
// Function properties
void functionRouteTableControl(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength);
void functionRfEnableSbc(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength);
uint32_t tableReference();
bool allocTable(uint32_t size, bool doFill, uint8_t fillByte);
void errorCode(ErrorCode errorCode);
void loadEvent(const uint8_t* data);
@ -30,10 +37,12 @@ private:
void loadEventLoading(const uint8_t* data);
void loadEventLoaded(const uint8_t* data);
void loadEventError(const uint8_t* data);
void additionalLoadControls(const uint8_t* data);
void loadState(LoadState newState);
LoadState _state = LS_UNLOADED;
Memory& _memory;
uint8_t *_data = 0;
bool _rfSbcRoutingEnabled = false;
};