diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index f2bcbe2..099f63a 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -725,6 +725,66 @@ void ApplicationLayer::memoryReadResponse(AckType ack, Priority priority, HopCou memorySend(MemoryResponse, ack, priority, hopType, asap, secCtrl, number, memoryAddress, memoryData); } +void ApplicationLayer::memoryExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, + uint8_t number, uint32_t memoryAddress, uint8_t * memoryData) +{ + CemiFrame frame(5 + number); + APDU& apdu = frame.apdu(); + apdu.type(MemoryExtReadResponse); + uint8_t* data = apdu.data(); + data[1] = code; + data[2] = (memoryAddress >> 16); + data[3] = (memoryAddress >> 0); + data[4] = (memoryAddress & 0xFF); + + memcpy(&data[5], memoryData, number); + + individualSend(ack, hopType, priority, asap, apdu, secCtrl); +} + +uint16_t ApplicationLayer::crc16Ccitt(uint8_t* input, uint16_t length) +{ + uint32_t polynom = 0x1021; + uint8_t padded[length+2]; + + memcpy(padded, input, length); + memset(padded+length, 0x00, 2); + + uint32_t result = 0xffff; + for (uint32_t i = 0; i < 8 * (uint32_t)sizeof(padded); i++) { + result <<= 1; + uint32_t nextBit = (padded[i / 8] >> (7 - (i % 8))) & 0x1; + result |= nextBit; + if ((result & 0x10000) != 0) + result ^= polynom; + } + return result & 0xffff; +} + +void ApplicationLayer::memoryExtWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, + uint8_t number, uint32_t memoryAddress, uint8_t * memoryData) +{ + bool withCrc = code == ReturnCodes::SuccessWithCrc; + + CemiFrame frame(5 + (withCrc ? 2 : 0)); + APDU& apdu = frame.apdu(); + apdu.type(MemoryExtWriteResponse); + uint8_t* data = apdu.data(); + data[1] = code; + data[2] = (memoryAddress >> 16); + data[3] = (memoryAddress >> 0); + data[4] = (memoryAddress & 0xFF); + + if (withCrc) + { + uint16_t crc = crc16Ccitt(memoryData, number); // TODO + data[5] = crc >> 8; + data[6] = crc & 0xFF; + } + + individualSend(ack, hopType, priority, asap, apdu, secCtrl); +} + void ApplicationLayer::memoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t * data) { @@ -1038,6 +1098,26 @@ void ApplicationLayer::individualIndication(HopCountType hopType, Priority prior case MemoryWrite: _bau.memoryWriteIndication(priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3); break; + case MemoryExtRead: + { + uint8_t number = data[1]; + uint32_t memoryAddress = ((data[2] & 0xff) << 16) | ((data[3] & 0xff) << 8) | (data[4] & 0xff); + _bau.memoryExtReadIndication(priority, hopType, tsap, secCtrl, number, memoryAddress); + break; + } + //case MemoryExtReadResponse: + // _bau.memoryExtReadAppLayerConfirm(priority, hopType, tsap, secCtrl, data[0], getInt(data + 1), data + 4); // TODO return code + // break; + case MemoryExtWrite: + { + uint8_t number = data[1]; + uint32_t memoryAddress = ((data[2] & 0xff) << 16) | ((data[3] & 0xff) << 8) | (data[4] & 0xff); + _bau.memoryExtWriteIndication(priority, hopType, tsap, secCtrl, number, memoryAddress, data + 5); + break; + } + //case MemoryExtWriteResponse: + // _bau.memoryExtWriteAppLayerConfirm(priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3); // TODO return code + // break; case UserMemoryRead: { uint32_t address = ((data[1] & 0xf0) << 12) + (data[2] << 8) + data[3]; @@ -1137,6 +1217,18 @@ void ApplicationLayer::individualConfirm(AckType ack, HopCountType hopType, Prio case MemoryWrite: _bau.memoryWriteLocalConfirm(ack, priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3, status); break; + case MemoryExtRead: + _bau.memoryExtReadLocalConfirm(ack, priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), status); + break; + case MemoryExtReadResponse: + _bau.memoryExtReadResponseConfirm(ack, priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3, status); + break; + case MemoryExtWrite: + _bau.memoryExtWriteLocalConfirm(ack, priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3, status); + break; + case MemoryExtWriteResponse: + _bau.memoryExtWriteResponseConfirm(ack, priority, hopType, tsap, secCtrl, data[0] & 0x3f, getWord(data + 1), data + 3, status); + break; case UserMemoryRead: { uint32_t address = ((data[1] & 0xf0) << 12) + (data[2] << 8) + data[3]; diff --git a/src/knx/application_layer.h b/src/knx/application_layer.h index ec57467..4234716 100644 --- a/src/knx/application_layer.h +++ b/src/knx/application_layer.h @@ -125,6 +125,10 @@ class ApplicationLayer uint16_t memoryAddress); void memoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data); + void memoryExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, uint8_t number, + uint32_t memoryAddress, uint8_t* data); + void memoryExtWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, uint8_t number, + uint32_t memoryAddress, uint8_t *memoryData); void memoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data); void userMemoryReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, @@ -195,6 +199,8 @@ class ApplicationLayer void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl, bool status); void individualSend(AckType ack, HopCountType hopType, Priority priority, uint16_t asap, APDU& apdu, const SecurityControl& secCtrl); + uint16_t crc16Ccitt(uint8_t* input, uint16_t length); + uint16_t _savedAsapReadRequest; uint16_t _savedAsapWriteRequest; uint16_t _savedAsapResponse; diff --git a/src/knx/bau.cpp b/src/knx/bau.cpp index 78334cb..a74e7bf 100644 --- a/src/knx/bau.cpp +++ b/src/knx/bau.cpp @@ -191,6 +191,38 @@ void BusAccessUnit::memoryWriteIndication(Priority priority, HopCountType hopTyp { } +void BusAccessUnit::memoryExtReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, bool status) +{ +} + +void BusAccessUnit::memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress) +{ +} + +void BusAccessUnit::memoryExtReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status) +{ +} + +void BusAccessUnit::memoryExtReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data) +{ +} + +void BusAccessUnit::memoryExtWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status) +{ +} + +void BusAccessUnit::memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data) +{ +} + +void BusAccessUnit::memoryExtWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status) +{ +} + +void BusAccessUnit::memoryExtWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data) +{ +} + void BusAccessUnit::userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, bool status) { } diff --git a/src/knx/bau.h b/src/knx/bau.h index 31ce8a0..78b3580 100644 --- a/src/knx/bau.h +++ b/src/knx/bau.h @@ -92,6 +92,21 @@ class BusAccessUnit uint16_t memoryAddress, uint8_t* data, bool status); virtual void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data); + virtual void memoryExtReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, bool status); + virtual void memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress); + virtual void memoryExtReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data, bool status); + virtual void memoryExtReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data); + virtual void memoryExtWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data, bool status); + virtual void memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data); + virtual void memoryExtWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data, bool status); + virtual void memoryExtWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data); virtual void userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, bool status); virtual void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index ed7fb88..96c81df 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -252,6 +252,18 @@ void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, u _memory.toAbsolute(memoryAddress)); } +void BauSystemB::memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t * data) +{ + _memory.writeMemory(memoryAddress, number, data); + + _appLayer.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)); +} + void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel) { if (restartType == RestartType::BasicRestart) diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index 4caa17d..2a7e059 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -47,6 +47,10 @@ class BauSystemB : protected BusAccessUnit uint16_t memoryAddress, uint8_t* data) override; void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress) override; + void memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress, uint8_t* data) override; + void memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, + uint32_t memoryAddress) override; void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType) override; void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel) override; void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key) override; diff --git a/src/knx/knx_types.h b/src/knx/knx_types.h index 8559bc5..f92b60c 100644 --- a/src/knx/knx_types.h +++ b/src/knx/knx_types.h @@ -165,6 +165,10 @@ enum ApduType FunctionPropertyExtCommand = 0x1D4, FunctionPropertyExtState = 0x1D5, FunctionPropertyExtStateResponse = 0x1D6, + MemoryExtWrite = 0x1FB, + MemoryExtWriteResponse = 0x1FC, + MemoryExtRead = 0x1FD, + MemoryExtReadResponse = 0x1FE, MemoryRead = 0x200, MemoryResponse = 0x240, MemoryWrite = 0x280, diff --git a/src/knx/security_interface_object.cpp b/src/knx/security_interface_object.cpp index 1e109be..e1c7c33 100644 --- a/src/knx/security_interface_object.cpp +++ b/src/knx/security_interface_object.cpp @@ -81,8 +81,8 @@ SecurityInterfaceObject::SecurityInterfaceObject() resultData[0] = ReturnCodes::GenericError; resultLength = 1; }), - new DataProperty( PID_P2P_KEY_TABLE, true, PDT_GENERIC_20, 32, ReadLv3 | WriteLv0 ), // written by ETS - new DataProperty( PID_GRP_KEY_TABLE, true, PDT_GENERIC_18, 32, ReadLv3 | WriteLv0 ), // written by ETS + new DataProperty( PID_P2P_KEY_TABLE, true, PDT_GENERIC_20, 1, ReadLv3 | WriteLv0 ), // written by ETS + new DataProperty( PID_GRP_KEY_TABLE, true, PDT_GENERIC_18, 50, ReadLv3 | WriteLv0 ), // written by ETS new DataProperty( PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE, true, PDT_GENERIC_08, 32, ReadLv3 | WriteLv0 ), // written by ETS new FunctionProperty(this, PID_SECURITY_FAILURES_LOG, // Command Callback of PID_SECURITY_FAILURES_LOG @@ -154,9 +154,9 @@ SecurityInterfaceObject::SecurityInterfaceObject() new DataProperty( PID_SECURITY_REPORT, true, PDT_BITSET8, 1, ReadLv3 | WriteLv0, _secReport ), // Not implemented new DataProperty( PID_SECURITY_REPORT_CONTROL, true, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, _secReportCtrl ), // Not implemented new DataProperty( PID_SEQUENCE_NUMBER_SENDING, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 ), // Updated by our device accordingly - new DataProperty( PID_ZONE_KEY_TABLE, true, PDT_GENERIC_19, 32, ReadLv3 | WriteLv0 ), // written by ETS - new DataProperty( PID_GO_SECURITY_FLAGS, true, PDT_GENERIC_01, 32, ReadLv3 | WriteLv0 ), // written by ETS - new DataProperty( PID_ROLE_TABLE, true, PDT_GENERIC_01, 32, ReadLv3 | WriteLv0 ), // written by ETS + new DataProperty( PID_ZONE_KEY_TABLE, true, PDT_GENERIC_19, 1, ReadLv3 | WriteLv0 ), // written by ETS + new DataProperty( PID_GO_SECURITY_FLAGS, true, PDT_GENERIC_01, 256, ReadLv3 | WriteLv0 ), // written by ETS + new DataProperty( PID_ROLE_TABLE, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 ), // written by ETS new DataProperty( PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT), new DataProperty( PID_TOOL_SEQUENCE_NUMBER_SENDING, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 ) // Updated by our device accordingly (non-standardized!) };