save work.

This commit is contained in:
Nanosonde 2020-07-09 21:08:38 +02:00
parent 96884f768e
commit 27433fe5e1
33 changed files with 750 additions and 393 deletions

View File

@ -19,13 +19,19 @@ add_executable(knx-linux
../../src/knx/bau.h
../../src/knx/bau07B0.cpp
../../src/knx/bau07B0.h
../../src/knx/bau27B0.cpp
../../src/knx/bau091A.cpp
../../src/knx/bau091A.h
../../src/knx/bau27B0.cpp
../../src/knx/bau27B0.h
../../src/knx/bau57B0.cpp
../../src/knx/bau57B0.h
../../src/knx/bau_systemB.cpp
../../src/knx/bau_systemB.h
../../src/knx/bits.cpp
../../src/knx/bau_systemB_device.cpp
../../src/knx/bau_systemB_device.h
../../src/knx/bau_systemB_coupler.cpp
../../src/knx/bau_systemB_coupler.h
../../src/knx/bits.cpp
../../src/knx/bits.h
../../src/knx/callback_property.h
../../src/knx/cemi_frame.cpp
@ -40,9 +46,9 @@ add_executable(knx-linux
../../src/knx/data_property.cpp
../../src/knx/data_property.h
../../src/knx/device_object.cpp
../../src/knx/device_object.h
../../src/knx/dpt.cpp
../../src/knx/dpt.h
../../src/knx/device_object.h
../../src/knx/dpt.cpp
../../src/knx/dpt.h
../../src/knx/dptconvert.cpp
../../src/knx/dptconvert.h
../../src/knx/function_property.h

View File

@ -1,10 +1,7 @@
#include "knx_facade.h"
#include "knx/bau57B0.h"
#include "knx/bau27B0.h"
#include "knx/bau07B0.h"
#include "knx/bau091A.h"
#include "knx/group_object_table_object.h"
#include "knx/bits.h"
#include <time.h>
#include <stdlib.h>
@ -34,59 +31,17 @@ bool isSendHidReportPossible()
return false;
}
#if MEDIUM_TYPE == 5
KnxFacade<LinuxPlatform, Bau57B0> knx;
KnxFacade<LinuxPlatform, Bau091A> knx;
#elif MEDIUM_TYPE == 2
KnxFacade<LinuxPlatform, Bau27B0> knx;
KnxFacade<LinuxPlatform, Bau2920> knx;
#else
#error Only MEDIUM_TYPE IP and RF supported
#endif
long lastsend = 0;
#define CURR knx.getGroupObject(1)
#define MAX knx.getGroupObject(2)
#define MIN knx.getGroupObject(3)
#define RESET knx.getGroupObject(4)
void measureTemp()
{
long now = millis();
if ((now - lastsend) < 10000)
return;
lastsend = now;
int r = rand();
double currentValue = (r * 1.0) / (RAND_MAX * 1.0);
currentValue *= 100;
currentValue -= 50;
// currentValue *= (670433.28 + 273);
// currentValue -= 273;
println(currentValue);
CURR.value(currentValue);
double max = MAX.value();
if (currentValue > max)
MAX.value(currentValue);
if (currentValue < (double)MIN.value())
MIN.value(currentValue);
}
void resetCallback(GroupObject& go)
{
if (go.value())
{
MAX.valueNoSend(-273.0);
MIN.valueNoSend(670433.28);
}
}
void appLoop()
{
if (!knx.configured())
return;
measureTemp();
}
void setup()
@ -99,18 +54,7 @@ void setup()
if (knx.configured())
{
CURR.dataPointType(Dpt(9, 1));
MIN.dataPointType(Dpt(9, 1));
MIN.value(670433.28);
MAX.dataPointType(Dpt(9, 1));
MAX.valueNoSend(-273.0);
RESET.dataPointType(Dpt(1, 15));
RESET.callback(resetCallback);
printf("Timeout: %d\n", knx.paramWord(0));
printf("Zykl. senden: %d\n", knx.paramByte(2));
printf("Min/Max senden: %d\n", knx.paramByte(3));
printf("Aenderung senden: %d\n", knx.paramByte(4));
printf("Abgleich %d\n", knx.paramByte(5));
printf("configured %d\n", knx.paramByte(5));
}
else
println("not configured");

View File

@ -10,8 +10,7 @@
const SecurityControl ApplicationLayer::noSecurity {.toolAccess=false, .dataSecurity=DataSecurity::none};
ApplicationLayer::ApplicationLayer(AssociationTableObject& assocTable, BusAccessUnit& bau):
_assocTable(assocTable), _bau(bau)
ApplicationLayer::ApplicationLayer(BusAccessUnit& bau) : _bau(bau)
{
}
@ -20,6 +19,11 @@ void ApplicationLayer::transportLayer(TransportLayer& layer)
_transportLayer = &layer;
}
void ApplicationLayer::associationTableObject(AssociationTableObject& assocTable)
{
_assocTable = &assocTable;
}
#pragma region TL Callbacks
void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
@ -29,6 +33,9 @@ void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priori
void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl)
{
if (_assocTable == nullptr)
return;
uint8_t len = apdu.length();
uint8_t dataArray[len];
uint8_t* data = dataArray;
@ -45,8 +52,8 @@ void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priori
}
uint16_t startIdx = 0;
int32_t asap = _assocTable.nextAsap(tsap, startIdx);
for (; asap != -1; asap = _assocTable.nextAsap(tsap, startIdx))
int32_t asap = _assocTable->nextAsap(tsap, startIdx);
for (; asap != -1; asap = _assocTable->nextAsap(tsap, startIdx))
{
switch (apdu.type())
{
@ -365,12 +372,15 @@ void ApplicationLayer::dataConnectedConfirm(uint16_t tsap, const SecurityControl
#pragma endregion
void ApplicationLayer::groupValueReadRequest(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl& secCtrl)
{
if (_assocTable == nullptr)
return;
_savedAsapReadRequest = asap;
CemiFrame frame(1);
APDU& apdu = frame.apdu();
apdu.type(GroupValueRead);
int32_t value = _assocTable.translateAsap(asap);
int32_t value = _assocTable->translateAsap(asap);
if (value < 0)
return; // there is no tsap in association table for this asap
@ -928,6 +938,9 @@ void ApplicationLayer::propertyExtDataSend(ApduType type, AckType ack, Priority
void ApplicationLayer::groupValueSend(ApduType type, AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t& dataLength)
{
if (_assocTable == nullptr)
return;
CemiFrame frame(dataLength + 1);
APDU& apdu = frame.apdu();
apdu.type(type);
@ -943,7 +956,7 @@ void ApplicationLayer::groupValueSend(ApduType type, AckType ack, uint16_t asap,
memcpy(apdudata + 1, data, dataLength);
}
// no need to check if there is a tsap. This is a response, so the read got trough
uint16_t tsap = (uint16_t)_assocTable.translateAsap(asap);
uint16_t tsap = (uint16_t)_assocTable->translateAsap(asap);
dataGroupRequest(ack, hopType, priority, tsap, apdu, secCtrl);
dataGroupIndication(hopType, priority, tsap, apdu, secCtrl);
}

View File

@ -22,12 +22,14 @@ class ApplicationLayer
* @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses.
* @param bau methods are called here depending of the content of the APDU
*/
ApplicationLayer(AssociationTableObject& assocTable, BusAccessUnit& bau);
ApplicationLayer(BusAccessUnit& bau);
/**
* Assigns the TransportLayer to which encoded APDU are submitted to.
*/
void transportLayer(TransportLayer& layer);
void associationTableObject(AssociationTableObject& assocTable);
// from transport layer
// Note: without data secure feature, the application layer is just used with SecurtyControl.dataSecurity = none
// hooks that can be implemented by derived class (e.g. SecureApplicationLayer)
@ -204,7 +206,7 @@ class ApplicationLayer
uint16_t _savedAsapReadRequest;
uint16_t _savedAsapWriteRequest;
uint16_t _savedAsapResponse;
AssociationTableObject& _assocTable;
AssociationTableObject* _assocTable = nullptr;
BusAccessUnit& _bau;
int32_t _connectedTsap = -1;

View File

@ -8,12 +8,14 @@
using namespace std;
Bau07B0::Bau07B0(Platform& platform)
: BauSystemB(platform),
_dlLayer(_deviceObj, _addrTable, _netLayer, _platform)
: BauSystemBDevice(platform),
_dlLayer(_deviceObj, _netLayer, _platform)
#ifdef USE_CEMI_SERVER
, _cemiServer(*this)
#endif
{
_dlLayer.groupAddressTable(_addrTable);
_netLayer.dataLinkLayer(_dlLayer);
#ifdef USE_CEMI_SERVER
_cemiServer.dataLinkLayer(_dlLayer);

View File

@ -1,14 +1,14 @@
#pragma once
#include "config.h"
#include "bau_systemB.h"
#include "bau_systemB_device.h"
#include "tpuart_data_link_layer.h"
#include "cemi_server.h"
#include "cemi_server_object.h"
#ifdef USE_TP
class Bau07B0 : public BauSystemB
class Bau07B0 : public BauSystemBDevice
{
public:
Bau07B0(Platform& platform);
@ -26,4 +26,4 @@ class Bau07B0 : public BauSystemB
CemiServerObject _cemiServerObject;
#endif
};
#endif
#endif

121
src/knx/bau091A.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "config.h"
#include "bau091A.h"
#include "bits.h"
#include <string.h>
#include <stdio.h>
#ifdef USE_IP
using namespace std;
Bau091A::Bau091A(Platform& platform)
: BauSystemBCoupler(platform),
_ipParameters(_deviceObj, platform),
_dlLayerPrimary(_deviceObj, _ipParameters, _netLayer, _platform),
_dlLayerSecondary(_deviceObj, _netLayer, platform)
#ifdef USE_CEMI_SERVER
,
_cemiServer(*this)
#endif
{
_netLayer.dataLinkLayer(_dlLayerSecondary);
#ifdef USE_CEMI_SERVER
_cemiServer.dataLinkLayer(_dlLayer);
_dlLayer.cemiServer(_cemiServer);
_memory.addSaveRestore(&_cemiServerObject);
#endif
_memory.addSaveRestore(&_ipParameters);
// Set Mask Version in Device Object depending on the BAU
_deviceObj.maskVersion(0x091A);
// Set which interface objects are available in the device object
// This differs from BAU to BAU with different medium types.
// 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);
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_SECURITY);
prop->write(8, (uint16_t) OT_CEMI_SERVER);
#elif defined(USE_DATASECURE)
prop->write(7, (uint16_t) OT_SECURITY);
#elif defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_CEMI_SERVER);
#endif
}
InterfaceObject* Bau091A::getInterfaceObject(uint8_t idx)
{
switch (idx)
{
case 0:
return &_deviceObj;
case 4:
return &_appProgram;
case 5: // would be app_program 2
return nullptr;
case 6:
return &_ipParameters;
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
case 7:
return &_secIfObj;
case 8:
return &_cemiServerObject;
#elif defined(USE_CEMI_SERVER)
case 7:
return &_cemiServerObject;
#elif defined(USE_DATASECURE)
case 7:
return &_secIfObj;
#endif
default:
return nullptr;
}
}
InterfaceObject* Bau091A::getInterfaceObject(ObjectType objectType, uint8_t objectInstance)
{
// We do not use it right now.
// Required for coupler mode as there are multiple router objects for example
(void) objectInstance;
switch (objectType)
{
case OT_DEVICE:
return &_deviceObj;
case OT_APPLICATION_PROG:
return &_appProgram;
case OT_IP_PARAMETER:
return &_ipParameters;
#ifdef USE_DATASECURE
case OT_SECURITY:
return &_secIfObj;
#endif
#ifdef USE_CEMI_SERVER
case OT_CEMI_SERVER:
return &_cemiServerObject;
#endif
default:
return nullptr;
}
}
void Bau091A::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
// Common SystemB objects
BauSystemB::doMasterReset(eraseCode, channel);
_ipParameters.masterReset(eraseCode, channel);
}
DataLinkLayer& Bau091A::dataLinkLayer()
{
return _dlLayerSecondary;
}
#endif

31
src/knx/bau091A.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#include "config.h"
#ifdef USE_IP
#include "bau_systemB_coupler.h"
#include "ip_parameter_object.h"
#include "ip_data_link_layer.h"
#include "tpuart_data_link_layer.h"
#include "cemi_server_object.h"
class Bau091A : public BauSystemBCoupler
{
public:
Bau091A(Platform& platform);
protected:
InterfaceObject* getInterfaceObject(uint8_t idx);
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
DataLinkLayer& dataLinkLayer();
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override;
private:
IpParameterObject _ipParameters;
IpDataLinkLayer _dlLayerPrimary;
TpUartDataLinkLayer _dlLayerSecondary;
#ifdef USE_CEMI_SERVER
CemiServer _cemiServer;
CemiServerObject _cemiServerObject;
#endif
};
#endif

View File

@ -7,8 +7,8 @@
using namespace std;
Bau27B0::Bau27B0(Platform& platform)
: BauSystemB(platform),
_dlLayer(_deviceObj, _rfMediumObj, _addrTable, _netLayer, _platform)
: BauSystemBDevice(platform),
_dlLayer(_deviceObj, _rfMediumObj, _netLayer, _platform)
#ifdef USE_CEMI_SERVER
, _cemiServer(*this)
#endif

View File

@ -2,14 +2,14 @@
#include "config.h"
#ifdef USE_RF
#include "bau_systemB.h"
#include "bau_systemB_device.h"
#include "rf_medium_object.h"
#include "rf_physical_layer.h"
#include "rf_data_link_layer.h"
#include "cemi_server.h"
#include "cemi_server_object.h"
class Bau27B0 : public BauSystemB
class Bau27B0 : public BauSystemBDevice
{
public:
Bau27B0(Platform& platform);

View File

@ -9,9 +9,9 @@
using namespace std;
Bau57B0::Bau57B0(Platform& platform)
: BauSystemB(platform),
: BauSystemBDevice(platform),
_ipParameters(_deviceObj, platform),
_dlLayer(_deviceObj, _addrTable, _ipParameters, _netLayer, _platform)
_dlLayer(_deviceObj, _ipParameters, _netLayer, _platform)
#ifdef USE_CEMI_SERVER
,
_cemiServer(*this)

View File

@ -2,12 +2,12 @@
#include "config.h"
#ifdef USE_IP
#include "bau_systemB.h"
#include "bau_systemB_device.h"
#include "ip_parameter_object.h"
#include "ip_data_link_layer.h"
#include "cemi_server_object.h"
class Bau57B0 : public BauSystemB
class Bau57B0 : public BauSystemBDevice
{
public:
Bau57B0(Platform& platform);

View File

@ -14,41 +14,17 @@ enum NmReadSerialNumberType
static constexpr auto kFunctionPropertyResultBufferMaxSize = 64;
static constexpr auto kRestartProcessTime = 3;
BauSystemB::BauSystemB(Platform& platform): _memory(platform, _deviceObj), _addrTable(_memory),
_assocTable(_memory), _groupObjTable(_memory), _appProgram(_memory),
_platform(platform),
#ifdef USE_DATASECURE
_appLayer(_deviceObj, _secIfObj, _assocTable, _addrTable, *this),
#else
_appLayer(_assocTable, *this),
#endif
_transLayer(_appLayer, _addrTable), _netLayer(_transLayer)
BauSystemB::BauSystemB(Platform& platform): _memory(platform, _deviceObj),
_appProgram(_memory),
_platform(platform)
{
#ifdef USE_DATASECURE
_secIfObj.secureApplicationLayer(_appLayer);
#endif
_appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_appProgram);
_memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable);
#ifdef USE_DATASECURE
_memory.addSaveRestore(&_secIfObj);
#endif
}
void BauSystemB::loop()
{
dataLinkLayer().loop();
_transLayer.loop();
sendNextGroupTelegram();
nextRestartState();
#ifdef USE_DATASECURE
_appLayer.loop();
#endif
}
bool BauSystemB::enabled()
@ -61,74 +37,6 @@ void BauSystemB::enabled(bool value)
dataLinkLayer().enabled(value);
}
void BauSystemB::sendNextGroupTelegram()
{
if(!configured())
return;
static uint16_t startIdx = 1;
GroupObjectTableObject& table = _groupObjTable;
uint16_t objCount = table.entryCount();
for (uint16_t asap = startIdx; asap <= objCount; asap++)
{
GroupObject& go = table.get(asap);
ComFlag flag = go.commFlag();
if (flag != ReadRequest && flag != WriteRequest)
continue;
if (!go.communicationEnable())
continue;
SecurityControl goSecurity;
goSecurity.toolAccess = false; // Secured group communication never uses the toolkey. ETS knows all keys, also the group keys.
#ifdef USE_DATASECURE
// Get security flags from Security Interface Object for this group object
goSecurity.dataSecurity = _secIfObj.getGroupObjectSecurity(asap);
#else
goSecurity.dataSecurity = DataSecurity::none;
#endif
if (flag == WriteRequest && go.transmitEnable())
{
uint8_t* data = go.valueRef();
_appLayer.groupValueWriteRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity, data,
go.sizeInTelegram());
}
else if (flag == ReadRequest)
{
_appLayer.groupValueReadRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity);
}
go.commFlag(Transmitting);
startIdx = asap + 1;
return;
}
startIdx = 1;
}
void BauSystemB::updateGroupObject(GroupObject & go, uint8_t * data, uint8_t length)
{
uint8_t* goData = go.valueRef();
if (length != go.valueSize())
{
go.commFlag(Error);
return;
}
memcpy(goData, data, length);
go.commFlag(Updated);
GroupObjectUpdatedHandler handler = go.callback();
if (handler)
handler(go);
}
void BauSystemB::readMemory()
{
_memory.readMemory();
@ -139,21 +47,16 @@ void BauSystemB::writeMemory()
_memory.writeMemory();
}
DeviceObject& BauSystemB::deviceObject()
{
return _deviceObj;
}
GroupObjectTableObject& BauSystemB::groupObjectTable()
{
return _groupObjTable;
}
ApplicationProgramObject& BauSystemB::parameters()
{
return _appProgram;
}
DeviceObject& BauSystemB::deviceObject()
{
return _deviceObj;
}
bool BauSystemB::configured()
{
// _configured is set to true initially, if the device was configured with ETS it will be set to true after restart
@ -161,10 +64,7 @@ bool BauSystemB::configured()
if (!_configured)
return false;
_configured = _groupObjTable.loadState() == LS_LOADED
&& _addrTable.loadState() == LS_LOADED
&& _assocTable.loadState() == LS_LOADED
&& _appProgram.loadState() == LS_LOADED;
_configured = _appProgram.loadState() == LS_LOADED;
return _configured;
}
@ -233,7 +133,7 @@ void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType
uint8_t data[2];
pushWord(_deviceObj.maskVersion(), data);
_appLayer.deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, secCtrl, descriptorType, data);
applicationLayer().deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, secCtrl, descriptorType, data);
}
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
@ -248,7 +148,7 @@ void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType,
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress)
{
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
applicationLayer().memoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
_memory.toAbsolute(memoryAddress));
}
@ -256,27 +156,17 @@ void BauSystemB::memoryExtWriteIndication(Priority priority, HopCountType hopTyp
{
_memory.writeMemory(memoryAddress, number, data);
_appLayer.memoryExtWriteResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
applicationLayer().memoryExtWriteResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
}
void BauSystemB::memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
_appLayer.memoryExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
applicationLayer().memoryExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
}
void BauSystemB::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
_addrTable.masterReset(eraseCode, channel);
_assocTable.masterReset(eraseCode, channel);
_groupObjTable.masterReset(eraseCode, channel);
_appProgram.masterReset(eraseCode, channel);
#ifdef USE_DATASECURE
// If erase code is FactoryReset or FactoryResetWithoutIA, set FDSK as toolkey again
// and disable security mode.
// FIXME: the A_RestartResponse PDU has still to be sent with the current toolkey.
// Idea: use local confirmation of sent A_RestartResponse PDU to trigger writing the FDSK afterwards
_secIfObj.masterReset(eraseCode, channel);
#endif
}
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel)
@ -290,7 +180,7 @@ void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopTyp
uint8_t errorCode = checkmasterResetValidity(eraseCode, channel);
// We send the restart response now before actually applying the reset values
// Processing time is kRestartProcessTime (example 3 seconds) that we require for the applying the master reset with restart
_appLayer.restartResponse(AckRequested, priority, hopType, secCtrl, errorCode, (errorCode == 0) ? kRestartProcessTime : 0);
applicationLayer().restartResponse(AckRequested, priority, hopType, secCtrl, errorCode, (errorCode == 0) ? kRestartProcessTime : 0);
doMasterReset(eraseCode, channel);
}
else
@ -307,12 +197,12 @@ void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopTyp
void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key)
{
_appLayer.authorizeResponse(AckRequested, priority, hopType, asap, secCtrl, 0);
applicationLayer().authorizeResponse(AckRequested, priority, hopType, asap, secCtrl, 0);
}
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
applicationLayer().userMemoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
_memory.toAbsolute(memoryAddress));
}
@ -336,7 +226,7 @@ void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountTy
if (obj)
obj->readPropertyDescription(pid, propertyIndex, writeEnable, type, numberOfElements, access);
_appLayer.propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, pid, propertyIndex,
applicationLayer().propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, pid, propertyIndex,
writeEnable, type, numberOfElements, access);
}
@ -362,7 +252,7 @@ void BauSystemB::propertyValueExtWriteIndication(Priority priority, HopCountType
if (confirmed)
{
_appLayer.propertyValueExtWriteConResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, numberOfElements, startIndex, returnCode);
applicationLayer().propertyValueExtWriteConResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, numberOfElements, startIndex, returnCode);
}
}
@ -390,7 +280,7 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop
if (elementCount == 0)
size = 0;
_appLayer.propertyValueReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, elementCount,
applicationLayer().propertyValueReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, elementCount,
startIndex, data, size);
}
@ -418,7 +308,7 @@ void BauSystemB::propertyValueExtReadIndication(Priority priority, HopCountType
if (elementCount == 0)
size = 0;
_appLayer.propertyValueExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, elementCount,
applicationLayer().propertyValueExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, elementCount,
startIndex, data, size);
}
@ -441,7 +331,7 @@ void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountTy
}
}
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
applicationLayer().functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
}
void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
@ -463,7 +353,7 @@ void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType
}
}
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
applicationLayer().functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
}
void BauSystemB::functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
@ -519,7 +409,7 @@ void BauSystemB::functionPropertyExtCommandIndication(Priority priority, HopCoun
resultData[0] = ReturnCodes::GenericError;
}
_appLayer.functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
applicationLayer().functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
}
void BauSystemB::functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
@ -566,13 +456,13 @@ void BauSystemB::functionPropertyExtStateIndication(Priority priority, HopCountT
resultData[0] = ReturnCodes::GenericError;
}
_appLayer.functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
applicationLayer().functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
}
void BauSystemB::individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl)
{
if (_deviceObj.progMode())
_appLayer.individualAddressReadResponse(AckRequested, hopType, secCtrl);
applicationLayer().individualAddressReadResponse(AckRequested, hopType, secCtrl);
}
void BauSystemB::individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress)
@ -598,85 +488,10 @@ void BauSystemB::individualAddressSerialNumberReadIndication(Priority priority,
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
{
uint8_t emptyDomainAddress[6] = {0x00};
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, secCtrl, emptyDomainAddress, knxSerialNumber);
applicationLayer().IndividualAddressSerialNumberReadResponse(priority, hopType, secCtrl, emptyDomainAddress, knxSerialNumber);
}
}
void BauSystemB::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void BauSystemB::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void BauSystemB::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueRead: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.readEnable())
return;
uint8_t* data = go.valueRef();
_appLayer.groupValueReadResponse(AckRequested, asap, priority, hopType, secCtrl, data, go.sizeInTelegram());
}
void BauSystemB::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data,
uint8_t dataLength)
{
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.responseUpdateEnable())
return;
updateGroupObject(go, data, dataLength);
}
void BauSystemB::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueWrite: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.writeEnable())
return;
updateGroupObject(go, data, dataLength);
}
void BauSystemB::addSaveRestore(SaveRestore* obj)
{
_memory.addSaveRestore(obj);
@ -684,12 +499,12 @@ void BauSystemB::addSaveRestore(SaveRestore* obj)
bool BauSystemB::restartRequest(uint16_t asap, const SecurityControl secCtrl)
{
if (_appLayer.isConnected())
if (applicationLayer().isConnected())
return false;
_restartState = Connecting; // order important, has to be set BEFORE connectRequest
_restartSecurity = secCtrl;
_appLayer.connectRequest(asap, SystemPriority);
_appLayer.deviceDescriptorReadRequest(AckRequested, SystemPriority, NetworkLayerParameter, asap, secCtrl, 0);
applicationLayer().connectRequest(asap, SystemPriority);
applicationLayer().deviceDescriptorReadRequest(AckRequested, SystemPriority, NetworkLayerParameter, asap, secCtrl, 0);
return true;
}
@ -721,7 +536,7 @@ void BauSystemB::nextRestartState()
/* connection confirmed, we send restartRequest, but we wait a moment (sending ACK etc)... */
if (millis() - _restartDelay > 30)
{
_appLayer.restartRequest(AckRequested, SystemPriority, NetworkLayerParameter, _restartSecurity);
applicationLayer().restartRequest(AckRequested, SystemPriority, NetworkLayerParameter, _restartSecurity);
_restartState = Restarted;
_restartDelay = millis();
}
@ -730,7 +545,7 @@ void BauSystemB::nextRestartState()
/* restart is finished, we send a discommect */
if (millis() - _restartDelay > 30)
{
_appLayer.disconnectRequest(SystemPriority);
applicationLayer().disconnectRequest(SystemPriority);
_restartState = Idle;
}
default:
@ -753,7 +568,7 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
if (_deviceObj.progMode() && (objectType == OT_DEVICE) && (propertyId == PID_SERIAL_NUMBER))
{
// Send reply. testResult data is KNX serial number
_appLayer.systemNetworkParameterReadResponse(priority, hopType, secCtrl, objectType, propertyId,
applicationLayer().systemNetworkParameterReadResponse(priority, hopType, secCtrl, objectType, propertyId,
testInfo, testInfoLength, (uint8_t*)_deviceObj.propertyData(PID_SERIAL_NUMBER), 6);
}
break;

View File

@ -2,10 +2,6 @@
#include "config.h"
#include "bau.h"
#include "device_object.h"
#include "address_table_object.h"
#include "association_table_object.h"
#include "group_object_table_object.h"
#include "security_interface_object.h"
#include "application_program_object.h"
#include "application_layer.h"
@ -21,9 +17,8 @@ class BauSystemB : protected BusAccessUnit
public:
BauSystemB(Platform& platform);
virtual void loop();
DeviceObject& deviceObject();
GroupObjectTableObject& groupObjectTable();
ApplicationProgramObject& parameters();
DeviceObject& deviceObject();
Memory& memory();
bool configured();
bool enabled();
@ -43,6 +38,8 @@ class BauSystemB : protected BusAccessUnit
protected:
virtual DataLinkLayer& dataLinkLayer() = 0;
virtual ApplicationLayer& applicationLayer() = 0;
void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data) override;
void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
@ -80,14 +77,6 @@ class BauSystemB : protected BusAccessUnit
void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber) override;
void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber) override;
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength, bool status) override;
void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status) override;
void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl) override;
void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override;
void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
@ -96,8 +85,6 @@ class BauSystemB : protected BusAccessUnit
virtual InterfaceObject* getInterfaceObject(uint8_t idx) = 0;
virtual InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance) = 0;
void sendNextGroupTelegram();
void updateGroupObject(GroupObject& go, uint8_t* data, uint8_t length);
void nextRestartState();
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel);
@ -110,21 +97,10 @@ class BauSystemB : protected BusAccessUnit
Restarted
};
DeviceObject _deviceObj;
Memory _memory;
AddressTableObject _addrTable;
AssociationTableObject _assocTable;
GroupObjectTableObject _groupObjTable;
DeviceObject _deviceObj;
ApplicationProgramObject _appProgram;
Platform& _platform;
#ifdef USE_DATASECURE
SecureApplicationLayer _appLayer;
SecurityInterfaceObject _secIfObj;
#else
ApplicationLayer _appLayer;
#endif
TransportLayer _transLayer;
NetworkLayer _netLayer;
bool _configured = true;
RestartState _restartState = Idle;
SecurityControl _restartSecurity;

View File

@ -0,0 +1,57 @@
#include "bau_systemB_coupler.h"
#include "bits.h"
#include <string.h>
#include <stdio.h>
BauSystemBCoupler::BauSystemBCoupler(Platform& platform) :
BauSystemB(platform),
_platform(platform),
#ifdef USE_DATASECURE
_appLayer(_deviceObj, _secIfObj, *this),
#else
_appLayer(*this),
#endif
_transLayer(_appLayer), _netLayer(_deviceObj, _transLayer)
{
#ifdef USE_DATASECURE
_secIfObj.secureApplicationLayer(_appLayer);
#endif
_appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_appProgram);
#ifdef USE_DATASECURE
_memory.addSaveRestore(&_secIfObj);
#endif
}
ApplicationLayer& BauSystemBCoupler::applicationLayer()
{
return _appLayer;
}
void BauSystemBCoupler::loop()
{
dataLinkLayer().loop();
_transLayer.loop();
#ifdef USE_DATASECURE
_appLayer.loop();
#endif
}
bool BauSystemBCoupler::configured()
{
// _configured is set to true initially, if the device was configured with ETS it will be set to true after restart
if (!_configured)
return false;
_configured = _appProgram.loadState() == LS_LOADED;
return _configured;
}
void BauSystemBCoupler::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
}

View File

@ -0,0 +1,53 @@
#pragma once
#include "config.h"
#include "bau_systemB.h"
#include "device_object.h"
#include "address_table_object.h"
#include "association_table_object.h"
#include "group_object_table_object.h"
#include "security_interface_object.h"
#include "application_program_object.h"
#include "application_layer.h"
#include "secure_application_layer.h"
#include "transport_layer.h"
#include "network_layer.h"
#include "data_link_layer.h"
#include "platform.h"
#include "memory.h"
class BauSystemBCoupler : public BauSystemB
{
public:
BauSystemBCoupler(Platform& platform);
virtual void loop();
bool configured();
protected:
virtual DataLinkLayer& dataLinkLayer() = 0;
virtual ApplicationLayer& applicationLayer() override;
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel);
enum RestartState
{
Idle,
Connecting,
Connected,
Restarted
};
Platform& _platform;
#ifdef USE_DATASECURE
SecureApplicationLayer _appLayer;
SecurityInterfaceObject _secIfObj;
#else
ApplicationLayer _appLayer;
#endif
TransportLayer _transLayer;
NetworkLayer _netLayer;
bool _configured = true;
RestartState _restartState = Idle;
SecurityControl _restartSecurity;
uint32_t _restartDelay = 0;
};

View File

@ -0,0 +1,227 @@
#include "bau_systemB_device.h"
#include "bits.h"
#include <string.h>
#include <stdio.h>
BauSystemBDevice::BauSystemBDevice(Platform& platform) :
BauSystemB(platform),
_addrTable(_memory),
_assocTable(_memory), _groupObjTable(_memory),
#ifdef USE_DATASECURE
_appLayer(_deviceObj, _secIfObj, *this),
#else
_appLayer(*this),
#endif
_transLayer(_appLayer), _netLayer(_deviceObj, _transLayer)
{
#ifdef USE_DATASECURE
_secIfObj.secureApplicationLayer(_appLayer);
#endif
_appLayer.transportLayer(_transLayer);
_appLayer.associationTableObject(_assocTable);
_appLayer.groupAddressTable(_addrTable);
_transLayer.networkLayer(_netLayer);
_transLayer.groupAddressTable(_addrTable);
_memory.addSaveRestore(&_deviceObj);
_memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable);
#ifdef USE_DATASECURE
_memory.addSaveRestore(&_secIfObj);
#endif
}
ApplicationLayer& BauSystemBDevice::applicationLayer()
{
return _appLayer;
}
void BauSystemBDevice::loop()
{
dataLinkLayer().loop();
_transLayer.loop();
sendNextGroupTelegram();
nextRestartState();
#ifdef USE_DATASECURE
_appLayer.loop();
#endif
}
void BauSystemBDevice::sendNextGroupTelegram()
{
if(!configured())
return;
static uint16_t startIdx = 1;
GroupObjectTableObject& table = _groupObjTable;
uint16_t objCount = table.entryCount();
for (uint16_t asap = startIdx; asap <= objCount; asap++)
{
GroupObject& go = table.get(asap);
ComFlag flag = go.commFlag();
if (flag != ReadRequest && flag != WriteRequest)
continue;
if (!go.communicationEnable())
continue;
SecurityControl goSecurity;
goSecurity.toolAccess = false; // Secured group communication never uses the toolkey. ETS knows all keys, also the group keys.
#ifdef USE_DATASECURE
// Get security flags from Security Interface Object for this group object
goSecurity.dataSecurity = _secIfObj.getGroupObjectSecurity(asap);
#else
goSecurity.dataSecurity = DataSecurity::none;
#endif
if (flag == WriteRequest && go.transmitEnable())
{
uint8_t* data = go.valueRef();
_appLayer.groupValueWriteRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity, data,
go.sizeInTelegram());
}
else if (flag == ReadRequest)
{
_appLayer.groupValueReadRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity);
}
go.commFlag(Transmitting);
startIdx = asap + 1;
return;
}
startIdx = 1;
}
void BauSystemBDevice::updateGroupObject(GroupObject & go, uint8_t * data, uint8_t length)
{
uint8_t* goData = go.valueRef();
if (length != go.valueSize())
{
go.commFlag(Error);
return;
}
memcpy(goData, data, length);
go.commFlag(Updated);
GroupObjectUpdatedHandler handler = go.callback();
if (handler)
handler(go);
}
GroupObjectTableObject& BauSystemBDevice::groupObjectTable()
{
return _groupObjTable;
}
bool BauSystemBDevice::configured()
{
// _configured is set to true initially, if the device was configured with ETS it will be set to true after restart
if (!_configured)
return false;
_configured = _groupObjTable.loadState() == LS_LOADED
&& _addrTable.loadState() == LS_LOADED
&& _assocTable.loadState() == LS_LOADED
&& _appProgram.loadState() == LS_LOADED;
return _configured;
}
void BauSystemBDevice::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
_addrTable.masterReset(eraseCode, channel);
_assocTable.masterReset(eraseCode, channel);
_groupObjTable.masterReset(eraseCode, channel);
_appProgram.masterReset(eraseCode, channel);
#ifdef USE_DATASECURE
// If erase code is FactoryReset or FactoryResetWithoutIA, set FDSK as toolkey again
// and disable security mode.
// FIXME: the A_RestartResponse PDU has still to be sent with the current toolkey.
// Idea: use local confirmation of sent A_RestartResponse PDU to trigger writing the FDSK afterwards
_secIfObj.masterReset(eraseCode, channel);
#endif
}
void BauSystemBDevice::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void BauSystemBDevice::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
go.commFlag(Ok);
else
go.commFlag(Error);
}
void BauSystemBDevice::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueRead: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.readEnable())
return;
uint8_t* data = go.valueRef();
_appLayer.groupValueReadResponse(AckRequested, asap, priority, hopType, secCtrl, data, go.sizeInTelegram());
}
void BauSystemBDevice::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data,
uint8_t dataLength)
{
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.responseUpdateEnable())
return;
updateGroupObject(go, data, dataLength);
}
void BauSystemBDevice::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueWrite: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.writeEnable())
return;
updateGroupObject(go, data, dataLength);
}

View File

@ -0,0 +1,56 @@
#pragma once
#include "config.h"
#include "bau_systemB.h"
#include "device_object.h"
#include "address_table_object.h"
#include "association_table_object.h"
#include "group_object_table_object.h"
#include "security_interface_object.h"
#include "application_program_object.h"
#include "application_layer.h"
#include "secure_application_layer.h"
#include "transport_layer.h"
#include "network_layer.h"
#include "data_link_layer.h"
#include "platform.h"
#include "memory.h"
class BauSystemBDevice : public BauSystemB
{
public:
BauSystemBDevice(Platform& platform);
virtual void loop();
GroupObjectTableObject& groupObjectTable();
Memory& memory();
bool configured();
protected:
virtual ApplicationLayer& applicationLayer() override;
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength, bool status) override;
void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status) override;
void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl) override;
void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void sendNextGroupTelegram();
void updateGroupObject(GroupObject& go, uint8_t* data, uint8_t length);
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel);
AddressTableObject _addrTable;
AssociationTableObject _assocTable;
GroupObjectTableObject _groupObjTable;
#ifdef USE_DATASECURE
SecureApplicationLayer _appLayer;
SecurityInterfaceObject _secIfObj;
#else
ApplicationLayer _appLayer;
#endif
TransportLayer _transLayer;
NetworkLayer _netLayer;
};

View File

@ -6,9 +6,8 @@
#include "address_table_object.h"
#include "cemi_server.h"
DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
NetworkLayer& layer, Platform& platform) :
_deviceObject(devObj), _groupAddressTable(addrTab), _networkLayer(layer), _platform(platform)
DataLinkLayer::DataLinkLayer(DeviceObject& devObj, NetworkLayer& layer, Platform& platform) :
_deviceObject(devObj), _networkLayer(layer), _platform(platform)
{
}
@ -115,18 +114,6 @@ void DataLinkLayer::frameRecieved(CemiFrame& frame)
}
else
{
if (addrType == InduvidualAddress && destination != _deviceObject.induvidualAddress())
return;
if (addrType == GroupAddress && !_groupAddressTable.contains(destination))
return;
// if (frame.npdu().octetCount() > 0)
// {
// _print("-> DLL ");
// frame.apdu().printPDU();
// }
_networkLayer.dataIndication(ack, addrType, destination, type, npdu, priority, source);
}
}

View File

@ -4,7 +4,6 @@
#include <stdint.h>
#include "device_object.h"
#include "address_table_object.h"
#include "knx_types.h"
#include "network_layer.h"
#include "cemi_server.h"
@ -12,7 +11,7 @@
class DataLinkLayer
{
public:
DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer,
DataLinkLayer(DeviceObject& devObj, NetworkLayer& layer,
Platform& platform);
#ifdef USE_CEMI_SERVER
@ -36,7 +35,6 @@ class DataLinkLayer
virtual bool sendFrame(CemiFrame& frame) = 0;
uint8_t* frameData(CemiFrame& frame);
DeviceObject& _deviceObject;
AddressTableObject& _groupAddressTable;
NetworkLayer& _networkLayer;
Platform& _platform;
#ifdef USE_CEMI_SERVER

View File

@ -5,7 +5,6 @@
#include "bits.h"
#include "platform.h"
#include "device_object.h"
#include "address_table_object.h"
#include "knx_ip_routing_indication.h"
#include "knx_ip_search_request.h"
#include "knx_ip_search_response.h"
@ -18,8 +17,8 @@
#define MIN_LEN_CEMI 10
IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam,
NetworkLayer& layer, Platform& platform) : DataLinkLayer(devObj, addrTab, layer, platform), _ipParameters(ipParam)
IpDataLinkLayer::IpDataLinkLayer(DeviceObject& devObj, IpParameterObject& ipParam,
NetworkLayer& layer, Platform& platform) : DataLinkLayer(devObj, layer, platform), _ipParameters(ipParam)
{
}

View File

@ -11,7 +11,7 @@ class IpDataLinkLayer : public DataLinkLayer
using DataLinkLayer::_deviceObject;
public:
IpDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, IpParameterObject& ipParam, NetworkLayer& layer,
IpDataLinkLayer(DeviceObject& devObj, IpParameterObject& ipParam, NetworkLayer& layer,
Platform& platform);
void loop();
@ -25,4 +25,4 @@ class IpDataLinkLayer : public DataLinkLayer
IpParameterObject& _ipParameters;
};
#endif
#endif

View File

@ -4,7 +4,7 @@
#include "data_link_layer.h"
#include "bits.h"
NetworkLayer::NetworkLayer(TransportLayer& layer): _transportLayer(layer)
NetworkLayer::NetworkLayer(DeviceObject &deviceObj, TransportLayer& layer): _transportLayer(layer), _deviceObj(deviceObj)
{
}
@ -27,6 +27,21 @@ void NetworkLayer::hopCount(uint8_t value)
void NetworkLayer::dataIndication(AckType ack, AddressType addrType, uint16_t destination, FrameFormat format, NPDU& npdu, Priority priority, uint16_t source)
{
HopCountType hopType = npdu.hopCount() == 7 ? UnlimitedRouting : NetworkLayerParameter;
// Only for devices which are not a coupler
if (addrType == InduvidualAddress && destination != _deviceObj.induvidualAddress())
return;
// TODO: remove. getTSAP() will return 0 later anyway. Get rid of dependency to GAT
//if (addrType == GroupAddress && !_groupAddressTable.contains(destination))
// return;
// if (frame.npdu().octetCount() > 0)
// {
// _print("-> DLL ");
// frame.apdu().printPDU();
// }
if (addrType == InduvidualAddress)
{
//if (npdu.octetCount() > 0)

View File

@ -5,11 +5,12 @@
#include "npdu.h"
#include "transport_layer.h"
class DataLinkLayer;
class DeviceObject;
class NetworkLayer
{
public:
NetworkLayer(TransportLayer& layer);
NetworkLayer(DeviceObject& deviceObj, TransportLayer& layer);
void dataLinkLayer(DataLinkLayer& layer);
uint8_t hopCount() const;
@ -38,4 +39,6 @@ class NetworkLayer
uint8_t _hopCount = 6;
DataLinkLayer* _dataLinkLayer = 0;
TransportLayer& _transportLayer;
DeviceObject& _deviceObj;
};

View File

@ -73,9 +73,9 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
return true;
}
RfDataLinkLayer::RfDataLinkLayer(DeviceObject& devObj, RfMediumObject& rfMediumObj, AddressTableObject& addrTab,
RfDataLinkLayer::RfDataLinkLayer(DeviceObject& devObj, RfMediumObject& rfMediumObj,
NetworkLayer& layer, Platform& platform)
: DataLinkLayer(devObj, addrTab, layer, platform),
: DataLinkLayer(devObj, layer, platform),
_rfMediumObj(rfMediumObj),
_rfPhy(*this, platform)
{
@ -377,4 +377,4 @@ void RfDataLinkLayer::loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBuffer
delete tx_frame;
}
#endif
#endif

View File

@ -16,12 +16,11 @@ class RfDataLinkLayer : public DataLinkLayer
friend class RfPhysicalLayer;
using DataLinkLayer::_deviceObject;
using DataLinkLayer::_groupAddressTable;
using DataLinkLayer::_platform;
public:
RfDataLinkLayer(DeviceObject& devObj, RfMediumObject& rfMediumObj, AddressTableObject& addrTab, NetworkLayer& layer,
Platform& platform);
RfDataLinkLayer(DeviceObject& devObj, RfMediumObject& rfMediumObj, NetworkLayer& layer,
Platform& platform);
void loop();
void enabled(bool value);
@ -60,4 +59,4 @@ class RfDataLinkLayer : public DataLinkLayer
uint16_t calcCrcRF(uint8_t* buffer, uint32_t offset, uint32_t len);
};
#endif
#endif

View File

@ -23,18 +23,25 @@ static constexpr uint8_t kSecureDataPdu = 0;
static constexpr uint8_t kSecureSyncRequest = 2;
static constexpr uint8_t kSecureSyncResponse = 3;
SecureApplicationLayer::SecureApplicationLayer(DeviceObject &deviceObj, SecurityInterfaceObject &secIfObj, AssociationTableObject& assocTable, AddressTableObject &addrTab, BusAccessUnit& bau):
ApplicationLayer(assocTable, bau),
SecureApplicationLayer::SecureApplicationLayer(DeviceObject &deviceObj, SecurityInterfaceObject &secIfObj, BusAccessUnit& bau):
ApplicationLayer(bau),
_secIfObj(secIfObj),
_deviceObj(deviceObj),
_addrTab(addrTab)
_deviceObj(deviceObj)
{
}
void SecureApplicationLayer::groupAddressTable(AddressTableObject &addrTable)
{
_addrTab = &addrTable;
}
/* from transport layer */
void SecureApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
{
if (_addrTab == nullptr)
return;
println("dataGroupIndication");
if (apdu.type() == SecureService)
@ -293,12 +300,15 @@ void SecureApplicationLayer::dataConnectedConfirm(uint16_t tsap)
void SecureApplicationLayer::dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl)
{
if (_addrTab == nullptr)
return;
println("dataGroupRequest");
if (secCtrl.dataSecurity != DataSecurity::none)
{
apdu.frame().sourceAddress(_deviceObj.induvidualAddress());
apdu.frame().destinationAddress(_addrTab.getGroupAddress(tsap));
apdu.frame().destinationAddress(_addrTab->getGroupAddress(tsap));
apdu.frame().addressType(GroupAddress);
uint16_t secureApduLength = apdu.length() + 3 + 6 + 4; // 3(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4
@ -507,7 +517,10 @@ void SecureApplicationLayer::blockCtr0(uint8_t* buffer, uint8_t* seqNum, uint16_
uint16_t SecureApplicationLayer::groupAddressIndex(uint16_t groupAddr)
{
return _addrTab.getTsap(groupAddr);
// Just for safety reasons, we should never get here, because the dataGroupIndication will return already return early without doing anything
if (_addrTab == nullptr)
return 0;
return _addrTab->getTsap(groupAddr);
}
const uint8_t* SecureApplicationLayer::securityKey(uint16_t addr, bool isGroupAddress)

View File

@ -28,7 +28,9 @@ class SecureApplicationLayer : public ApplicationLayer
* @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses.
* @param bau methods are called here depending of the content of the APDU
*/
SecureApplicationLayer(DeviceObject& deviceObj, SecurityInterfaceObject& secIfObj, AssociationTableObject& assocTable, AddressTableObject& addrTab, BusAccessUnit& bau);
SecureApplicationLayer(DeviceObject& deviceObj, SecurityInterfaceObject& secIfObj, BusAccessUnit& bau);
void groupAddressTable(AddressTableObject& addrTable);
void clearFailureLog();
void getFailureCounters(uint8_t* data);
@ -150,5 +152,5 @@ class SecureApplicationLayer : public ApplicationLayer
SecurityInterfaceObject& _secIfObj;
DeviceObject& _deviceObj;
AddressTableObject& _addrTab;
AddressTableObject* _addrTab = nullptr;
};

View File

@ -265,23 +265,39 @@ void TpUartDataLinkLayer::loop()
if (!_isEcho)
{
uint8_t c = 0x10;
//ceck if individual or group address
if ((buffer[6] & 0x80) == 0)
// If this is not a nullptr we consider this a device to be a coupler
// TODO: Improve for coupler mode, only ACK according to filter tables
if (_groupAddressTable)
{
//check if individual or group address
if ((buffer[6] & 0x80) == 0)
{
//individual
if (_deviceObject.induvidualAddress() == getWord(buffer + 4))
{
c |= 0x01;
}
}
else
{
//group
if (_groupAddressTable->contains(getWord(buffer + 4)) || getWord(buffer + 4) == 0)
{
c |= 0x01;
}
}
}
else
{
// TODO: test for only our coupler
//individual
if (_deviceObject.induvidualAddress() == getWord(buffer + 4))
{
c |= 0x01;
}
}
else
{
//group
if (_groupAddressTable.contains(getWord(buffer + 4)) || getWord(buffer + 4) == 0)
{
c |= 0x01;
}
}
_platform.writeUart(c);
}
}
@ -412,12 +428,17 @@ void TpUartDataLinkLayer::stopChip()
#endif
}
TpUartDataLinkLayer::TpUartDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab,
TpUartDataLinkLayer::TpUartDataLinkLayer(DeviceObject& devObj,
NetworkLayer& layer, Platform& platform)
: DataLinkLayer(devObj, addrTab, layer, platform)
: DataLinkLayer(devObj, layer, platform)
{
}
void TpUartDataLinkLayer::groupAddressTable(AddressTableObject &addrTable)
{
_groupAddressTable = &addrTable;
}
void TpUartDataLinkLayer::frameBytesReceived(uint8_t* buffer, uint16_t length)
{
//printHex("=>", buffer, length);
@ -548,4 +569,4 @@ void TpUartDataLinkLayer::loadNextTxFrame()
}
delete tx_frame;
}
#endif
#endif

View File

@ -11,13 +11,15 @@
class TpUartDataLinkLayer : public DataLinkLayer
{
using DataLinkLayer::_deviceObject;
using DataLinkLayer::_groupAddressTable;
using DataLinkLayer::_platform;
public:
TpUartDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer,
TpUartDataLinkLayer(DeviceObject& devObj, NetworkLayer& layer,
Platform& platform);
;
void groupAddressTable(AddressTableObject& addrTable);
void loop();
void enabled(bool value);
bool enabled() const;
@ -62,5 +64,7 @@ class TpUartDataLinkLayer : public DataLinkLayer
void dataConBytesReceived(uint8_t* buffer, uint16_t length, bool success);
bool resetChip();
void stopChip();
AddressTableObject* _groupAddressTable = nullptr;
};
#endif
#endif

View File

@ -7,8 +7,8 @@
#include "bits.h"
#include <stdio.h>
TransportLayer::TransportLayer(ApplicationLayer& layer, AddressTableObject& gat): _savedFrame(0),
_savedFrameConnecting(0), _applicationLayer(layer), _groupAddressTable(gat)
TransportLayer::TransportLayer(ApplicationLayer& layer): _savedFrame(0),
_savedFrameConnecting(0), _applicationLayer(layer)
{
_currentState = Closed;
}
@ -18,6 +18,11 @@ void TransportLayer::networkLayer(NetworkLayer& layer)
_networkLayer = &layer;
}
void TransportLayer::groupAddressTable(AddressTableObject &addrTable)
{
_groupAddressTable = &addrTable;
}
void TransportLayer::dataIndividualIndication(uint16_t destination, HopCountType hopType, Priority priority, uint16_t source, TPDU& tpdu)
{
//if (tpdu.apdu().length() > 0)
@ -361,7 +366,10 @@ void TransportLayer::dataIndividualConfirm(AckType ack, uint16_t destination, Ho
void TransportLayer::dataGroupIndication(uint16_t destination, HopCountType hopType, Priority priority, uint16_t source, TPDU& tpdu)
{
uint16_t tsap = _groupAddressTable.getTsap(destination);
if (_groupAddressTable == nullptr)
return;
uint16_t tsap = _groupAddressTable->getTsap(destination);
if (tsap == 0)
return;
@ -395,7 +403,10 @@ void TransportLayer::dataSystemBroadcastConfirm(AckType ack, HopCountType hopTyp
void TransportLayer::dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
{
uint16_t groupAdress = _groupAddressTable.getGroupAddress(tsap);
if (_groupAddressTable == nullptr)
return;
uint16_t groupAdress = _groupAddressTable->getGroupAddress(tsap);
TPDU& tpdu = apdu.frame().tpdu();
_networkLayer->dataGroupRequest(ack, groupAdress, hopType, priority, tpdu);
}

View File

@ -16,8 +16,9 @@ enum StateType { Closed, OpenIdle, OpenWait, Connecting };
class TransportLayer
{
public:
TransportLayer(ApplicationLayer& layer, AddressTableObject& gat);
TransportLayer(ApplicationLayer& layer);
void networkLayer(NetworkLayer& layer);
void groupAddressTable(AddressTableObject& addrTable);
#pragma region from network layer
void dataIndividualIndication(uint16_t destination, HopCountType hopType, Priority priority, uint16_t source, TPDU& tpdu);
@ -115,6 +116,6 @@ private:
uint8_t _maxRepCount = 3;
#pragma endregion
ApplicationLayer& _applicationLayer;
AddressTableObject& _groupAddressTable;
AddressTableObject* _groupAddressTable;
NetworkLayer* _networkLayer;
};

View File

@ -27,6 +27,7 @@
#include "linux_platform.h"
#include "knx/bau57B0.h"
#include "knx/bau27B0.h"
#include "knx/bau091A.h"
#endif
void buttonUp();