diff --git a/src/knx/bau27B0.cpp b/src/knx/bau27B0.cpp index 3e66890..e1d0c53 100644 --- a/src/knx/bau27B0.cpp +++ b/src/knx/bau27B0.cpp @@ -10,9 +10,18 @@ using namespace std; Bau27B0::Bau27B0(Platform& platform) : BauSystemB(platform), _dlLayer(_deviceObj, _rfMediumObj, _addrTable, _netLayer, _platform) +#ifdef USE_USBIF + , _cemiServer(_tunnelInterface, *this) + , _tunnelInterface(_deviceObj, _cemiServer, _platform) +#endif { _netLayer.dataLinkLayer(_dlLayer); _memory.addSaveRestore(&_rfMediumObj); +#ifdef USE_USBIF + _cemiServer.dataLinkLayer(_dlLayer); + _dlLayer.cemiServer(_cemiServer); + _memory.addSaveRestore(&_cemiServerObject); +#endif // Set Mask Version in Device Object depending on the BAU uint16_t maskVersion; @@ -70,6 +79,18 @@ DataLinkLayer& Bau27B0::dataLinkLayer() return _dlLayer; } +void Bau27B0::enabled(bool value) +{ + ::BauSystemB::enabled(value); + _tunnelInterface.enabled(value); +} + +void Bau27B0::loop() +{ + ::BauSystemB::loop(); + _tunnelInterface.loop(); +} + void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint8_t* rfDoA, uint8_t* knxSerialNumber) { diff --git a/src/knx/bau27B0.h b/src/knx/bau27B0.h index 544409d..39bddf6 100644 --- a/src/knx/bau27B0.h +++ b/src/knx/bau27B0.h @@ -4,11 +4,18 @@ #include "rf_medium_object.h" #include "rf_physical_layer.h" #include "rf_data_link_layer.h" +#ifdef USE_USBIF +#include "usb_data_link_layer.h" +#include "cemi_server.h" +#include "cemi_server_object.h" +#endif class Bau27B0 : public BauSystemB { public: Bau27B0(Platform& platform); + void enabled(bool value); + void loop(); protected: InterfaceObject* getInterfaceObject(uint8_t idx); @@ -18,6 +25,11 @@ class Bau27B0 : public BauSystemB private: RfDataLinkLayer _dlLayer; RfMediumObject _rfMediumObj; +#ifdef USE_USBIF + CemiServer _cemiServer; + UsbDataLinkLayer _tunnelInterface; + CemiServerObject _cemiServerObject; +#endif uint8_t _descriptor[2] = {0x27, 0xB0}; #ifdef USE_USBIF diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index b8dd785..9840c0d 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -15,10 +15,6 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platfo _assocTable(platform), _groupObjTable(platform), _appProgram(platform), _platform(platform), _appLayer(_assocTable, *this), _transLayer(_appLayer, _addrTable), _netLayer(_transLayer) -#ifdef USE_USBIF - , _dlLayerUsb(_deviceObj, _addrTable, _netLayer, _platform), - _cemiServer(_dlLayerUsb, *this) -#endif { _appLayer.transportLayer(_transLayer); _transLayer.networkLayer(_netLayer); @@ -27,17 +23,11 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform), _addrTable(platfo _memory.addSaveRestore(&_addrTable); _memory.addSaveRestore(&_assocTable); _memory.addSaveRestore(&_groupObjTable); -#ifdef USE_USBIF - _memory.addSaveRestore(&_cemiServerObject); -#endif } void BauSystemB::loop() { dataLinkLayer().loop(); -#ifdef USE_USBIF - _dlLayerUsb.loop(); -#endif _transLayer.loop(); sendNextGroupTelegram(); nextRestartState(); @@ -51,9 +41,6 @@ bool BauSystemB::enabled() void BauSystemB::enabled(bool value) { dataLinkLayer().enabled(value); -#ifdef USE_USBIF - _dlLayerUsb.enabled(value); -#endif } void BauSystemB::sendNextGroupTelegram() diff --git a/src/knx/bau_systemB.h b/src/knx/bau_systemB.h index 6b65899..5ca0ff5 100644 --- a/src/knx/bau_systemB.h +++ b/src/knx/bau_systemB.h @@ -12,11 +12,6 @@ #include "tpuart_data_link_layer.h" #include "platform.h" #include "memory.h" -#ifdef USE_USBIF -#include "usb_data_link_layer.h" -#include "cemi_server.h" -#include "cemi_server_object.h" -#endif class BauSystemB : protected BusAccessUnit { @@ -93,9 +88,4 @@ class BauSystemB : protected BusAccessUnit bool _configured = true; RestartState _restartState = Idle; uint32_t _restartDelay = 0; -#ifdef USE_USBIF - UsbDataLinkLayer _dlLayerUsb; - CemiServer _cemiServer; - CemiServerObject _cemiServerObject; -#endif }; \ No newline at end of file diff --git a/src/knx/cemi_server.cpp b/src/knx/cemi_server.cpp index 2333525..301c22f 100644 --- a/src/knx/cemi_server.cpp +++ b/src/knx/cemi_server.cpp @@ -6,14 +6,79 @@ #include "bits.h" #include -CemiServer::CemiServer(UsbDataLinkLayer& dlLayer, BusAccessUnit& bau): - _dlLayer(dlLayer), +CemiServer::CemiServer(UsbDataLinkLayer& tunnelInterface, BusAccessUnit& bau): + _tunnelInterface(tunnelInterface), _bau(bau) { } -#pragma region DLL Callbacks +void CemiServer::dataLinkLayer(DataLinkLayer& layer) +{ + _dataLinkLayer = &layer; +} +void CemiServer::dataIndicationToTunnel(CemiFrame& frame) +{ + _tunnelInterface.sendCemiFrame(frame); +} + +void CemiServer::frameReceived(CemiFrame& frame) +{ + switch(frame.messageCode()) + { + case L_data_req: + { + // Send as indication to data link layer + frame.messageCode(L_data_ind); + _dataLinkLayer->dataIndicationFromTunnel(frame); + + // Send local reply to tunnel + frame.messageCode(L_data_con); + _tunnelInterface.sendCemiFrame(frame); + break; + } + + case M_PropRead_req: + { + break; + } + + case M_PropWrite_req: + { + break; + } + + case M_FuncPropCommand_req: + { + break; + } + + case M_FuncPropStateRead_req: + { + break; + } + + case M_Reset_req: + { + break; + } + + // we should not receive this: server -> client + case L_data_con: + case L_data_ind: + case M_PropInfo_ind: + case M_PropRead_con: + case M_PropWrite_con: + case M_FuncPropCommand_con: + //case M_FuncPropStateRead_con: // same value as M_FuncPropCommand_con + case M_Reset_ind: + default: + break; + } + _dataLinkLayer->dataIndicationFromTunnel(frame); +} + +/* void CemiServer::propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) { @@ -176,3 +241,5 @@ void CemiServer::individualConfirm(AckType ack, HopCountType hopType, Priority p break; } } + +*/ \ No newline at end of file diff --git a/src/knx/cemi_server.h b/src/knx/cemi_server.h index e829004..3e93b4f 100644 --- a/src/knx/cemi_server.h +++ b/src/knx/cemi_server.h @@ -5,6 +5,9 @@ class UsbDataLinkLayer; class BusAccessUnit; +class DataLinkLayer; +class CemiFrame; + /** * This is an implementation of the cEMI server as specified in @cite knx:3/6/3. * Overview on page 57. @@ -18,18 +21,22 @@ class CemiServer public: /** * The constructor. - * @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses. + * @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(UsbDataLinkLayer& dlLayer, BusAccessUnit& bau); + CemiServer(UsbDataLinkLayer& tunnelInterface, BusAccessUnit& bau); + + void dataLinkLayer(DataLinkLayer& layer); // from data link layer -#pragma region Data - Link - Layer - Callbacks - void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu); - void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status); -#pragma endregion + // Only L_Data service + void dataIndicationToTunnel(CemiFrame& frame); -#pragma region from bau + // From tunnel interface + void frameReceived(CemiFrame& frame); + + +/* 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, @@ -41,15 +48,16 @@ class CemiServer 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); -#pragma endregion - +*/ 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); - - UsbDataLinkLayer& _dlLayer; +*/ + DataLinkLayer* _dataLinkLayer; + UsbDataLinkLayer& _tunnelInterface; BusAccessUnit& _bau; }; diff --git a/src/knx/data_link_layer.cpp b/src/knx/data_link_layer.cpp index 92d34a6..14a3e9e 100644 --- a/src/knx/data_link_layer.cpp +++ b/src/knx/data_link_layer.cpp @@ -4,7 +4,7 @@ #include "platform.h" #include "device_object.h" #include "address_table_object.h" - +#include "cemi_server.h" DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer, Platform& platform) : @@ -12,6 +12,16 @@ DataLinkLayer::DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, { } +void DataLinkLayer::cemiServer(CemiServer& cemiServer) +{ + _cemiServer = &cemiServer; +} + +void DataLinkLayer::dataIndicationFromTunnel(CemiFrame& frame) +{ +} + + void DataLinkLayer::dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, Priority priority, NPDU& npdu) { // Normal data requests and broadcasts will always be transmitted as (domain) broadcast with domain address for open media (e.g. RF medium) diff --git a/src/knx/data_link_layer.h b/src/knx/data_link_layer.h index a08e524..5674ce6 100644 --- a/src/knx/data_link_layer.h +++ b/src/knx/data_link_layer.h @@ -5,6 +5,7 @@ #include "address_table_object.h" #include "knx_types.h" #include "network_layer.h" +#include "cemi_server.h" class DataLinkLayer { @@ -12,6 +13,10 @@ class DataLinkLayer DataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer, Platform& platform); + void cemiServer(CemiServer& cemiServer); + + void dataIndicationFromTunnel(CemiFrame& frame); + // from network layer void dataRequest(AckType ack, AddressType addrType, uint16_t destinationAddr, FrameFormat format, Priority priority, NPDU& npdu); @@ -30,4 +35,5 @@ class DataLinkLayer AddressTableObject& _groupAddressTable; NetworkLayer& _networkLayer; Platform& _platform; + CemiServer* _cemiServer; }; diff --git a/src/knx/usb_data_link_layer.cpp b/src/knx/usb_data_link_layer.cpp index 5592b2b..d9f84b1 100644 --- a/src/knx/usb_data_link_layer.cpp +++ b/src/knx/usb_data_link_layer.cpp @@ -15,7 +15,7 @@ Adafruit_USBD_HID usb_hid; // HID report descriptor using TinyUSB's template // Generic In Out with 64 bytes report (max) -uint8_t const desc_hid_report[] = +static uint8_t const desc_hid_report[] = { //TUD_HID_REPORT_DESC_GENERIC_INOUT(64) 0x06, 0xA0, 0xFF, // Usage Page (Vendor Defined 0xFFA0) @@ -235,10 +235,18 @@ void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8 void UsbDataLinkLayer::loop() { if (!_enabled) + { return; + } + + if (!isTxQueueEmpty()) + { + //loadNextTxFrame(); + //sendKnxHidReport(); + } } -bool UsbDataLinkLayer::sendFrame(CemiFrame& frame) +bool UsbDataLinkLayer::sendCemiFrame(CemiFrame& frame) { if (!_enabled) return false; @@ -248,18 +256,11 @@ bool UsbDataLinkLayer::sendFrame(CemiFrame& frame) // the L_Data.con for the previous L_Data.req. addFrameTxQueue(frame); - // TODO: For now L_data.req is confirmed immediately (L_Data.con) - // see 3.6.3 p.80: L_Data.con shall be generated AFTER transmission of the corresponsing frame - // RF sender will never generate L_Data.con with C=1 (Error), but only if the TX buffer overflows - // The RF sender cannot detect if the RF frame was transmitted successfully or not according to the spec. - dataConReceived(frame, true); - return true; } -UsbDataLinkLayer::UsbDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, - NetworkLayer& layer, Platform& platform) - : DataLinkLayer(devObj, addrTab, layer, platform) +UsbDataLinkLayer::UsbDataLinkLayer(DeviceObject& deviceObject, CemiServer& cemiServer, Platform& platform) + : _deviceObject(deviceObject), _cemiServer(cemiServer), _platform(platform) { } @@ -267,26 +268,14 @@ void UsbDataLinkLayer::frameBytesReceived(uint8_t* _buffer, uint16_t length) { // Prepare the cEMI frame CemiFrame frame(_buffer, length); -/* - frame.frameType(ExtendedFrame); // KNX RF uses only extended frame format - frame.priority(SystemPriority); // Not used in KNX RF - frame.ack(AckDontCare); // Not used in KNX RF - frame.systemBroadcast(systemBroadcast); // Mapped from flag AddrExtensionType (KNX serial(0) or Domain Address(1)) - frame.hopCount(hopCount); // Hop count from routing counter - frame.addressType(addressType); // Group address or individual address - frame.rfSerialOrDoA(&rfPacketBuf[4]); // Copy pointer to field Serial or Domain Address (check broadcast flag what it is exactly) - frame.rfInfo(rfPacketBuf[3]); // RF-info field (1 byte) - frame.rfLfn(lfn); // Data link layer frame number (LFN field) -*/ -/* - print(" len: "); - print(newLength); + print("cEMI USB RX len: "); + print(length); print(" data: "); - printHex(" data: ", _buffer, newLength); -*/ - frameRecieved(frame); + printHex(" data: ", _buffer, length); + + _cemiServer.frameReceived(frame); } void UsbDataLinkLayer::enabled(bool value) @@ -329,12 +318,11 @@ void UsbDataLinkLayer::addFrameTxQueue(CemiFrame& frame) tx_frame->data = new uint8_t[tx_frame->length]; tx_frame->next = NULL; -/* - print(" len: "); - print(totalLength); + print("cEMI USB TX len: "); + print(tx_frame->length); + + printHex(" data:", tx_frame->data, tx_frame->length); - printHex(" data:", tx_frame->data, totalLength); -*/ if (_tx_queue.back == NULL) { _tx_queue.front = _tx_queue.back = tx_frame; diff --git a/src/knx/usb_data_link_layer.h b/src/knx/usb_data_link_layer.h index eb1f1fb..0c1ede9 100644 --- a/src/knx/usb_data_link_layer.h +++ b/src/knx/usb_data_link_layer.h @@ -3,25 +3,26 @@ #include #include #include "data_link_layer.h" +#include "cemi_server.h" #define MAX_KNX_TELEGRAM_SIZE 263 extern Adafruit_USBD_HID usb_hid; -class UsbDataLinkLayer : public DataLinkLayer -{ - using DataLinkLayer::_deviceObject; - using DataLinkLayer::_groupAddressTable; - using DataLinkLayer::_platform; +class DeviceObject; +class Platform; +class UsbDataLinkLayer +{ public: - UsbDataLinkLayer(DeviceObject& devObj, AddressTableObject& addrTab, NetworkLayer& layer, - Platform& platform); + UsbDataLinkLayer(DeviceObject& deviceObject, CemiServer& cemiServer, Platform& platform); void loop(); void enabled(bool value); bool enabled() const; + bool sendCemiFrame(CemiFrame& frame); + private: bool _enabled = false; uint8_t _loopState = 0; @@ -43,10 +44,12 @@ class UsbDataLinkLayer : public DataLinkLayer _tx_queue_frame_t* back = NULL; } _tx_queue; + DeviceObject& _deviceObject; + CemiServer& _cemiServer; + Platform& _platform; void addFrameTxQueue(CemiFrame& frame); bool isTxQueueEmpty(); void loadNextTxFrame(uint8_t** sendBuffer, uint16_t* sendBufferLength); - bool sendFrame(CemiFrame& frame); void frameBytesReceived(uint8_t* buffer, uint16_t length); };