mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	save work
This commit is contained in:
		
							parent
							
								
									c70e552991
								
							
						
					
					
						commit
						255ee7f1c4
					
				| @ -18,13 +18,21 @@ Bau091A::Bau091A(Platform& platform) | ||||
|       _cemiServer(*this) | ||||
| #endif | ||||
| { | ||||
|     _rtObjPrimary.property(PID_MEDIUM)->write((uint8_t) DptMedium::KNX_IP); | ||||
|     _rtObjSecondary.property(PID_MEDIUM)->write((uint8_t) DptMedium::KNX_TP1); | ||||
| 
 | ||||
|     _rtObjPrimary.property(PID_OBJECT_INDEX)->write((uint8_t) 1); | ||||
|     _rtObjSecondary.property(PID_OBJECT_INDEX)->write((uint8_t) 2); | ||||
| 
 | ||||
|     _netLayer.getEntity(0).dataLinkLayer(_dlLayerPrimary); | ||||
|     _netLayer.getEntity(1).dataLinkLayer(_dlLayerSecondary); | ||||
| 
 | ||||
| #ifdef USE_CEMI_SERVER | ||||
|     _cemiServer.dataLinkLayer(_dlLayerSecondary); // Secondary I/F is the important one!
 | ||||
|     _dlLayer.cemiServer(_cemiServer); | ||||
|     _memory.addSaveRestore(&_cemiServerObject); | ||||
| #endif | ||||
| 
 | ||||
|     _memory.addSaveRestore(&_ipParameters); | ||||
| 
 | ||||
|     // Set Mask Version in Device Object depending on the BAU
 | ||||
| @ -35,18 +43,17 @@ Bau091A::Bau091A(Platform& platform) | ||||
|     // See PID_IO_LIST
 | ||||
|     Property* prop = _deviceObj.property(PID_IO_LIST); | ||||
|     prop->write(1, (uint16_t) OT_DEVICE); | ||||
|     prop->write(2, (uint16_t) OT_ADDR_TABLE); | ||||
|     prop->write(3, (uint16_t) OT_ASSOC_TABLE); | ||||
|     prop->write(4, (uint16_t) OT_GRP_OBJ_TABLE); | ||||
|     prop->write(5, (uint16_t) OT_APPLICATION_PROG); | ||||
|     prop->write(6, (uint16_t) OT_IP_PARAMETER); | ||||
|     prop->write(2, (uint16_t) OT_ROUTER); | ||||
|     prop->write(3, (uint16_t) OT_ROUTER); | ||||
|     prop->write(3, (uint16_t) OT_APPLICATION_PROG); | ||||
|     prop->write(4, (uint16_t) OT_IP_PARAMETER); | ||||
| #if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER) | ||||
|     prop->write(7, (uint16_t) OT_SECURITY); | ||||
|     prop->write(8, (uint16_t) OT_CEMI_SERVER); | ||||
|     prop->write(5, (uint16_t) OT_SECURITY); | ||||
|     prop->write(6, (uint16_t) OT_CEMI_SERVER); | ||||
| #elif defined(USE_DATASECURE) | ||||
|     prop->write(7, (uint16_t) OT_SECURITY); | ||||
|     prop->write(5, (uint16_t) OT_SECURITY); | ||||
| #elif defined(USE_CEMI_SERVER) | ||||
|     prop->write(7, (uint16_t) OT_CEMI_SERVER); | ||||
|     prop->write(5, (uint16_t) OT_CEMI_SERVER); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| @ -57,9 +64,9 @@ InterfaceObject* Bau091A::getInterfaceObject(uint8_t idx) | ||||
|         case 0: | ||||
|             return &_deviceObj; | ||||
|         case 1: | ||||
|             return nullptr; // TODO: Router Object Primary IF
 | ||||
|             return &_rtObjPrimary; | ||||
|         case 2: | ||||
|             return nullptr; // TODO: Router Object Secondary IF
 | ||||
|             return &_rtObjSecondary; | ||||
|         case 3: | ||||
|             return &_appProgram; | ||||
|         case 4: | ||||
| @ -91,6 +98,8 @@ InterfaceObject* Bau091A::getInterfaceObject(ObjectType objectType, uint8_t obje | ||||
|     { | ||||
|         case OT_DEVICE: | ||||
|             return &_deviceObj; | ||||
|         case OT_ROUTER: | ||||
|             return objectInstance == 0 ? &_rtObjPrimary : &_rtObjSecondary; | ||||
|         case OT_APPLICATION_PROG: | ||||
|             return &_appProgram; | ||||
|         case OT_IP_PARAMETER: | ||||
|  | ||||
| @ -6,6 +6,8 @@ | ||||
| BauSystemBCoupler::BauSystemBCoupler(Platform& platform) : | ||||
|     BauSystemB(platform), | ||||
|     _platform(platform), | ||||
|     _rtObjPrimary(), | ||||
|     _rtObjSecondary(memory()), | ||||
| #ifdef USE_DATASECURE | ||||
|     _appLayer(_deviceObj, _secIfObj, *this), | ||||
| #else | ||||
|  | ||||
| @ -8,6 +8,8 @@ | ||||
| #include "group_object_table_object.h" | ||||
| #include "security_interface_object.h" | ||||
| #include "application_program_object.h" | ||||
| #include "router_object.h" | ||||
| #include "router_object_filtertable.h" | ||||
| #include "application_layer.h" | ||||
| #include "secure_application_layer.h" | ||||
| #include "transport_layer.h" | ||||
| @ -29,6 +31,9 @@ class BauSystemBCoupler : public BauSystemB | ||||
|     virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override; | ||||
| 
 | ||||
|     Platform& _platform; | ||||
|     RouterObject _rtObjPrimary; | ||||
|     RouterObjectFilterTable _rtObjSecondary; | ||||
| 
 | ||||
| #ifdef USE_DATASECURE | ||||
|     SecureApplicationLayer _appLayer; | ||||
|     SecurityInterfaceObject _secIfObj; | ||||
|  | ||||
| @ -228,3 +228,13 @@ enum EraseCode | ||||
|     ResetLinks = 0x06, | ||||
|     FactoryResetWithoutIA = 0x07 | ||||
| }; | ||||
| 
 | ||||
| enum DptMedium | ||||
| { | ||||
|     // DPT_Medium (20.1004), range 0-255
 | ||||
|     // All other values are reserved.
 | ||||
|     KNX_TP1 = 0x00, | ||||
|     KNX_PL110 = 0x01, | ||||
|     KNX_RF = 0x02, | ||||
|     KNX_IP = 0x05 | ||||
| }; | ||||
|  | ||||
| @ -15,11 +15,11 @@ void RouterObject::initializeProperties(size_t propertiesSize, Property** proper | ||||
|     Property* ownProperties[] = | ||||
|     { | ||||
|         new DataProperty( PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) OT_ROUTER ), | ||||
|         new DataProperty( PID_OBJECT_INDEX, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
 | ||||
|         new DataProperty( PID_MEDIUM_STATUS, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
 | ||||
|         new DataProperty( PID_MAX_APDU_LENGTH_ROUTER, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 254 ), | ||||
|         new DataProperty( PID_HOP_COUNT, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 5), | ||||
|         new DataProperty( PID_MEDIUM, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint16_t) 0) , // TODO
 | ||||
|         new DataProperty( PID_OBJECT_INDEX, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0 ), // Must be set by concrete BAUxxxx
 | ||||
|         new DataProperty( PID_MEDIUM_STATUS, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // For now: communication on medium is always possible
 | ||||
|         new DataProperty( PID_MAX_APDU_LENGTH_ROUTER, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 254 ), // For now: fixed size
 | ||||
|         new DataProperty( PID_HOP_COUNT, true, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t) 5), // TODO: Primary side: 5 for line coupler, 4 for backbone coupler, only exists if secondary is open medium without hop count
 | ||||
|         new DataProperty( PID_MEDIUM, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0 ), // Must be set by concrete BAUxxxx
 | ||||
|     }; | ||||
| 
 | ||||
|     uint8_t ownPropertiesCount = sizeof(ownProperties) / sizeof(Property*); | ||||
|  | ||||
| @ -8,6 +8,14 @@ | ||||
| #include "callback_property.h" | ||||
| #include "function_property.h" | ||||
| 
 | ||||
| enum RouteTableServices | ||||
| { | ||||
|     ClearRoutingTable = 0x01, // no info bytes
 | ||||
|     SetRoutingTable = 0x02,   // no info bytes
 | ||||
|     ClearGroupAddress = 0x03, // 4 bytes: start address and end address
 | ||||
|     SetGroupAddress = 0x04,   // 4 bytes: start address and end address
 | ||||
| }; | ||||
| 
 | ||||
| RouterObjectFilterTable::RouterObjectFilterTable(Memory& memory) | ||||
|     : _memory(memory) | ||||
| { | ||||
| @ -48,121 +56,24 @@ RouterObjectFilterTable::RouterObjectFilterTable(Memory& memory) | ||||
|         new FunctionProperty<RouterObjectFilterTable>(this, PID_ROUTETABLE_CONTROL, | ||||
|             // Command Callback of PID_ROUTETABLE_CONTROL
 | ||||
|             [](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void { | ||||
|                 if (length != 3) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::DataVoid; | ||||
|                     resultLength = 1; | ||||
|                     return; | ||||
|                 } | ||||
|                 uint8_t id = data[1]; | ||||
|                 uint8_t info = data[2]; | ||||
|                 if (id == 0 && info == 0) | ||||
|                 { | ||||
|                     //obj->clearFailureLog();
 | ||||
|                     resultData[0] = ReturnCodes::Success; | ||||
|                     resultData[1] = id; | ||||
|                     resultLength = 2; | ||||
|                     return; | ||||
|                 } | ||||
|                 resultData[0] = ReturnCodes::GenericError; | ||||
|                 resultLength = 1; | ||||
|                 obj->functionRouteTableControl(true, data, length, resultData, resultLength); | ||||
|             }, | ||||
|             // State Callback of PID_ROUTETABLE_CONTROL
 | ||||
|             [](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void { | ||||
|                 if (length != 3) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::DataVoid; | ||||
|                     resultLength = 1; | ||||
|                     return; | ||||
|                 } | ||||
|                 uint8_t id = data[1]; | ||||
|                 uint8_t info = data[2]; | ||||
| 
 | ||||
|                 // failure counters
 | ||||
|                 if (id == 0 && info == 0) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::Success; | ||||
|                     resultData[1] = id; | ||||
|                     resultData[2] = info; | ||||
|                     //obj->getFailureCounters(&resultData[3]); // Put 8 bytes in the buffer
 | ||||
|                     resultLength = 3 + 8; | ||||
|                     return; | ||||
|                 } | ||||
|                 // query latest failure by index
 | ||||
|                 else if(id == 1) | ||||
|                 { | ||||
|                     uint8_t maxBufferSize = resultLength; // Remember the maximum buffer size of the buffer that is provided to us
 | ||||
|                     uint8_t index = info; | ||||
|                     uint8_t numBytes = 0;//obj->getFromFailureLogByIndex(index, &resultData[2], maxBufferSize);
 | ||||
|                     if ( numBytes > 0) | ||||
|                     { | ||||
|                         resultData[0] = ReturnCodes::Success; | ||||
|                         resultData[1] = id; | ||||
|                         resultData[2] = index; | ||||
|                         resultLength += numBytes; | ||||
|                         resultLength = 3 + numBytes; | ||||
|                         return; | ||||
|                     } | ||||
|                     resultData[0] = ReturnCodes::DataVoid; | ||||
|                     resultData[1] = id; | ||||
|                     resultLength = 2; | ||||
|                     return; | ||||
|                 } | ||||
|                 resultData[0] = ReturnCodes::GenericError; | ||||
|                 resultLength = 1; | ||||
|                 obj->functionRouteTableControl(false, data, length, resultData, resultLength); | ||||
|             }), | ||||
| 
 | ||||
|         new DataProperty( PID_FILTER_TABLE_USE, false, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // TODO
 | ||||
| /*
 | ||||
| 
 | ||||
|         new FunctionProperty<RouterObjectFilterTable>(this, PID_RF_ENABLE_SBC, | ||||
|             // Command Callback of PID_RF_ENABLE_SBC
 | ||||
|             [](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void { | ||||
|                 uint8_t serviceId = data[1] & 0xff; | ||||
|                 if (serviceId != 0) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::InvalidCommand; | ||||
|                     resultLength = 1; | ||||
|                     return; | ||||
|                 } | ||||
|                 if (length == 3) | ||||
|                 { | ||||
|                     uint8_t mode = data[2]; | ||||
|                     if (mode > 1) | ||||
|                     { | ||||
|                         resultData[0] = ReturnCodes::DataVoid; | ||||
|                         resultLength = 1; | ||||
|                         return; | ||||
|                     } | ||||
|                     //obj->setSecurityMode(mode == 1);
 | ||||
|                     resultData[0] = ReturnCodes::Success; | ||||
|                     resultData[1] = serviceId; | ||||
|                     resultLength = 2; | ||||
|                     return; | ||||
|                 } | ||||
|                 resultData[0] = ReturnCodes::GenericError; | ||||
|                 resultLength = 1; | ||||
|                 obj->functionRfEnableSbc(true, data, length, resultData, resultLength); | ||||
|             }, | ||||
|             // State Callback of PID_RF_ENABLE_SBC
 | ||||
|             [](RouterObjectFilterTable* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void { | ||||
|                 uint8_t serviceId = data[1] & 0xff; | ||||
|                 if (serviceId != 0) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::InvalidCommand; | ||||
|                     resultLength = 1; | ||||
|                     return; | ||||
|                 } | ||||
|                 if (length == 2) | ||||
|                 { | ||||
|                     resultData[0] = ReturnCodes::Success; | ||||
|                     resultData[1] = serviceId; | ||||
|                     resultData[2] = 0;//obj->isSecurityModeEnabled() ? 1 : 0;
 | ||||
|                     resultLength = 3; | ||||
|                     return; | ||||
|                 } | ||||
|                 resultData[0] = ReturnCodes::GenericError; | ||||
|                 resultLength = 1; | ||||
|                 obj->functionRfEnableSbc(false, data, length, resultData, resultLength); | ||||
|             }), | ||||
| */ | ||||
|     }; | ||||
| 
 | ||||
|     RouterObject::initializeProperties(sizeof(properties), properties); | ||||
| @ -202,11 +113,103 @@ uint16_t RouterObjectFilterTable::saveSize() | ||||
|     return 1 + 4 + RouterObject::saveSize(); | ||||
| } | ||||
| 
 | ||||
| void RouterObjectFilterTable::functionRouteTableControl(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) | ||||
| { | ||||
|     bool isError = false; | ||||
|     RouteTableServices srvId = (RouteTableServices) data[1]; | ||||
| 
 | ||||
|     // Filter Table Realization Type 3
 | ||||
|     // The Filter Table Realisation Type 3 shall be organised as a memory mapped bit-field of
 | ||||
|     // 65536 bits and thus 8 192 octets. Each bit shall uniquely correspond to one Group Address.
 | ||||
|     // The full 16 bit KNX GA encoding range shall be supported.
 | ||||
|     //
 | ||||
|     // octet_address = GA_value div 8
 | ||||
|     // bit_position = GA_value mod 8
 | ||||
| 
 | ||||
|     // The CRC of the Memory Control Block Table Property is a CRC16-CCITT with the following
 | ||||
|     // parameters:
 | ||||
|     // Width = 16 bit
 | ||||
|     // Truncated polynomial = 1021h
 | ||||
|     // Initial value = FFFFh
 | ||||
|     // Input date is NOT reflected.
 | ||||
|     // Output CRC is NOT reflected.
 | ||||
|     // No XOR is performed on the output CRC.
 | ||||
|     // EXAMPLE The correct CRC16-CCITT of the string ‘123456789’ is E5CCh.
 | ||||
| 
 | ||||
|     if (isCommand) | ||||
|     { | ||||
|         switch(srvId) | ||||
|         { | ||||
|             case ClearRoutingTable: | ||||
|             case SetRoutingTable: | ||||
|             case ClearGroupAddress: | ||||
|             case SetGroupAddress: break; | ||||
|             default: isError = true; | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         switch(srvId) | ||||
|         { | ||||
|             case ClearRoutingTable: | ||||
|             case SetRoutingTable: | ||||
|             case ClearGroupAddress: | ||||
|             case SetGroupAddress: break; | ||||
|             default: isError = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (isError) | ||||
|     { | ||||
|         resultData[0] = ReturnCodes::GenericError; | ||||
|         resultData[1] = srvId; | ||||
|         resultLength = 2; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RouterObjectFilterTable::functionRfEnableSbc(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) | ||||
| { | ||||
|     if (isCommand) | ||||
|     { | ||||
|         _rfSbcRoutingEnabled = (data[0] == 1) ? true : false; | ||||
|     } | ||||
| 
 | ||||
|     resultData[0] = ReturnCodes::Success; | ||||
|     resultData[1] = _rfSbcRoutingEnabled ? 1 : 0; | ||||
|     resultLength = 2; | ||||
| } | ||||
| 
 | ||||
| bool RouterObjectFilterTable::isRfSbcRoutingEnabled() | ||||
| { | ||||
|     return _rfSbcRoutingEnabled; | ||||
| } | ||||
| 
 | ||||
| uint32_t RouterObjectFilterTable::tableReference() | ||||
| { | ||||
|     return (uint32_t)_memory.toRelative(_data); | ||||
| } | ||||
| 
 | ||||
| bool RouterObjectFilterTable::allocTable(uint32_t size, bool doFill, uint8_t fillByte) | ||||
| { | ||||
|     if (_data) | ||||
|     { | ||||
|         _memory.freeMemory(_data); | ||||
|         _data = 0; | ||||
|     } | ||||
| 
 | ||||
|     if (size == 0) | ||||
|         return true; | ||||
| 
 | ||||
|     _data = _memory.allocMemory(size); | ||||
|     if (!_data) | ||||
|         return false; | ||||
| 
 | ||||
|     if (doFill) | ||||
|         memset(_data, fillByte, size); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool RouterObjectFilterTable::isLoaded() | ||||
| { | ||||
|     return _state == LS_LOADED; | ||||
| @ -272,7 +275,9 @@ void RouterObjectFilterTable::loadEventLoading(const uint8_t* data) | ||||
|         case LE_UNLOAD: | ||||
|             loadState(LS_UNLOADED); | ||||
|             break; | ||||
|         case LE_ADDITIONAL_LOAD_CONTROLS: // Not supported here
 | ||||
|         case LE_ADDITIONAL_LOAD_CONTROLS: | ||||
|             additionalLoadControls(data); | ||||
|             break; | ||||
|         default: | ||||
|             loadState(LS_ERROR); | ||||
|             errorCode(E_GOT_UNDEF_LOAD_CMD); | ||||
| @ -292,6 +297,12 @@ void RouterObjectFilterTable::loadEventLoaded(const uint8_t* data) | ||||
|             break; | ||||
|         case LE_UNLOAD: | ||||
|             loadState(LS_UNLOADED); | ||||
|             //free nv memory
 | ||||
|             if (_data) | ||||
|             { | ||||
|                 _memory.freeMemory(_data); | ||||
|                 _data = 0; | ||||
|             } | ||||
|             break; | ||||
|         case LE_ADDITIONAL_LOAD_CONTROLS: | ||||
|             loadState(LS_ERROR); | ||||
| @ -322,6 +333,25 @@ void RouterObjectFilterTable::loadEventError(const uint8_t* data) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RouterObjectFilterTable::additionalLoadControls(const uint8_t* data) | ||||
| { | ||||
|     if (data[1] != 0x0B) // Data Relative Allocation
 | ||||
|     { | ||||
|         loadState(LS_ERROR); | ||||
|         errorCode(E_INVALID_OPCODE); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     size_t size = ((data[2] << 24) | (data[3] << 16) | (data[4] << 8) | data[5]); | ||||
|     bool doFill = data[6] == 0x1; | ||||
|     uint8_t fillByte = data[7]; | ||||
|     if (!allocTable(size, doFill, fillByte)) | ||||
|     { | ||||
|         loadState(LS_ERROR); | ||||
|         errorCode(E_MAX_TABLE_LENGTH_EXEEDED); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RouterObjectFilterTable::loadState(LoadState newState) | ||||
| { | ||||
|     if (newState == _state) | ||||
|  | ||||
| @ -12,6 +12,8 @@ class RouterObjectFilterTable: public RouterObject | ||||
| public: | ||||
|   RouterObjectFilterTable(Memory& memory); | ||||
| 
 | ||||
|   bool isRfSbcRoutingEnabled(); | ||||
| 
 | ||||
|   virtual void masterReset(EraseCode eraseCode, uint8_t channel) override; | ||||
| 
 | ||||
|   bool isLoaded(); | ||||
| @ -22,7 +24,12 @@ public: | ||||
|   uint16_t saveSize() override; | ||||
| 
 | ||||
| private: | ||||
|   // Function properties
 | ||||
|   void functionRouteTableControl(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); | ||||
|   void functionRfEnableSbc(bool isCommand, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength); | ||||
| 
 | ||||
|   uint32_t tableReference(); | ||||
|   bool allocTable(uint32_t size, bool doFill, uint8_t fillByte); | ||||
|   void errorCode(ErrorCode errorCode); | ||||
| 
 | ||||
|   void loadEvent(const uint8_t* data); | ||||
| @ -30,10 +37,12 @@ private: | ||||
|   void loadEventLoading(const uint8_t* data); | ||||
|   void loadEventLoaded(const uint8_t* data); | ||||
|   void loadEventError(const uint8_t* data); | ||||
|   void additionalLoadControls(const uint8_t* data); | ||||
| 
 | ||||
|   void loadState(LoadState newState); | ||||
|   LoadState _state = LS_UNLOADED; | ||||
| 
 | ||||
|   Memory& _memory; | ||||
|   uint8_t *_data = 0; | ||||
|   bool _rfSbcRoutingEnabled = false; | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user