diff --git a/src/knx/application_program_object.cpp b/src/knx/application_program_object.cpp index 7269ff4..24663a4 100644 --- a/src/knx/application_program_object.cpp +++ b/src/knx/application_program_object.cpp @@ -25,7 +25,7 @@ void ApplicationProgramObject::readProperty(PropertyID id, uint32_t start, uint3 } } -void ApplicationProgramObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void ApplicationProgramObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) { switch (id) { diff --git a/src/knx/application_program_object.h b/src/knx/application_program_object.h index 14c7f3f..ab101b3 100644 --- a/src/knx/application_program_object.h +++ b/src/knx/application_program_object.h @@ -7,7 +7,7 @@ class ApplicationProgramObject : public TableObject public: ApplicationProgramObject(Platform& platform); void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count); uint8_t propertySize(PropertyID id); ObjectType objectType() { return OT_APPLICATION_PROG; } uint8_t* data(uint32_t addr); diff --git a/src/knx/bau.cpp b/src/knx/bau.cpp index 3d32f28..f3db808 100644 --- a/src/knx/bau.cpp +++ b/src/knx/bau.cpp @@ -256,8 +256,15 @@ void BusAccessUnit::domainAddressSerialNumberReadIndication(Priority priority, H { } -void BusAccessUnit::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint32_t &numberOfElements, uint16_t startIndex, - uint8_t **data, uint32_t &dataSize) +void BusAccessUnit::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t **data, uint32_t &length) +{ +} + +void BusAccessUnit::propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t* data, uint32_t length) { } diff --git a/src/knx/bau.h b/src/knx/bau.h index 602a626..8d31879 100644 --- a/src/knx/bau.h +++ b/src/knx/bau.h @@ -119,6 +119,11 @@ class BusAccessUnit virtual void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber); - virtual void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint32_t &numberOfElements, uint16_t startIndex, - uint8_t **data, uint32_t &dataSize); + virtual void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t **data, uint32_t &length); + + virtual void propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t* data, uint32_t length); }; diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 543ffa8..16955c6 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -209,16 +209,17 @@ void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountTy void BauSystemB::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) { + uint32_t elementCount = numberOfElements; InterfaceObject* obj = getInterfaceObject(objectIndex); if(obj) - obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements); - propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, numberOfElements, startIndex); + obj->writeProperty((PropertyID)propertyId, startIndex, data, elementCount); + propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, elementCount, startIndex); } void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) { - uint8_t size = 0; + uint8_t size = 0; uint32_t elementCount = numberOfElements; InterfaceObject* obj = getInterfaceObject(objectIndex); if (obj) @@ -393,7 +394,8 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun } void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, - uint32_t &numberOfElements, uint16_t startIndex, uint8_t **data, uint32_t &dataSize) + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t **data, uint32_t &length) { uint32_t size = 0; uint32_t elementCount = numberOfElements; @@ -414,5 +416,16 @@ void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance } numberOfElements = elementCount; - dataSize = size; + length = size; +} + +void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t* data, uint32_t length) +{ + InterfaceObject* obj = getInterfaceObject(objectType, objectInstance); + if(obj) + obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements); + else + numberOfElements = 0; } diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index 24cf18c..57c20ee 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -28,6 +28,13 @@ class BauSystemB : protected BusAccessUnit void writeMemory(); void addSaveRestore(SaveRestore* obj); bool restartRequest(uint16_t asap); + + void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t **data, uint32_t &length) override; + void propertyValueWrite(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, + uint32_t &numberOfElements, uint16_t startIndex, + uint8_t* data, uint32_t length) override; protected: virtual DataLinkLayer& dataLinkLayer() = 0; @@ -61,8 +68,6 @@ class BauSystemB : protected BusAccessUnit void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType, uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override; void connectConfirm(uint16_t tsap) override; - void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint32_t &numberOfElements, uint16_t startIndex, - uint8_t **data, uint32_t &dataSize) override; virtual InterfaceObject* getInterfaceObject(uint8_t idx) = 0; virtual InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance) = 0; diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index f9cb7c4..6a94618 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -1,15 +1,17 @@ #include "cemi_server.h" #include "cemi_frame.h" -#include "bau.h" +#include "bau_systemB.h" #include "usb_data_link_layer.h" #include "data_link_layer.h" #include "string.h" #include "bits.h" #include -CemiServer::CemiServer(BusAccessUnit& bau) +CemiServer::CemiServer(BauSystemB& bau) : _bau(bau), - _usbTunnelInterface(*this) + _usbTunnelInterface(*this, + _bau.deviceObject().maskVersion(), + _bau.deviceObject().manufacturerId()) { } @@ -20,6 +22,7 @@ void CemiServer::dataLinkLayer(DataLinkLayer& layer) void CemiServer::dataIndicationToTunnel(CemiFrame& frame) { + println("L_data_ind: "); _usbTunnelInterface.sendCemiFrame(frame); } @@ -33,50 +36,14 @@ void CemiServer::localManagmentRequestFromTunnel(CemiFrame& frame) } */ -/* - uint8_t messageCode = data[11]; - switch(messageCode) - { - case 0xFC: // M_PropRead.req - { - data[11] = 0xFB; // M_PropRead.con - if (data[15] == 0x34) - { - data[18] = 00; // PID_COMM_MODE: 0: Data Link Layer - } - else - { - data[16] = 0; // Number of elements must be 0 if negative response - data[18] = 7; // Error code 7 (Void DP) - } - respDataSize = 1; - break; - } - case 0xF6: // M_PropWrite.req - { - data[11] = 0xF5; // M_PropWrite.con - if ((data[15] == 0x34) && (data[18] == 0x00)) - { - respDataSize = -1; - } - else - { - data[16] = 0; // Number of elements must be 0 if negative response - data[18] = 6; // Error code 6 (illegal command) - respDataSize = 0; - forceSend = true; - } - break; - } - } -*/ - void CemiServer::frameReceived(CemiFrame& frame) { switch(frame.messageCode()) { case L_data_req: { + println("L_data_req: "); + // Send as indication to data link layer frame.messageCode(L_data_ind); _dataLinkLayer->dataIndicationFromTunnel(frame); @@ -89,7 +56,7 @@ void CemiServer::frameReceived(CemiFrame& frame) case M_PropRead_req: { - println("M_PropRead_req"); + print("M_PropRead_req: "); uint16_t objectType; popWord(objectType, &frame.data()[1]); @@ -100,11 +67,25 @@ void CemiServer::frameReceived(CemiFrame& frame) uint8_t* data = nullptr; uint32_t dataSize = 0; + print("ObjType: "); + print(objectType, DEC); + print(" ObjInst: "); + print(objectInstance, DEC); + print(" PropId: "); + print(propertyId, DEC); + print(" NoE: "); + print(numberOfElements, DEC); + print(" startIdx: "); + print(startIndex, DEC); + // propertyValueRead() allocates memory for the data! Needs to be deleted again! _bau.propertyValueRead((ObjectType)objectType, objectInstance, propertyId, numberOfElements, startIndex, &data, dataSize); if (data && dataSize && numberOfElements) { + printHex(" <- data: ", data, dataSize); + println(""); + // Prepare positive response uint8_t responseData[7 + dataSize]; memcpy(responseData, frame.data(), 7); @@ -123,6 +104,10 @@ void CemiServer::frameReceived(CemiFrame& frame) memcpy(responseData, frame.data(), sizeof(responseData)); responseData[7] = Void_DP; // Set cEMI error code responseData[5] = 0; // Set Number of elements to zero + + printHex(" <- error: ", &responseData[7], 1); + println(""); + CemiFrame responseFrame(responseData, sizeof(responseData)); responseFrame.messageCode(M_PropRead_con); _usbTunnelInterface.sendCemiFrame(responseFrame); @@ -132,7 +117,7 @@ void CemiServer::frameReceived(CemiFrame& frame) case M_PropWrite_req: { - println("M_PropWrite_req"); + print("M_PropWrite_req: "); uint16_t objectType; popWord(objectType, &frame.data()[1]); @@ -142,18 +127,30 @@ void CemiServer::frameReceived(CemiFrame& frame) uint16_t startIndex = frame.data()[6] | ((frame.data()[5]&0x0F)<<8); uint8_t* requestData = &frame.data()[7]; uint32_t requestDataSize = frame.dataLength() - 7; - // propertyValueRead() allocates memory for the data! Needs to be deleted again! - //_bau.propertyValueRead((ObjectType)objectType, objectInstance, propertyId, numberOfElements, startIndex, data, dataSize); -if (propertyId != 0x34 && objectType!= OT_CEMI_SERVER) -{ -numberOfElements = 0; -} + + print("ObjType: "); + print(objectType, DEC); + print(" ObjInst: "); + print(objectInstance, DEC); + print(" PropId: "); + print(propertyId, DEC); + print(" NoE: "); + print(numberOfElements, DEC); + print(" startIdx: "); + print(startIndex, DEC); + + printHex(" -> data: ", requestData, requestDataSize); + + _bau.propertyValueWrite((ObjectType)objectType, objectInstance, propertyId, numberOfElements, startIndex, requestData, requestDataSize); + if (numberOfElements) { // Prepare positive response uint8_t responseData[7]; memcpy(responseData, frame.data(), sizeof(responseData)); - + + println(" <- no error"); + CemiFrame responseFrame(responseData, sizeof(responseData)); responseFrame.messageCode(M_PropWrite_con); _usbTunnelInterface.sendCemiFrame(responseFrame); @@ -166,6 +163,9 @@ numberOfElements = 0; responseData[7] = Illegal_Command; // Set cEMI error code responseData[5] = 0; // Set Number of elements to zero + printHex(" <- error: ", &responseData[7], 1); + println(""); + CemiFrame responseFrame(responseData, sizeof(responseData)); responseFrame.messageCode(M_PropWrite_con); _usbTunnelInterface.sendCemiFrame(responseFrame); diff --git a/src/knx/cemi_server.h b/src/knx/cemi_server.h index a1fda50..a78b95c 100644 --- a/src/knx/cemi_server.h +++ b/src/knx/cemi_server.h @@ -4,7 +4,7 @@ #include "knx_types.h" #include "usb_data_link_layer.h" -class BusAccessUnit; +class BauSystemB; class DataLinkLayer; class CemiFrame; @@ -24,7 +24,7 @@ class CemiServer * @param tunnelInterface The TunnelInterface of the KNX tunnel (e.g. USB or KNXNET/IP) * @param bau methods are called here depending of the content of the APDU */ - CemiServer(BusAccessUnit& bau); + CemiServer(BauSystemB& bau); void dataLinkLayer(DataLinkLayer& layer); @@ -37,28 +37,8 @@ class CemiServer void loop(); -/* - void propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, - uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex); - void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, - uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); - void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, - uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length); - void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, - uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex); - void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, - uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, - uint16_t maxNumberOfElements, uint8_t access); -*/ private: -/* - void propertyDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, - uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, - uint8_t length); - void individualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu); - void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status); -*/ DataLinkLayer* _dataLinkLayer; - BusAccessUnit& _bau; + BauSystemB& _bau; UsbDataLinkLayer _usbTunnelInterface; }; diff --git a/src/knx/cemi_server_object.cpp b/src/knx/cemi_server_object.cpp index 433172e..43a473d 100644 --- a/src/knx/cemi_server_object.cpp +++ b/src/knx/cemi_server_object.cpp @@ -11,24 +11,28 @@ void CemiServerObject::readProperty(PropertyID propertyId, uint32_t start, uint3 break; case PID_MEDIUM_TYPE: // PDT_BITSET16 #if MEDIUM_TYPE==0 - data[0] = 2; // TP1 supported + pushWord(2, data); // TP1 supported #elif MEDIUM_TYPE==2 - data[0] = 16; // RF supported + pushWord(16, data); // RF supported #elif MEDIUM_TYPE==5 - data[0] = 32; // IP supported + pushWord(32, data); // IP supported #endif break; case PID_COMM_MODE: // PDT_ENUM8 // See KNX spec. cEMI 3/6/3 p.110 data[0] = 0x00; // Only Data Link Layer mode supported and we do not allow switching (read-only) break; + case PID_COMM_MODES_SUPPORTED: + data[0] = 0x00; + data[1] = 0x01; + break; case PID_MEDIUM_AVAILABILITY: // PDT_BITSET16 #if MEDIUM_TYPE==0 - data[0] = 2; // TP1 active + pushWord(2, data); // TP1 active #elif MEDIUM_TYPE==2 - data[0] = 16; // RF active + pushWord(16, data); // RF active #elif MEDIUM_TYPE==5 - data[0] = 32; // IP active + pushWord(32, data); // IP active #endif break; case PID_ADD_INFO_TYPES: // PDT_ENUM8[] @@ -41,7 +45,7 @@ void CemiServerObject::readProperty(PropertyID propertyId, uint32_t start, uint3 } } -void CemiServerObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void CemiServerObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) { switch (id) { @@ -51,6 +55,7 @@ void CemiServerObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data break; default: + count = 0; break; } } @@ -64,6 +69,7 @@ uint8_t CemiServerObject::propertySize(PropertyID id) case PID_OBJECT_TYPE: case PID_MEDIUM_TYPE: case PID_MEDIUM_AVAILABILITY: + case PID_COMM_MODES_SUPPORTED: return 2; case PID_ADD_INFO_TYPES: return sizeof(_addInfoTypesTable); @@ -88,6 +94,7 @@ static PropertyDescription _propertyDescriptions[] = { PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 }, { PID_MEDIUM_TYPE, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 }, { PID_COMM_MODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 }, + { PID_COMM_MODES_SUPPORTED, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 }, { PID_MEDIUM_AVAILABILITY, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 }, { PID_ADD_INFO_TYPES, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 } }; diff --git a/src/knx/cemi_server_object.h b/src/knx/cemi_server_object.h index 4162980..18e22fe 100644 --- a/src/knx/cemi_server_object.h +++ b/src/knx/cemi_server_object.h @@ -5,9 +5,9 @@ class CemiServerObject: public InterfaceObject { public: - void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); - uint8_t propertySize(PropertyID id); + void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data) override; + void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) override; + uint8_t propertySize(PropertyID id) override; uint8_t* save(uint8_t* buffer); uint8_t* restore(uint8_t* buffer); void readPropertyDescription(uint8_t propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access); diff --git a/src/knx/device_object.cpp b/src/knx/device_object.cpp index e9d0905..1cace46 100644 --- a/src/knx/device_object.cpp +++ b/src/knx/device_object.cpp @@ -52,12 +52,15 @@ void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t& case PID_DEVICE_DESCRIPTOR: pushWord(_maskVersion, data); break; + case PID_RF_DOMAIN_ADDRESS_CEMI_SERVER: + pushByteArray((uint8_t*)_rfDomainAddress, 6, data); + break; default: count = 0; } } -void DeviceObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void DeviceObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) { switch (id) { @@ -70,6 +73,20 @@ void DeviceObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, ui case PID_PROG_MODE: _prgMode = data[0]; break; + case PID_RF_DOMAIN_ADDRESS_CEMI_SERVER: + //for (uint8_t i = start; i < start + count; i++) + //_rfDomainAddress[i-1] = data[i - start]; + memcpy(_rfDomainAddress, data, propertySize(PID_RF_DOMAIN_ADDRESS_CEMI_SERVER)); + break; + case PID_SUBNET_ADDR: + _ownAddress = (data[0] << 8) | (_ownAddress & 0xff); + break; + case PID_DEVICE_ADDR: + _ownAddress = data[0] | (_ownAddress & 0xff00); + break; + default: + count = 0; + break; } } @@ -93,6 +110,7 @@ uint8_t DeviceObject::propertySize(PropertyID id) return 4; case PID_SERIAL_NUMBER: case PID_HARDWARE_TYPE: + case PID_RF_DOMAIN_ADDRESS_CEMI_SERVER: return 6; case PID_ORDER_INFO: return 10; @@ -105,6 +123,7 @@ uint8_t* DeviceObject::save(uint8_t* buffer) buffer = pushByte(_deviceControl, buffer); buffer = pushByte(_routingCount, buffer); buffer = pushWord(_ownAddress, buffer); + buffer = pushByteArray((uint8_t*)_rfDomainAddress, 6, buffer); return buffer; } @@ -113,6 +132,7 @@ uint8_t* DeviceObject::restore(uint8_t* buffer) buffer = popByte(_deviceControl, buffer); buffer = popByte(_routingCount, buffer); buffer = popWord(_ownAddress, buffer); + buffer = popByteArray((uint8_t*)_rfDomainAddress, 6, buffer); _prgMode = 0; return buffer; } @@ -278,6 +298,16 @@ void DeviceObject::ifObj(const uint32_t* value) _ifObjs = value; } +uint8_t* DeviceObject::rfDomainAddress() +{ + return _rfDomainAddress; +} + +void DeviceObject::rfDomainAddress(uint8_t* value) +{ + pushByteArray(value, 6, _rfDomainAddress); +} + static PropertyDescription _propertyDescriptions[] = { { PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 }, diff --git a/src/knx/device_object.h b/src/knx/device_object.h index 8793075..fa66cf8 100644 --- a/src/knx/device_object.h +++ b/src/knx/device_object.h @@ -6,7 +6,7 @@ class DeviceObject: public InterfaceObject { public: void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count); uint8_t propertySize(PropertyID id); uint8_t* save(uint8_t* buffer); uint8_t* restore(uint8_t* buffer); @@ -41,6 +41,8 @@ public: void maxApduLength(uint16_t value); const uint32_t* ifObj(); void ifObj(const uint32_t* value); + uint8_t* rfDomainAddress(); + void rfDomainAddress(uint8_t* value); protected: uint8_t propertyCount(); PropertyDescription* propertyDescriptions(); @@ -57,4 +59,5 @@ private: uint16_t _maskVersion = 0x0000; uint16_t _maxApduLength = 254; const uint32_t* _ifObjs; + uint8_t _rfDomainAddress[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; }; \ No newline at end of file diff --git a/src/knx/interface_object.cpp b/src/knx/interface_object.cpp index f75eb8e..d51ace4 100644 --- a/src/knx/interface_object.cpp +++ b/src/knx/interface_object.cpp @@ -48,11 +48,16 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop void InterfaceObject::readProperty(PropertyID id, uint32_t start, uint32_t &count, uint8_t *data) { + // Set number of elements to zero as we are in the end of the call chain + // Nobody processed the property before. count = 0; } -void InterfaceObject::writeProperty(PropertyID id, uint8_t start, uint8_t *data, uint8_t count) +void InterfaceObject::writeProperty(PropertyID id, uint32_t start, uint8_t *data, uint32_t &count) { + // Set number of elements to zero as we are in the end of the call chain + // Nobody processed the property before. + count = 0; } uint8_t InterfaceObject::propertySize(PropertyID id) diff --git a/src/knx/interface_object.h b/src/knx/interface_object.h index 43bc17b..cc70121 100644 --- a/src/knx/interface_object.h +++ b/src/knx/interface_object.h @@ -84,11 +84,12 @@ class InterfaceObject : public SaveRestore * * @param start (for properties with multiple values) at which element should we start * - * @param count how many values should be written. + * @param[in, out] count how many values should be written. If there is a problem (e.g. property does not exist) + * this value is set to 0. * - * @param data The data that should be written. + * @param[in] data The data that should be written. */ - virtual void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + virtual void writeProperty(PropertyID id, uint32_t start, uint8_t *data, uint32_t &count); /** * Gets the size of of property in bytes. * diff --git a/src/knx/ip_parameter_object.cpp b/src/knx/ip_parameter_object.cpp index d35883e..4139e82 100644 --- a/src/knx/ip_parameter_object.cpp +++ b/src/knx/ip_parameter_object.cpp @@ -79,7 +79,7 @@ void IpParameterObject::readProperty(PropertyID propertyId, uint32_t start, uint } } -void IpParameterObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void IpParameterObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) { switch (id) { @@ -114,6 +114,9 @@ void IpParameterObject::writeProperty(PropertyID id, uint8_t start, uint8_t* dat for (uint8_t i = start; i < start + count; i++) _friendlyName[i-1] = data[i - start]; break; + default: + count = 0; + break; } } diff --git a/src/knx/ip_parameter_object.h b/src/knx/ip_parameter_object.h index 90cf93b..fc6fc00 100644 --- a/src/knx/ip_parameter_object.h +++ b/src/knx/ip_parameter_object.h @@ -9,7 +9,7 @@ class IpParameterObject : public InterfaceObject public: IpParameterObject(DeviceObject& deviceObject, Platform& platform); void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count); uint8_t propertySize(PropertyID id); ObjectType objectType() { return OT_IP_PARAMETER; } diff --git a/src/knx/property_types.h b/src/knx/property_types.h index 4ed89aa..5df562f 100644 --- a/src/knx/property_types.h +++ b/src/knx/property_types.h @@ -94,6 +94,7 @@ enum PropertyID PID_DEVICE_ADDR = 58, PID_IO_LIST = 71, PID_HARDWARE_TYPE = 78, + PID_RF_DOMAIN_ADDRESS_CEMI_SERVER = 82, PID_DEVICE_DESCRIPTOR = 83, /** Properties in the RF Medium Object */ @@ -144,7 +145,18 @@ enum PropertyID PID_TIME_BASE = 55, PID_TRANSP_ENABLE = 56, PID_CLIENT_SNA = 57, - PID_CLIENT_DEVICE_ADDRESS = 58 + PID_CLIENT_DEVICE_ADDRESS = 58, + PID_BIBAT_NEXTBLOCK = 59, + PID_RF_MODE_SELECT = 60, + PID_RF_MODE_SUPPORT = 61, + PID_RF_FILTERING_MODE_SELECT_CEMI_SERVER = 62, + PID_RF_FILTERING_MODE_SUPPORT_CEMI_SERVER = 63, + PID_COMM_MODES_SUPPORTED = 64, + PID_FILTERING_MODE_SUPPORT = 65, + PID_FILTERING_MODE_SELECT = 66, + PID_MAX_INTERFACE_APDU_LENGTH = 68, + PID_MAX_LOCAL_APDU_LENGTH = 69, + }; enum LoadState diff --git a/src/knx/rf_medium_object.cpp b/src/knx/rf_medium_object.cpp index 2e96d9d..0aaef2c 100644 --- a/src/knx/rf_medium_object.cpp +++ b/src/knx/rf_medium_object.cpp @@ -37,7 +37,7 @@ void RfMediumObject::readProperty(PropertyID propertyId, uint32_t start, uint32_ } } -void RfMediumObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void RfMediumObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count) { switch (id) { @@ -60,6 +60,7 @@ void RfMediumObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, // Not supported yet break; default: + count = 0; break; } } diff --git a/src/knx/rf_medium_object.h b/src/knx/rf_medium_object.h index 18bcab3..1d4c4a6 100644 --- a/src/knx/rf_medium_object.h +++ b/src/knx/rf_medium_object.h @@ -6,7 +6,7 @@ class RfMediumObject: public InterfaceObject { public: void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count); uint8_t propertySize(PropertyID id); uint8_t* save(uint8_t* buffer); uint8_t* restore(uint8_t* buffer); diff --git a/src/knx/table_object.cpp b/src/knx/table_object.cpp index c9aaa1b..5df4c32 100644 --- a/src/knx/table_object.cpp +++ b/src/knx/table_object.cpp @@ -29,7 +29,7 @@ void TableObject::readProperty(PropertyID id, uint32_t start, uint32_t& count, u } } -void TableObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count) +void TableObject::writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t &count) { switch (id) { diff --git a/src/knx/table_object.h b/src/knx/table_object.h index d30fb70..bcefd23 100644 --- a/src/knx/table_object.h +++ b/src/knx/table_object.h @@ -15,7 +15,7 @@ public: */ TableObject(Platform& platform); virtual void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); - virtual void writeProperty(PropertyID id, uint8_t start, uint8_t* data, uint8_t count); + virtual void writeProperty(PropertyID id, uint32_t start, uint8_t* data, uint32_t& count); virtual uint8_t propertySize(PropertyID id); /** * The destructor. diff --git a/src/knx/usb_data_link_layer.cpp b/src/knx/usb_data_link_layer.cpp index 7dcd879..09a7344 100644 --- a/src/knx/usb_data_link_layer.cpp +++ b/src/knx/usb_data_link_layer.cpp @@ -13,6 +13,9 @@ Adafruit_USBD_HID usb_hid; +uint16_t manufacturerId; +uint16_t maskVersion; + // HID report descriptor using TinyUSB's template // Generic In Out with 64 bytes report (max) uint8_t const desc_hid_report[] = @@ -145,8 +148,7 @@ static void handleBusAccessServerProtocol(const uint8_t* requestData, uint16_t p case 0x02: // Host Device Descriptor Type 0 Serial1.println("Device Feature Get: Host Device Descriptor Type 0"); respDataSize = 2; - data[12] = 0x00; // USB KNX Transfer Protocol Body: Feature Data - data[13] = 0x00; // USB KNX Transfer Protocol Body: Feature Data + pushWord(maskVersion, &data[12]); // USB KNX Transfer Protocol Body: Feature Data -> Mask version break; case 0x03: // Bus connection status Serial1.println("Device Feature Get: Bus connection status"); @@ -156,8 +158,7 @@ static void handleBusAccessServerProtocol(const uint8_t* requestData, uint16_t p case 0x04: // KNX manufacturer code Serial1.println("Device Feature Get: KNX manufacturer code"); respDataSize = 2; - data[12] = 0x00; // USB KNX Transfer Protocol Body: Feature Data - data[13] = 0x00; // USB KNX Transfer Protocol Body: Feature Data -> Manufacturer Code + pushWord(manufacturerId, &data[12]); // USB KNX Transfer Protocol Body: Feature Data -> Manufacturer Code break; case 0x05: // Active EMI type Serial1.println("Device Feature Get: Active EMI type"); @@ -310,9 +311,13 @@ void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8 // class UsbDataLinkLayer -UsbDataLinkLayer::UsbDataLinkLayer(CemiServer& cemiServer) +UsbDataLinkLayer::UsbDataLinkLayer(CemiServer& cemiServer, + uint16_t mId, + uint16_t mV) : _cemiServer(cemiServer) { + manufacturerId = mId; + maskVersion = mV; } void UsbDataLinkLayer::loop() @@ -327,13 +332,13 @@ void UsbDataLinkLayer::loop() uint8_t* buffer; uint16_t length; loadNextTxFrame(&buffer, &length); - +/* print("cEMI USB TX len: "); print(length); print(" data: "); printHex(" data: ", buffer, length); - +*/ sendKnxTunnelHidReport(buffer, length); } @@ -345,13 +350,13 @@ void UsbDataLinkLayer::loop() // Prepare the cEMI frame CemiFrame frame(buffer, length); - +/* print("cEMI USB RX len: "); print(length); print(" data: "); printHex(" data: ", buffer, length); - +*/ _cemiServer.frameReceived(frame); } } diff --git a/src/knx/usb_data_link_layer.h b/src/knx/usb_data_link_layer.h index 325ccf2..abf1e5b 100644 --- a/src/knx/usb_data_link_layer.h +++ b/src/knx/usb_data_link_layer.h @@ -10,7 +10,7 @@ class CemiFrame; class UsbDataLinkLayer { public: - UsbDataLinkLayer(CemiServer& cemiServer); + UsbDataLinkLayer(CemiServer& cemiServer, uint16_t manufacturerId, uint16_t maskVersion); void loop(); void enabled(bool value);