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
							
								
									ef004ced0d
								
							
						
					
					
						commit
						ff9426fdc3
					
				@ -42,7 +42,8 @@ add_executable(knx-linux
 | 
			
		||||
	../../src/knx/dpt.h
 | 
			
		||||
	../../src/knx/dptconvert.cpp
 | 
			
		||||
	../../src/knx/dptconvert.h
 | 
			
		||||
	../../src/knx/group_object.cpp 
 | 
			
		||||
        ../../src/knx/function_property.h
 | 
			
		||||
        ../../src/knx/group_object.cpp
 | 
			
		||||
	../../src/knx/group_object.h
 | 
			
		||||
	../../src/knx/group_object_table_object.cpp 
 | 
			
		||||
	../../src/knx/group_object_table_object.h
 | 
			
		||||
 | 
			
		||||
@ -552,6 +552,26 @@ void ApplicationLayer::propertyValueWriteRequest(AckType ack, Priority priority,
 | 
			
		||||
        startIndex, data, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationLayer::functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
 | 
			
		||||
                                                     uint8_t objectIndex, uint8_t propertyId, uint8_t returnCode, uint8_t* resultData, uint8_t resultLength)
 | 
			
		||||
{
 | 
			
		||||
    CemiFrame frame(3 + resultLength + 1);
 | 
			
		||||
    APDU& apdu = frame.apdu();
 | 
			
		||||
    apdu.type(FunctionPropertyStateResponse);
 | 
			
		||||
    uint8_t* data = apdu.data() + 1;
 | 
			
		||||
 | 
			
		||||
    data[0] = objectIndex;
 | 
			
		||||
    data[1] = propertyId;
 | 
			
		||||
    data[2] = returnCode;
 | 
			
		||||
    if (resultLength > 0)
 | 
			
		||||
        memcpy(&data[3], resultData, resultLength);
 | 
			
		||||
 | 
			
		||||
    if (asap == _connectedTsap)
 | 
			
		||||
        dataConnectedRequest(asap, priority, apdu);
 | 
			
		||||
    else
 | 
			
		||||
        dataIndividualRequest(ack, hopType, priority, asap, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ApplicationLayer::propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
 | 
			
		||||
    uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ class ApplicationLayer
 | 
			
		||||
     * 
 | 
			
		||||
     * @param hopType Should routing be endless or should the NetworkLayer::hopCount be used? See also ::HopCountType.
 | 
			
		||||
     */
 | 
			
		||||
    void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    virtual void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    /**
 | 
			
		||||
     * Report the status of an APDU that we sent via multicast communiation back to us. See 3.2 of @cite knx:3/3/4. 
 | 
			
		||||
     * See also ApplicationLayer::dataGroupConfirm and TransportLayer::dataGroupRequest. This method is called by 
 | 
			
		||||
@ -63,20 +63,20 @@ class ApplicationLayer
 | 
			
		||||
     * 
 | 
			
		||||
     * @param ack Did we want a DataLinkLayer acknowledgement? See ::AckType.
 | 
			
		||||
     */
 | 
			
		||||
    void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
 | 
			
		||||
    virtual void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
 | 
			
		||||
                          APDU& apdu, bool status);
 | 
			
		||||
    void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    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);
 | 
			
		||||
    void connectIndication(uint16_t tsap);
 | 
			
		||||
    void connectConfirm(uint16_t destination, uint16_t tsap, bool status);
 | 
			
		||||
    void disconnectIndication(uint16_t tsap);
 | 
			
		||||
    void disconnectConfirm(Priority priority, uint16_t tsap, bool status);
 | 
			
		||||
    void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    void dataConnectedConfirm(uint16_t tsap);
 | 
			
		||||
    virtual void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    virtual void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    virtual void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    virtual void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    virtual void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    virtual void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
 | 
			
		||||
    virtual void connectIndication(uint16_t tsap);
 | 
			
		||||
    virtual void connectConfirm(uint16_t destination, uint16_t tsap, bool status);
 | 
			
		||||
    virtual void disconnectIndication(uint16_t tsap);
 | 
			
		||||
    virtual void disconnectConfirm(Priority priority, uint16_t tsap, bool status);
 | 
			
		||||
    virtual void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    virtual void dataConnectedConfirm(uint16_t tsap);
 | 
			
		||||
#pragma endregion
 | 
			
		||||
 | 
			
		||||
#pragma region from bau
 | 
			
		||||
@ -105,6 +105,8 @@ class ApplicationLayer
 | 
			
		||||
                                   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 functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
 | 
			
		||||
                                       uint8_t objectIndex, uint8_t propertyId, uint8_t returnCode, 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,
 | 
			
		||||
 | 
			
		||||
@ -240,6 +240,34 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop
 | 
			
		||||
        startIndex, data, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
 | 
			
		||||
                                                   uint8_t propertyId, uint8_t* data, uint8_t length)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t returnCode = 0xFF;
 | 
			
		||||
    uint8_t resultLength = 0;
 | 
			
		||||
    uint8_t resultData[32];
 | 
			
		||||
 | 
			
		||||
    InterfaceObject* obj = getInterfaceObject(objectIndex);
 | 
			
		||||
    if(obj)
 | 
			
		||||
        returnCode = obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
 | 
			
		||||
 | 
			
		||||
    _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, returnCode, resultData, resultLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
 | 
			
		||||
                                                 uint8_t propertyId, uint8_t* data, uint8_t length)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t returnCode = 0xFF;
 | 
			
		||||
    uint8_t resultLength = 0;
 | 
			
		||||
    uint8_t resultData[32];
 | 
			
		||||
 | 
			
		||||
    InterfaceObject* obj = getInterfaceObject(objectIndex);
 | 
			
		||||
    if(obj)
 | 
			
		||||
        returnCode = obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
 | 
			
		||||
 | 
			
		||||
    _appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, returnCode, resultData, resultLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BauSystemB::individualAddressReadIndication(HopCountType hopType)
 | 
			
		||||
{
 | 
			
		||||
    if (_deviceObj.progMode())
 | 
			
		||||
@ -433,4 +461,4 @@ void BauSystemB::propertyValueWrite(ObjectType objectType, uint8_t objectInstanc
 | 
			
		||||
Memory& BauSystemB::memory()
 | 
			
		||||
{
 | 
			
		||||
    return _memory;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,10 @@ class BauSystemB : protected BusAccessUnit
 | 
			
		||||
                                      uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) override;
 | 
			
		||||
    void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
 | 
			
		||||
                                     uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override;
 | 
			
		||||
    void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
 | 
			
		||||
                                           uint8_t propertyId, uint8_t* data, uint8_t length);
 | 
			
		||||
    void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
 | 
			
		||||
                                         uint8_t propertyId, uint8_t* data, uint8_t length);
 | 
			
		||||
    void individualAddressReadIndication(HopCountType hopType) override;
 | 
			
		||||
    void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override;
 | 
			
		||||
    void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								src/knx/function_property.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/knx/function_property.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "property.h"
 | 
			
		||||
 | 
			
		||||
class InterfaceObject;
 | 
			
		||||
 | 
			
		||||
template <class T> class FunctionProperty : public Property
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    FunctionProperty(T* io, PropertyID id, uint8_t access,
 | 
			
		||||
                     uint8_t (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&),
 | 
			
		||||
                     uint8_t (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&))
 | 
			
		||||
        : Property(id, false, PDT_FUNCTION, 1, access), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback)
 | 
			
		||||
        /* max_elements is set to 1, see 3.3.7 Application Layer p.68 */
 | 
			
		||||
    {}
 | 
			
		||||
    
 | 
			
		||||
    virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) override
 | 
			
		||||
    {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual uint8_t command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override
 | 
			
		||||
    {
 | 
			
		||||
        if (length == 0 || _commandCallback == nullptr )
 | 
			
		||||
            return 0xFF;
 | 
			
		||||
 | 
			
		||||
        return _commandCallback(_interfaceObject, data, length, resultData, resultLength);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual uint8_t state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) override
 | 
			
		||||
    {
 | 
			
		||||
        if (length == 0 || _stateCallback == nullptr )
 | 
			
		||||
            return 0xFF;
 | 
			
		||||
 | 
			
		||||
        return _stateCallback(_interfaceObject, data, length, resultData, resultLength);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    T* _interfaceObject = nullptr;
 | 
			
		||||
    uint8_t (*_commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr;
 | 
			
		||||
    uint8_t (*_stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&) = nullptr;
 | 
			
		||||
};
 | 
			
		||||
@ -137,6 +137,28 @@ uint8_t InterfaceObject::propertySize(PropertyID id)
 | 
			
		||||
    return prop->ElementSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t InterfaceObject::command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
 | 
			
		||||
{
 | 
			
		||||
    Property* prop = property(id);
 | 
			
		||||
    if (prop == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        return 0xFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return prop->command(data, length, resultData, resultLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength)
 | 
			
		||||
{
 | 
			
		||||
    Property* prop = property(id);
 | 
			
		||||
    if (prop == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        return 0xFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return prop->state(data, length, resultData, resultLength);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t InterfaceObject::propertyDescriptionCount()
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,9 @@ enum ObjectType
 | 
			
		||||
    /** File Server Object */
 | 
			
		||||
    OT_FILE_SERVER = 13,
 | 
			
		||||
 | 
			
		||||
    /** Security Interface Object */
 | 
			
		||||
    OT_SECURITY = 17,
 | 
			
		||||
 | 
			
		||||
    /** RF Medium Object */
 | 
			
		||||
    OT_RF_MEDIUM = 19
 | 
			
		||||
};
 | 
			
		||||
@ -98,6 +101,34 @@ class InterfaceObject : public SaveRestore
 | 
			
		||||
     * @returns the size in byte or 0 if the interface object does not have the property
 | 
			
		||||
     */
 | 
			
		||||
    virtual uint8_t propertySize(PropertyID id);
 | 
			
		||||
    /**
 | 
			
		||||
     * Call command of a function property of the interface object. Property type must be PDT_FUNCTION
 | 
			
		||||
     *
 | 
			
		||||
     * @param id id of the property to call
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] length The size of the data buffer
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] data The argument data for the function
 | 
			
		||||
     *
 | 
			
		||||
     * @param[out] resultLength The size of the result data buffer
 | 
			
		||||
     *
 | 
			
		||||
     * @param[out] resultData The result data for the function
 | 
			
		||||
     */
 | 
			
		||||
    virtual uint8_t command(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength);
 | 
			
		||||
    /**
 | 
			
		||||
     * Get state of a function property of the interface object. Property type must be PDT_FUNCTION
 | 
			
		||||
     *
 | 
			
		||||
     * @param id id of the property to call
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] length The size of the data buffer
 | 
			
		||||
     *
 | 
			
		||||
     * @param[in] data The argument data for the function
 | 
			
		||||
     *
 | 
			
		||||
     * @param[out] resultLength The size of the result data buffer
 | 
			
		||||
     *
 | 
			
		||||
     * @param[out] resultData The result data for the function
 | 
			
		||||
     */
 | 
			
		||||
    virtual uint8_t state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength);
 | 
			
		||||
    /**
 | 
			
		||||
     * Read the Description of a property of the interface object. The output parameters are only valid if nuberOfElements is not zero.
 | 
			
		||||
     * 
 | 
			
		||||
@ -170,4 +201,4 @@ class InterfaceObject : public SaveRestore
 | 
			
		||||
 | 
			
		||||
    Property** _properties = nullptr;
 | 
			
		||||
    uint8_t _propertyCount = 0;
 | 
			
		||||
};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -138,6 +138,9 @@ enum ApduType
 | 
			
		||||
    UserMemoryWrite = 0x2C2,
 | 
			
		||||
    UserManufacturerInfoRead = 0x2C5,
 | 
			
		||||
    UserManufacturerInfoResponse = 0x2C6,
 | 
			
		||||
    FunctionPropertyCommand = 0x2C7,
 | 
			
		||||
    FunctionPropertyState = 0x2C8,
 | 
			
		||||
    FunctionPropertyStateResponse = 0x2C9,
 | 
			
		||||
    DeviceDescriptorRead = 0x300,
 | 
			
		||||
    DeviceDescriptorResponse = 0x340,
 | 
			
		||||
    Restart = 0x380,
 | 
			
		||||
 | 
			
		||||
@ -203,3 +203,23 @@ uint8_t Property::write(uint16_t position, uint16_t value)
 | 
			
		||||
    pushWord(value, data);
 | 
			
		||||
    return write(position, 1, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t Property::command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
 | 
			
		||||
{
 | 
			
		||||
    (void)data;
 | 
			
		||||
    (void)length;
 | 
			
		||||
    (void)resultData;
 | 
			
		||||
    resultLength = 0;
 | 
			
		||||
 | 
			
		||||
    return 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t Property::state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength)
 | 
			
		||||
{
 | 
			
		||||
    (void)data;
 | 
			
		||||
    (void)length;
 | 
			
		||||
    (void)resultData;
 | 
			
		||||
    resultLength = 0;
 | 
			
		||||
 | 
			
		||||
    return 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -238,6 +238,8 @@ class Property : public SaveRestore
 | 
			
		||||
    uint8_t ElementSize() const;
 | 
			
		||||
    virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const = 0;
 | 
			
		||||
    virtual uint8_t write(uint16_t start, uint8_t count, const uint8_t* data) = 0;
 | 
			
		||||
    virtual uint8_t command(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength);
 | 
			
		||||
    virtual uint8_t state(uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength);
 | 
			
		||||
    uint8_t read(uint8_t& value) const;
 | 
			
		||||
    uint8_t read(uint16_t& value) const;
 | 
			
		||||
    uint8_t read(uint32_t& value) const;
 | 
			
		||||
@ -253,4 +255,4 @@ class Property : public SaveRestore
 | 
			
		||||
    PropertyDataType _type;
 | 
			
		||||
    uint16_t _maxElements;
 | 
			
		||||
    uint8_t _access;
 | 
			
		||||
};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -23,19 +23,49 @@ SecureApplicationLayer::SecureApplicationLayer(AssociationTableObject& assocTabl
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* from transport layer */
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataGroupIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Decrypt secure APDU
 | 
			
		||||
 | 
			
		||||
        // Process decrypted inner APDU
 | 
			
		||||
        ApplicationLayer::dataGroupIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataGroupIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority,  uint16_t tsap, APDU& apdu, bool status)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataGroupConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Decrypt secure APDU
 | 
			
		||||
 | 
			
		||||
        // Process decrypted inner APDU
 | 
			
		||||
        ApplicationLayer::dataGroupConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataGroupConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataBroadcastIndication(hopType, priority, source, apdu);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Secure APDU is not allowed in Broadcast
 | 
			
		||||
        println("Secure APDU in Broadcast not allowed!");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataBroadcastIndication(hopType, priority, source, apdu);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status)
 | 
			
		||||
@ -45,7 +75,15 @@ void SecureApplicationLayer::dataBroadcastConfirm(AckType ack, HopCountType hopT
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataSystemBroadcastIndication(hopType, priority, source, apdu);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Secure APDU is not allowed in Broadcast
 | 
			
		||||
        println("Secure APDU in SystemBroadcast not allowed!");
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataSystemBroadcastIndication(hopType, priority, source, apdu);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status)
 | 
			
		||||
@ -55,12 +93,32 @@ void SecureApplicationLayer::dataSystemBroadcastConfirm(HopCountType hopType, Pr
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataIndividualIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Decrypt secure APDU
 | 
			
		||||
 | 
			
		||||
        // Process decrypted inner APDU
 | 
			
		||||
        ApplicationLayer::dataIndividualIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataIndividualIndication(hopType, priority, tsap, apdu);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataIndividualConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Decrypt secure APDU
 | 
			
		||||
 | 
			
		||||
        // Process decrypted inner APDU
 | 
			
		||||
        ApplicationLayer::dataIndividualConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataIndividualConfirm(ack, hopType, priority, tsap, apdu, status);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::connectIndication(uint16_t tsap)
 | 
			
		||||
@ -85,7 +143,40 @@ void SecureApplicationLayer::disconnectConfirm(Priority priority, uint16_t tsap,
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataConnectedIndication(priority, tsap, apdu);
 | 
			
		||||
    if (apdu.type() == SecureService)
 | 
			
		||||
    {
 | 
			
		||||
        // Decrypt secure APDU
 | 
			
		||||
 | 
			
		||||
        println("Secure APDU: ");
 | 
			
		||||
        apdu.printPDU();
 | 
			
		||||
 | 
			
		||||
        uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac)
 | 
			
		||||
        CemiFrame plainFrame(plainApduLength);
 | 
			
		||||
 | 
			
		||||
        uint16_t srcAddress = apdu.frame().sourceAddress();
 | 
			
		||||
        uint16_t dstAddress = apdu.frame().destinationAddress();
 | 
			
		||||
        uint8_t tpci = apdu.frame().data()[TPDU_LPDU_DIFF]; // FIXME: when cEMI class is refactored, there might be additional info fields in cEMI [fixed TPDU_LPDU_DIFF]
 | 
			
		||||
        print("Secure Debug: TPCI: ");
 | 
			
		||||
        println(tpci, HEX);
 | 
			
		||||
 | 
			
		||||
        // FIXME: when cEMI class is refactored, there might be additional info fields in cEMI (fixed APDU_LPDU_DIFF)
 | 
			
		||||
        if (decrypt(plainFrame.data()+APDU_LPDU_DIFF, srcAddress, dstAddress, tpci, apdu.data(), apdu.length()))
 | 
			
		||||
        {
 | 
			
		||||
            println("Plain APDU: ");
 | 
			
		||||
            plainFrame.apdu().printPDU();
 | 
			
		||||
 | 
			
		||||
            // Process decrypted inner APDU
 | 
			
		||||
            ApplicationLayer::dataConnectedIndication(priority, tsap, plainFrame.apdu());
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            println("Decryption failed!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ApplicationLayer::dataConnectedIndication(priority, tsap, apdu);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataConnectedConfirm(uint16_t tsap)
 | 
			
		||||
@ -93,28 +184,36 @@ void SecureApplicationLayer::dataConnectedConfirm(uint16_t tsap)
 | 
			
		||||
    ApplicationLayer::dataConnectedConfirm(tsap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* to transport layer */
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataGroupRequest(ack, hopType, priority, tsap, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataBroadcastRequest(ack, hopType, SystemPriority, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataSystemBroadcastRequest(AckDontCare, hopType, SystemPriority, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    ApplicationLayer::dataIndividualRequest(ack, hopType, priority, destination, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SecureApplicationLayer::dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu)
 | 
			
		||||
{
 | 
			
		||||
    // apdu must be valid until it was confirmed
 | 
			
		||||
    ApplicationLayer::dataConnectedRequest(tsap, priority, apdu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* encryption/decryption stuff */
 | 
			
		||||
 | 
			
		||||
class TpTelegram
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
@ -325,7 +424,7 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t srcAddr, uint1
 | 
			
		||||
    pBuf = popByte(scf, secureAsdu);
 | 
			
		||||
 | 
			
		||||
        bool toolAccess = ((scf & 0x80) == 0x80);
 | 
			
		||||
        bool systemBroadcast = ((scf & 0x08) == 0x08);
 | 
			
		||||
        // bool systemBroadcast = ((scf & 0x08) == 0x08); // not used for decryption
 | 
			
		||||
        uint8_t sai = (scf >> 4) & 0x07; // sai can only be 0x0 (CCM auth only) or 0x1 (CCM with auth+conf), other values are reserved
 | 
			
		||||
        bool authOnly = ( sai == 0);
 | 
			
		||||
        uint8_t service = (scf & 0x07); // only 0x0 (S-A_Data-PDU), 0x2 (S-A_Sync_Req-PDU) or 0x3 (S-A_Sync_Rsp-PDU) are valid values
 | 
			
		||||
 | 
			
		||||
@ -25,29 +25,29 @@ class SecureApplicationLayer :  public ApplicationLayer
 | 
			
		||||
    SecureApplicationLayer(AssociationTableObject& assocTable, BusAccessUnit& bau);
 | 
			
		||||
 | 
			
		||||
    // from transport layer
 | 
			
		||||
    void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
 | 
			
		||||
                          APDU& apdu, bool status);
 | 
			
		||||
    void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
 | 
			
		||||
    void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status);
 | 
			
		||||
    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);
 | 
			
		||||
    void connectIndication(uint16_t tsap);
 | 
			
		||||
    void connectConfirm(uint16_t destination, uint16_t tsap, bool status);
 | 
			
		||||
    void disconnectIndication(uint16_t tsap);
 | 
			
		||||
    void disconnectConfirm(Priority priority, uint16_t tsap, bool status);
 | 
			
		||||
    void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    void dataConnectedConfirm(uint16_t tsap);
 | 
			
		||||
    virtual void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
 | 
			
		||||
    virtual void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
 | 
			
		||||
                                  APDU& apdu, bool status) override;
 | 
			
		||||
    virtual void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
 | 
			
		||||
    virtual void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
 | 
			
		||||
    virtual void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
 | 
			
		||||
    virtual void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
 | 
			
		||||
    virtual void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
 | 
			
		||||
    virtual void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) override;
 | 
			
		||||
    virtual void connectIndication(uint16_t tsap) override;
 | 
			
		||||
    virtual void connectConfirm(uint16_t destination, uint16_t tsap, bool status) override;
 | 
			
		||||
    virtual void disconnectIndication(uint16_t tsap) override;
 | 
			
		||||
    virtual void disconnectConfirm(Priority priority, uint16_t tsap, bool status) override;
 | 
			
		||||
    virtual void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu) override;
 | 
			
		||||
    virtual void dataConnectedConfirm(uint16_t tsap) override;
 | 
			
		||||
 | 
			
		||||
  protected:
 | 
			
		||||
    // to transport layer
 | 
			
		||||
    virtual void dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
 | 
			
		||||
    virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu);
 | 
			
		||||
    virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu);
 | 
			
		||||
    virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu);
 | 
			
		||||
    virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu); // apdu must be valid until it was confirmed
 | 
			
		||||
    virtual void dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
 | 
			
		||||
    virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
 | 
			
		||||
    virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
 | 
			
		||||
    virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu) override;
 | 
			
		||||
    virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu) override; // apdu must be valid until it was confirmed
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    uint32_t calcAuthOnlyMac(uint8_t* apdu, uint8_t apduLength, uint8_t* key, uint8_t* iv, uint8_t* ctr0);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user