Save work

This commit is contained in:
nanosonde 2019-11-14 18:22:48 +01:00
parent afbc767165
commit 478f5c569a
23 changed files with 196 additions and 119 deletions

View File

@ -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) switch (id)
{ {

View File

@ -7,7 +7,7 @@ class ApplicationProgramObject : public TableObject
public: public:
ApplicationProgramObject(Platform& platform); ApplicationProgramObject(Platform& platform);
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); 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 propertySize(PropertyID id);
ObjectType objectType() { return OT_APPLICATION_PROG; } ObjectType objectType() { return OT_APPLICATION_PROG; }
uint8_t* data(uint32_t addr); uint8_t* data(uint32_t addr);

View File

@ -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, void BusAccessUnit::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
uint8_t **data, uint32_t &dataSize) 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)
{ {
} }

View File

@ -119,6 +119,11 @@ class BusAccessUnit
virtual void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber); 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, virtual void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
uint8_t **data, uint32_t &dataSize); 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);
}; };

View File

@ -209,16 +209,17 @@ void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountTy
void BauSystemB::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, 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) uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
{ {
uint32_t elementCount = numberOfElements;
InterfaceObject* obj = getInterfaceObject(objectIndex); InterfaceObject* obj = getInterfaceObject(objectIndex);
if(obj) if(obj)
obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements); obj->writeProperty((PropertyID)propertyId, startIndex, data, elementCount);
propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, numberOfElements, startIndex); propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, elementCount, startIndex);
} }
void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{ {
uint8_t size = 0; uint8_t size = 0;
uint32_t elementCount = numberOfElements; uint32_t elementCount = numberOfElements;
InterfaceObject* obj = getInterfaceObject(objectIndex); InterfaceObject* obj = getInterfaceObject(objectIndex);
if (obj) if (obj)
@ -393,7 +394,8 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
} }
void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, 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 size = 0;
uint32_t elementCount = numberOfElements; uint32_t elementCount = numberOfElements;
@ -414,5 +416,16 @@ void BauSystemB::propertyValueRead(ObjectType objectType, uint8_t objectInstance
} }
numberOfElements = elementCount; 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;
} }

View File

@ -29,6 +29,13 @@ class BauSystemB : protected BusAccessUnit
void addSaveRestore(SaveRestore* obj); void addSaveRestore(SaveRestore* obj);
bool restartRequest(uint16_t asap); 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: protected:
virtual DataLinkLayer& dataLinkLayer() = 0; virtual DataLinkLayer& dataLinkLayer() = 0;
virtual uint8_t* descriptor() = 0; virtual uint8_t* descriptor() = 0;
@ -61,8 +68,6 @@ class BauSystemB : protected BusAccessUnit
void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType, void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override; uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override;
void connectConfirm(uint16_t tsap) 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(uint8_t idx) = 0;
virtual InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance) = 0; virtual InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance) = 0;

View File

@ -1,15 +1,17 @@
#include "cemi_server.h" #include "cemi_server.h"
#include "cemi_frame.h" #include "cemi_frame.h"
#include "bau.h" #include "bau_systemB.h"
#include "usb_data_link_layer.h" #include "usb_data_link_layer.h"
#include "data_link_layer.h" #include "data_link_layer.h"
#include "string.h" #include "string.h"
#include "bits.h" #include "bits.h"
#include <stdio.h> #include <stdio.h>
CemiServer::CemiServer(BusAccessUnit& bau) CemiServer::CemiServer(BauSystemB& bau)
: _bau(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) void CemiServer::dataIndicationToTunnel(CemiFrame& frame)
{ {
println("L_data_ind: ");
_usbTunnelInterface.sendCemiFrame(frame); _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) void CemiServer::frameReceived(CemiFrame& frame)
{ {
switch(frame.messageCode()) switch(frame.messageCode())
{ {
case L_data_req: case L_data_req:
{ {
println("L_data_req: ");
// Send as indication to data link layer // Send as indication to data link layer
frame.messageCode(L_data_ind); frame.messageCode(L_data_ind);
_dataLinkLayer->dataIndicationFromTunnel(frame); _dataLinkLayer->dataIndicationFromTunnel(frame);
@ -89,7 +56,7 @@ void CemiServer::frameReceived(CemiFrame& frame)
case M_PropRead_req: case M_PropRead_req:
{ {
println("M_PropRead_req"); print("M_PropRead_req: ");
uint16_t objectType; uint16_t objectType;
popWord(objectType, &frame.data()[1]); popWord(objectType, &frame.data()[1]);
@ -100,11 +67,25 @@ void CemiServer::frameReceived(CemiFrame& frame)
uint8_t* data = nullptr; uint8_t* data = nullptr;
uint32_t dataSize = 0; 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! // propertyValueRead() allocates memory for the data! Needs to be deleted again!
_bau.propertyValueRead((ObjectType)objectType, objectInstance, propertyId, numberOfElements, startIndex, &data, dataSize); _bau.propertyValueRead((ObjectType)objectType, objectInstance, propertyId, numberOfElements, startIndex, &data, dataSize);
if (data && dataSize && numberOfElements) if (data && dataSize && numberOfElements)
{ {
printHex(" <- data: ", data, dataSize);
println("");
// Prepare positive response // Prepare positive response
uint8_t responseData[7 + dataSize]; uint8_t responseData[7 + dataSize];
memcpy(responseData, frame.data(), 7); memcpy(responseData, frame.data(), 7);
@ -123,6 +104,10 @@ void CemiServer::frameReceived(CemiFrame& frame)
memcpy(responseData, frame.data(), sizeof(responseData)); memcpy(responseData, frame.data(), sizeof(responseData));
responseData[7] = Void_DP; // Set cEMI error code responseData[7] = Void_DP; // Set cEMI error code
responseData[5] = 0; // Set Number of elements to zero responseData[5] = 0; // Set Number of elements to zero
printHex(" <- error: ", &responseData[7], 1);
println("");
CemiFrame responseFrame(responseData, sizeof(responseData)); CemiFrame responseFrame(responseData, sizeof(responseData));
responseFrame.messageCode(M_PropRead_con); responseFrame.messageCode(M_PropRead_con);
_usbTunnelInterface.sendCemiFrame(responseFrame); _usbTunnelInterface.sendCemiFrame(responseFrame);
@ -132,7 +117,7 @@ void CemiServer::frameReceived(CemiFrame& frame)
case M_PropWrite_req: case M_PropWrite_req:
{ {
println("M_PropWrite_req"); print("M_PropWrite_req: ");
uint16_t objectType; uint16_t objectType;
popWord(objectType, &frame.data()[1]); 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); uint16_t startIndex = frame.data()[6] | ((frame.data()[5]&0x0F)<<8);
uint8_t* requestData = &frame.data()[7]; uint8_t* requestData = &frame.data()[7];
uint32_t requestDataSize = frame.dataLength() - 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); print("ObjType: ");
if (propertyId != 0x34 && objectType!= OT_CEMI_SERVER) print(objectType, DEC);
{ print(" ObjInst: ");
numberOfElements = 0; 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) if (numberOfElements)
{ {
// Prepare positive response // Prepare positive response
uint8_t responseData[7]; uint8_t responseData[7];
memcpy(responseData, frame.data(), sizeof(responseData)); memcpy(responseData, frame.data(), sizeof(responseData));
println(" <- no error");
CemiFrame responseFrame(responseData, sizeof(responseData)); CemiFrame responseFrame(responseData, sizeof(responseData));
responseFrame.messageCode(M_PropWrite_con); responseFrame.messageCode(M_PropWrite_con);
_usbTunnelInterface.sendCemiFrame(responseFrame); _usbTunnelInterface.sendCemiFrame(responseFrame);
@ -166,6 +163,9 @@ numberOfElements = 0;
responseData[7] = Illegal_Command; // Set cEMI error code responseData[7] = Illegal_Command; // Set cEMI error code
responseData[5] = 0; // Set Number of elements to zero responseData[5] = 0; // Set Number of elements to zero
printHex(" <- error: ", &responseData[7], 1);
println("");
CemiFrame responseFrame(responseData, sizeof(responseData)); CemiFrame responseFrame(responseData, sizeof(responseData));
responseFrame.messageCode(M_PropWrite_con); responseFrame.messageCode(M_PropWrite_con);
_usbTunnelInterface.sendCemiFrame(responseFrame); _usbTunnelInterface.sendCemiFrame(responseFrame);

View File

@ -4,7 +4,7 @@
#include "knx_types.h" #include "knx_types.h"
#include "usb_data_link_layer.h" #include "usb_data_link_layer.h"
class BusAccessUnit; class BauSystemB;
class DataLinkLayer; class DataLinkLayer;
class CemiFrame; class CemiFrame;
@ -24,7 +24,7 @@ class CemiServer
* @param tunnelInterface The TunnelInterface of the KNX tunnel (e.g. USB or KNXNET/IP) * @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 * @param bau methods are called here depending of the content of the APDU
*/ */
CemiServer(BusAccessUnit& bau); CemiServer(BauSystemB& bau);
void dataLinkLayer(DataLinkLayer& layer); void dataLinkLayer(DataLinkLayer& layer);
@ -37,28 +37,8 @@ class CemiServer
void loop(); 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: 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; DataLinkLayer* _dataLinkLayer;
BusAccessUnit& _bau; BauSystemB& _bau;
UsbDataLinkLayer _usbTunnelInterface; UsbDataLinkLayer _usbTunnelInterface;
}; };

View File

@ -11,24 +11,28 @@ void CemiServerObject::readProperty(PropertyID propertyId, uint32_t start, uint3
break; break;
case PID_MEDIUM_TYPE: // PDT_BITSET16 case PID_MEDIUM_TYPE: // PDT_BITSET16
#if MEDIUM_TYPE==0 #if MEDIUM_TYPE==0
data[0] = 2; // TP1 supported pushWord(2, data); // TP1 supported
#elif MEDIUM_TYPE==2 #elif MEDIUM_TYPE==2
data[0] = 16; // RF supported pushWord(16, data); // RF supported
#elif MEDIUM_TYPE==5 #elif MEDIUM_TYPE==5
data[0] = 32; // IP supported pushWord(32, data); // IP supported
#endif #endif
break; break;
case PID_COMM_MODE: // PDT_ENUM8 case PID_COMM_MODE: // PDT_ENUM8
// See KNX spec. cEMI 3/6/3 p.110 // 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) data[0] = 0x00; // Only Data Link Layer mode supported and we do not allow switching (read-only)
break; break;
case PID_COMM_MODES_SUPPORTED:
data[0] = 0x00;
data[1] = 0x01;
break;
case PID_MEDIUM_AVAILABILITY: // PDT_BITSET16 case PID_MEDIUM_AVAILABILITY: // PDT_BITSET16
#if MEDIUM_TYPE==0 #if MEDIUM_TYPE==0
data[0] = 2; // TP1 active pushWord(2, data); // TP1 active
#elif MEDIUM_TYPE==2 #elif MEDIUM_TYPE==2
data[0] = 16; // RF active pushWord(16, data); // RF active
#elif MEDIUM_TYPE==5 #elif MEDIUM_TYPE==5
data[0] = 32; // IP active pushWord(32, data); // IP active
#endif #endif
break; break;
case PID_ADD_INFO_TYPES: // PDT_ENUM8[] 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) switch (id)
{ {
@ -51,6 +55,7 @@ void CemiServerObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data
break; break;
default: default:
count = 0;
break; break;
} }
} }
@ -64,6 +69,7 @@ uint8_t CemiServerObject::propertySize(PropertyID id)
case PID_OBJECT_TYPE: case PID_OBJECT_TYPE:
case PID_MEDIUM_TYPE: case PID_MEDIUM_TYPE:
case PID_MEDIUM_AVAILABILITY: case PID_MEDIUM_AVAILABILITY:
case PID_COMM_MODES_SUPPORTED:
return 2; return 2;
case PID_ADD_INFO_TYPES: case PID_ADD_INFO_TYPES:
return sizeof(_addInfoTypesTable); return sizeof(_addInfoTypesTable);
@ -88,6 +94,7 @@ static PropertyDescription _propertyDescriptions[] =
{ PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 }, { PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 },
{ PID_MEDIUM_TYPE, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 }, { PID_MEDIUM_TYPE, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 },
{ PID_COMM_MODE, false, PDT_ENUM8, 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_MEDIUM_AVAILABILITY, false, PDT_BITSET16, 1, ReadLv3 | WriteLv0 },
{ PID_ADD_INFO_TYPES, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 } { PID_ADD_INFO_TYPES, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 }
}; };

View File

@ -5,9 +5,9 @@
class CemiServerObject: public InterfaceObject class CemiServerObject: public InterfaceObject
{ {
public: public:
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data) override;
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) override;
uint8_t propertySize(PropertyID id); uint8_t propertySize(PropertyID id) override;
uint8_t* save(uint8_t* buffer); uint8_t* save(uint8_t* buffer);
uint8_t* restore(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); void readPropertyDescription(uint8_t propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);

View File

@ -52,12 +52,15 @@ void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t&
case PID_DEVICE_DESCRIPTOR: case PID_DEVICE_DESCRIPTOR:
pushWord(_maskVersion, data); pushWord(_maskVersion, data);
break; break;
case PID_RF_DOMAIN_ADDRESS_CEMI_SERVER:
pushByteArray((uint8_t*)_rfDomainAddress, 6, data);
break;
default: default:
count = 0; 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) switch (id)
{ {
@ -70,6 +73,20 @@ void DeviceObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data, ui
case PID_PROG_MODE: case PID_PROG_MODE:
_prgMode = data[0]; _prgMode = data[0];
break; 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; return 4;
case PID_SERIAL_NUMBER: case PID_SERIAL_NUMBER:
case PID_HARDWARE_TYPE: case PID_HARDWARE_TYPE:
case PID_RF_DOMAIN_ADDRESS_CEMI_SERVER:
return 6; return 6;
case PID_ORDER_INFO: case PID_ORDER_INFO:
return 10; return 10;
@ -105,6 +123,7 @@ uint8_t* DeviceObject::save(uint8_t* buffer)
buffer = pushByte(_deviceControl, buffer); buffer = pushByte(_deviceControl, buffer);
buffer = pushByte(_routingCount, buffer); buffer = pushByte(_routingCount, buffer);
buffer = pushWord(_ownAddress, buffer); buffer = pushWord(_ownAddress, buffer);
buffer = pushByteArray((uint8_t*)_rfDomainAddress, 6, buffer);
return buffer; return buffer;
} }
@ -113,6 +132,7 @@ uint8_t* DeviceObject::restore(uint8_t* buffer)
buffer = popByte(_deviceControl, buffer); buffer = popByte(_deviceControl, buffer);
buffer = popByte(_routingCount, buffer); buffer = popByte(_routingCount, buffer);
buffer = popWord(_ownAddress, buffer); buffer = popWord(_ownAddress, buffer);
buffer = popByteArray((uint8_t*)_rfDomainAddress, 6, buffer);
_prgMode = 0; _prgMode = 0;
return buffer; return buffer;
} }
@ -278,6 +298,16 @@ void DeviceObject::ifObj(const uint32_t* value)
_ifObjs = value; _ifObjs = value;
} }
uint8_t* DeviceObject::rfDomainAddress()
{
return _rfDomainAddress;
}
void DeviceObject::rfDomainAddress(uint8_t* value)
{
pushByteArray(value, 6, _rfDomainAddress);
}
static PropertyDescription _propertyDescriptions[] = static PropertyDescription _propertyDescriptions[] =
{ {
{ PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 }, { PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 },

View File

@ -6,7 +6,7 @@ class DeviceObject: public InterfaceObject
{ {
public: public:
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); 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 propertySize(PropertyID id);
uint8_t* save(uint8_t* buffer); uint8_t* save(uint8_t* buffer);
uint8_t* restore(uint8_t* buffer); uint8_t* restore(uint8_t* buffer);
@ -41,6 +41,8 @@ public:
void maxApduLength(uint16_t value); void maxApduLength(uint16_t value);
const uint32_t* ifObj(); const uint32_t* ifObj();
void ifObj(const uint32_t* value); void ifObj(const uint32_t* value);
uint8_t* rfDomainAddress();
void rfDomainAddress(uint8_t* value);
protected: protected:
uint8_t propertyCount(); uint8_t propertyCount();
PropertyDescription* propertyDescriptions(); PropertyDescription* propertyDescriptions();
@ -57,4 +59,5 @@ private:
uint16_t _maskVersion = 0x0000; uint16_t _maskVersion = 0x0000;
uint16_t _maxApduLength = 254; uint16_t _maxApduLength = 254;
const uint32_t* _ifObjs; const uint32_t* _ifObjs;
uint8_t _rfDomainAddress[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
}; };

View File

@ -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) 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; 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) uint8_t InterfaceObject::propertySize(PropertyID id)

View File

@ -84,11 +84,12 @@ class InterfaceObject : public SaveRestore
* *
* @param start (for properties with multiple values) at which element should we start * @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. * Gets the size of of property in bytes.
* *

View File

@ -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) 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++) for (uint8_t i = start; i < start + count; i++)
_friendlyName[i-1] = data[i - start]; _friendlyName[i-1] = data[i - start];
break; break;
default:
count = 0;
break;
} }
} }

View File

@ -9,7 +9,7 @@ class IpParameterObject : public InterfaceObject
public: public:
IpParameterObject(DeviceObject& deviceObject, Platform& platform); IpParameterObject(DeviceObject& deviceObject, Platform& platform);
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); 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 propertySize(PropertyID id);
ObjectType objectType() { return OT_IP_PARAMETER; } ObjectType objectType() { return OT_IP_PARAMETER; }

View File

@ -94,6 +94,7 @@ enum PropertyID
PID_DEVICE_ADDR = 58, PID_DEVICE_ADDR = 58,
PID_IO_LIST = 71, PID_IO_LIST = 71,
PID_HARDWARE_TYPE = 78, PID_HARDWARE_TYPE = 78,
PID_RF_DOMAIN_ADDRESS_CEMI_SERVER = 82,
PID_DEVICE_DESCRIPTOR = 83, PID_DEVICE_DESCRIPTOR = 83,
/** Properties in the RF Medium Object */ /** Properties in the RF Medium Object */
@ -144,7 +145,18 @@ enum PropertyID
PID_TIME_BASE = 55, PID_TIME_BASE = 55,
PID_TRANSP_ENABLE = 56, PID_TRANSP_ENABLE = 56,
PID_CLIENT_SNA = 57, 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 enum LoadState

View File

@ -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) switch (id)
{ {
@ -60,6 +60,7 @@ void RfMediumObject::writeProperty(PropertyID id, uint8_t start, uint8_t* data,
// Not supported yet // Not supported yet
break; break;
default: default:
count = 0;
break; break;
} }
} }

View File

@ -6,7 +6,7 @@ class RfMediumObject: public InterfaceObject
{ {
public: public:
void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); 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 propertySize(PropertyID id);
uint8_t* save(uint8_t* buffer); uint8_t* save(uint8_t* buffer);
uint8_t* restore(uint8_t* buffer); uint8_t* restore(uint8_t* buffer);

View File

@ -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) switch (id)
{ {

View File

@ -15,7 +15,7 @@ public:
*/ */
TableObject(Platform& platform); TableObject(Platform& platform);
virtual void readProperty(PropertyID id, uint32_t start, uint32_t& count, uint8_t* data); 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); virtual uint8_t propertySize(PropertyID id);
/** /**
* The destructor. * The destructor.

View File

@ -13,6 +13,9 @@
Adafruit_USBD_HID usb_hid; Adafruit_USBD_HID usb_hid;
uint16_t manufacturerId;
uint16_t maskVersion;
// HID report descriptor using TinyUSB's template // HID report descriptor using TinyUSB's template
// Generic In Out with 64 bytes report (max) // Generic In Out with 64 bytes report (max)
uint8_t const desc_hid_report[] = 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 case 0x02: // Host Device Descriptor Type 0
Serial1.println("Device Feature Get: Host Device Descriptor Type 0"); Serial1.println("Device Feature Get: Host Device Descriptor Type 0");
respDataSize = 2; respDataSize = 2;
data[12] = 0x00; // USB KNX Transfer Protocol Body: Feature Data pushWord(maskVersion, &data[12]); // USB KNX Transfer Protocol Body: Feature Data -> Mask version
data[13] = 0x00; // USB KNX Transfer Protocol Body: Feature Data
break; break;
case 0x03: // Bus connection status case 0x03: // Bus connection status
Serial1.println("Device Feature Get: 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 case 0x04: // KNX manufacturer code
Serial1.println("Device Feature Get: KNX manufacturer code"); Serial1.println("Device Feature Get: KNX manufacturer code");
respDataSize = 2; respDataSize = 2;
data[12] = 0x00; // USB KNX Transfer Protocol Body: Feature Data pushWord(manufacturerId, &data[12]); // USB KNX Transfer Protocol Body: Feature Data -> Manufacturer Code
data[13] = 0x00; // USB KNX Transfer Protocol Body: Feature Data -> Manufacturer Code
break; break;
case 0x05: // Active EMI type case 0x05: // Active EMI type
Serial1.println("Device Feature Get: 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 // class UsbDataLinkLayer
UsbDataLinkLayer::UsbDataLinkLayer(CemiServer& cemiServer) UsbDataLinkLayer::UsbDataLinkLayer(CemiServer& cemiServer,
uint16_t mId,
uint16_t mV)
: _cemiServer(cemiServer) : _cemiServer(cemiServer)
{ {
manufacturerId = mId;
maskVersion = mV;
} }
void UsbDataLinkLayer::loop() void UsbDataLinkLayer::loop()
@ -327,13 +332,13 @@ void UsbDataLinkLayer::loop()
uint8_t* buffer; uint8_t* buffer;
uint16_t length; uint16_t length;
loadNextTxFrame(&buffer, &length); loadNextTxFrame(&buffer, &length);
/*
print("cEMI USB TX len: "); print("cEMI USB TX len: ");
print(length); print(length);
print(" data: "); print(" data: ");
printHex(" data: ", buffer, length); printHex(" data: ", buffer, length);
*/
sendKnxTunnelHidReport(buffer, length); sendKnxTunnelHidReport(buffer, length);
} }
@ -345,13 +350,13 @@ void UsbDataLinkLayer::loop()
// Prepare the cEMI frame // Prepare the cEMI frame
CemiFrame frame(buffer, length); CemiFrame frame(buffer, length);
/*
print("cEMI USB RX len: "); print("cEMI USB RX len: ");
print(length); print(length);
print(" data: "); print(" data: ");
printHex(" data: ", buffer, length); printHex(" data: ", buffer, length);
*/
_cemiServer.frameReceived(frame); _cemiServer.frameReceived(frame);
} }
} }

View File

@ -10,7 +10,7 @@ class CemiFrame;
class UsbDataLinkLayer class UsbDataLinkLayer
{ {
public: public:
UsbDataLinkLayer(CemiServer& cemiServer); UsbDataLinkLayer(CemiServer& cemiServer, uint16_t manufacturerId, uint16_t maskVersion);
void loop(); void loop();
void enabled(bool value); void enabled(bool value);