public override void HandleMessage(FunctionCodeSecondary fcs, bool acd, bool dfc,
                                           int address, byte[] msg, int userDataStart, int userDataLength)
        {
            SlaveConnection slave = null;

            if (address == -1)
            {
                slave = currentSlave;
            }
            else
            {
                slave = GetSlaveConnection(address);
            }

            if (slave != null)
            {
                slave.HandleMessage(fcs, acd, dfc, address, msg, userDataStart, userDataLength);
            }
            else
            {
                DebugLog("PLL RECV - response from unknown slave " + address + " !");
            }
        }
Esempio n. 2
0
        public void HandleMessageBalancedAndPrimaryUnbalanced(byte[] msg, int msgSize)
        {
            int  userDataLength = 0;
            int  userDataStart  = 0;
            byte c       = 0;
            int  csStart = 0;
            int  csIndex = 0;
            int  address = 0;            /* address can be ignored in balanced mode? */
            bool prm     = true;
            int  fc      = 0;

            bool isAck = false;

            if (msg [0] == 0x68)
            {
                if (msg [1] != msg [2])
                {
                    DebugLog("ERROR: L fields differ!");
                    return;
                }

                userDataLength = (int)msg [1] - linkLayerParameters.AddressLength - 1;
                userDataStart  = 5 + linkLayerParameters.AddressLength;

                csStart = 4;
                csIndex = userDataStart + userDataLength;

                // check if message size is reasonable
                if (msgSize != (userDataStart + userDataLength + 2 /* CS + END */))
                {
                    DebugLog("ERROR: Invalid message length");
                    return;
                }

                c = msg [4];

                if (linkLayerParameters.AddressLength > 0)
                {
                    address += msg [5];
                }

                if (linkLayerParameters.AddressLength > 1)
                {
                    address += msg [6] * 0x100;
                }
            }
            else if (msg [0] == 0x10)
            {
                c       = msg [1];
                csStart = 1;
                csIndex = 2 + linkLayerParameters.AddressLength;

                if (linkLayerParameters.AddressLength > 0)
                {
                    address += msg [2];
                }

                if (linkLayerParameters.AddressLength > 1)
                {
                    address += msg [3] * 0x100;
                }
            }
            else if (msg [0] == 0xe5)
            {
                isAck = true;
                fc    = (int)FunctionCodeSecondary.ACK;
                prm   = false;               /* single char ACK is only sent by secondary station */
                DebugLog("Received single char ACK");
            }
            else
            {
                DebugLog("ERROR: Received unexpected message type!");
                return;
            }

            if (isAck == false)
            {
                //check checksum
                byte checksum = 0;

                for (int i = csStart; i < csIndex; i++)
                {
                    checksum += msg [i];
                }

                if (checksum != msg [csIndex])
                {
                    DebugLog("ERROR: checksum invalid!");
                    return;
                }

                // parse C field bits
                fc  = c & 0x0f;
                prm = ((c & 0x40) == 0x40);

                if (prm)                   /* we are secondary link layer */
                {
                    bool fcb = ((c & 0x20) == 0x20);
                    bool fcv = ((c & 0x10) == 0x10);

                    DebugLog("PRM=" + (prm == true ? "1" : "0") + " FCB=" + (fcb == true ? "1" : "0") + " FCV=" + (fcv == true ? "1" : "0")
                             + " FC=" + fc + "(" + ((FunctionCodePrimary)c).ToString() + ")");

                    FunctionCodePrimary fcp = (FunctionCodePrimary)fc;

                    if (secondaryLinkLayer != null)
                    {
                        secondaryLinkLayer.HandleMessage(fcp, false, address, fcb, fcv, msg, userDataStart, userDataLength);
                    }
                    else
                    {
                        DebugLog("No secondary link layer available!");
                    }
                }
                else                                 /* we are primary link layer */
                {
                    bool dir = ((c & 0x80) == 0x80); /* DIR - direction for balanced transmission */
                    bool dfc = ((c & 0x10) == 0x10); /* DFC - Data flow control */
                    bool acd = ((c & 0x20) == 0x20); /* ACD - access demand for class 1 data - for unbalanced transmission */

                    DebugLog("PRM=" + (prm == true ? "1" : "0") + " DIR=" + (dir == true ? "1" : "0") + " DFC=" + (dfc == true ? "1" : "0")
                             + " FC=" + fc + "(" + ((FunctionCodeSecondary)c).ToString() + ")");

                    FunctionCodeSecondary fcs = (FunctionCodeSecondary)fc;

                    if (primaryLinkLayer != null)
                    {
                        if (linkLayerMode == LinkLayerMode.BALANCED)
                        {
                            primaryLinkLayer.HandleMessage(fcs, dir, dfc, address, msg, userDataStart, userDataLength);
                        }
                        else
                        {
                            primaryLinkLayer.HandleMessage(fcs, acd, dfc, address, msg, userDataStart, userDataLength);
                        }
                    }
                    else
                    {
                        DebugLog("No primary link layer available!");
                    }
                }
            }
            else               /* Single byte ACK */
            {
                if (primaryLinkLayer != null)
                {
                    primaryLinkLayer.HandleMessage(FunctionCodeSecondary.ACK, false, false, -1, null, 0, 0);
                }
            }
        }
Esempio n. 3
0
        internal void SendVariableLengthFrameSecondary(FunctionCodeSecondary fc, int address, bool acd, bool dfc, BufferFrame frame)
        {
            buffer [0] = 0x68;             /* START */
            buffer [3] = 0x68;             /* START */

            byte c = (byte)((int)fc & 0x1f);

            if (linkLayerMode == LinkLayerMode.BALANCED)
            {
                if (dir)
                {
                    c += 0x80;
                }
            }

            if (acd)
            {
                c += 0x20;
            }

            if (dfc)
            {
                c += 0x10;
            }

            buffer [4] = c;

            int bufPos = 5;

            if (linkLayerParameters.AddressLength > 0)
            {
                buffer [bufPos++] = (byte)(address % 0x100);

                if (linkLayerParameters.AddressLength > 1)
                {
                    buffer [bufPos++] = (byte)((address / 0x100) % 0x100);
                }
            }

            byte[] userData       = frame.GetBuffer();
            int    userDataLength = frame.GetMsgSize();

            int l = 1 + linkLayerParameters.AddressLength + userDataLength;

            if (l > 255)
            {
                return;
            }

            buffer [1] = (byte)l;
            buffer [2] = (byte)l;

            for (int i = 0; i < userDataLength; i++)
            {
                buffer [bufPos++] = userData[i];
            }

            byte checksum = 0;

            for (int i = 4; i < bufPos; i++)
            {
                checksum += buffer[i];
            }

            buffer [bufPos++] = checksum;

            buffer [bufPos++] = 0x16;             /* END */

            if (sentRawMessageHandler != null)
            {
                sentRawMessageHandler(sentRawMessageHandlerParameter, buffer, bufPos);
            }

            transceiver.SendMessage(buffer, bufPos);
        }
Esempio n. 4
0
 public void SendFixedFrameSecondary(FunctionCodeSecondary fc, int address, bool acd, bool dfc)
 {
     SendFixedFrame((byte)fc, address, false, dir, acd, dfc);
 }
            internal void HandleMessage(FunctionCodeSecondary fcs, bool acd, bool dfc,
                                        int addr, byte[] msg, int userDataStart, int userDataLength)
            {
                PrimaryLinkLayerState newState = primaryState;

                if (dfc)
                {
                    //stop sending ASDUs; only send Status of link requests
                    dontSendMessages = true;

                    switch (primaryState)
                    {
                    case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:
                    case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:
                        newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;
                        break;

                    case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:
                    //TODO message must be handled and switched to BUSY state later!
                    case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                        newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                        break;
                    }

                    SetState(LinkLayerState.BUSY);

                    primaryState = newState;
                    return;
                }
                else
                {
                    // unblock transmission of application layer messages
                    dontSendMessages = false;
                }

                switch (fcs)
                {
                case FunctionCodeSecondary.ACK:

                    DebugLog("[SLAVE " + address + "] PLL - received ACK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        if (sendLinkLayerTestFunction)
                        {
                            sendLinkLayerTestFunction = false;
                        }

                        SetState(LinkLayerState.AVAILABLE);

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    }
                    else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        /* single char ACK is interpreted as RESP NO DATA */
                        requestClass1Data = false;
                        requestClass2Data = false;

                        SetState(LinkLayerState.AVAILABLE);

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    }

                    waitingForResponse = false;
                    break;

                case FunctionCodeSecondary.NACK:

                    DebugLog("[SLAVE " + address + "] PLL - received NACK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        SetState(LinkLayerState.BUSY);

                        newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    }

                    waitingForResponse = false;
                    break;

                case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND:

                    DebugLog("[SLAVE " + address + "] PLL - received STATUS OF LINK");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK)
                    {
                        DebugLog("[SLAVE " + address + "] PLL - SEND RESET REMOTE LINK");

                        linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, address, false, false);

                        nextFcb            = true;
                        lastSendTime       = SystemUtils.currentTimeMillis();
                        waitingForResponse = true;
                        newState           = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK;

                        SetState(LinkLayerState.BUSY);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);

                        waitingForResponse = false;
                    }

                    break;

                case FunctionCodeSecondary.RESP_USER_DATA:

                    DebugLog("[SLAVE " + address + "] PLL - received USER DATA");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        linkLayerUnbalanced.callbacks.UserData(address, msg, userDataStart, userDataLength);

                        requestClass1Data = false;
                        requestClass2Data = false;

                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);
                    }

                    waitingForResponse = false;

                    break;

                case FunctionCodeSecondary.RESP_NACK_NO_DATA:

                    DebugLog("[SLAVE " + address + "] PLL - received RESP NO DATA");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_REQUEST_RESPOND)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        requestClass1Data = false;
                        requestClass2Data = false;

                        SetState(LinkLayerState.AVAILABLE);
                    }
                    else
                    {     /* illegal message */
                        newState = PrimaryLinkLayerState.IDLE;

                        SetState(LinkLayerState.ERROR);
                    }

                    waitingForResponse = false;

                    break;

                case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING:
                case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED:

                    DebugLog("[SLAVE " + address + "] PLL - link layer service not functioning/not implemented in secondary station ");

                    if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                    {
                        newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;

                        SetState(LinkLayerState.AVAILABLE);
                    }

                    waitingForResponse = false;

                    break;

                default:
                    DebugLog("[SLAVE " + address + "] UNEXPECTED SECONDARY LINK LAYER MESSAGE");
                    break;
                }

                if (acd)
                {
                    if (linkLayerUnbalanced.callbacks != null)
                    {
                        linkLayerUnbalanced.callbacks.AccessDemand(address);
                    }
                }

                DebugLog("[SLAVE " + address + "] PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString());

                primaryState = newState;
            }
Esempio n. 6
0
        public override void HandleMessage(FunctionCodeSecondary fcs, bool dir, bool dfc,
                                           int address, byte[] msg, int userDataStart, int userDataLength)
        {
            PrimaryLinkLayerState newState = primaryState;

            if (dfc)
            {
                //TODO stop sending ASDUs; only send Status of link requests

                switch (primaryState)
                {
                case PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK:
                case PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK:
                    newState = PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK;
                    break;

                case PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM:
                //TODO message must be handled and switched to BUSY state later!
                case PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY:
                    newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    break;
                }

                SetNewState(LinkLayerState.BUSY);
                primaryState = newState;
                return;
            }

            switch (fcs)
            {
            case FunctionCodeSecondary.ACK:
                //TODO what to do if we are not waiting for a response?
                DebugLog("PLL - received ACK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK)
                {
                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }
                else if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    if (sendLinkLayerTestFunction)
                    {
                        sendLinkLayerTestFunction = false;
                    }

                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }

                waitingForResponse = false;
                break;

            case FunctionCodeSecondary.NACK:
                DebugLog("PLL - received NACK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    newState = PrimaryLinkLayerState.SECONDARY_LINK_LAYER_BUSY;
                    SetNewState(LinkLayerState.BUSY);
                }
                break;

            case FunctionCodeSecondary.RESP_USER_DATA:

                newState = PrimaryLinkLayerState.IDLE;
                SetNewState(LinkLayerState.ERROR);

                break;

            case FunctionCodeSecondary.RESP_NACK_NO_DATA:

                newState = PrimaryLinkLayerState.IDLE;
                SetNewState(LinkLayerState.ERROR);

                break;


            case FunctionCodeSecondary.STATUS_OF_LINK_OR_ACCESS_DEMAND:
                DebugLog("PLL - received STATUS OF LINK");
                if (primaryState == PrimaryLinkLayerState.EXECUTE_REQUEST_STATUS_OF_LINK)
                {
                    DebugLog("PLL - SEND RESET REMOTE LINK to address " + linkLayerAddressOtherStation);
                    linkLayer.SendFixedFramePrimary(FunctionCodePrimary.RESET_REMOTE_LINK, linkLayerAddressOtherStation, false, false);
                    lastSendTime       = SystemUtils.currentTimeMillis();
                    waitingForResponse = true;
                    newState           = PrimaryLinkLayerState.EXECUTE_RESET_REMOTE_LINK;
                    SetNewState(LinkLayerState.BUSY);
                }
                else                   /* illegal message */
                {
                    newState = PrimaryLinkLayerState.IDLE;
                    SetNewState(LinkLayerState.ERROR);
                }

                break;

            case FunctionCodeSecondary.LINK_SERVICE_NOT_FUNCTIONING:
            case FunctionCodeSecondary.LINK_SERVICE_NOT_IMPLEMENTED:
                DebugLog("PLL - link layer service not functioning/not implemented in secondary station");

                if (sendLinkLayerTestFunction)
                {
                    sendLinkLayerTestFunction = false;
                }

                if (primaryState == PrimaryLinkLayerState.EXECUTE_SERVICE_SEND_CONFIRM)
                {
                    newState = PrimaryLinkLayerState.LINK_LAYERS_AVAILABLE;
                    SetNewState(LinkLayerState.AVAILABLE);
                }
                break;

            default:
                DebugLog("UNEXPECTED SECONDARY LINK LAYER MESSAGE");
                break;
            }

            DebugLog("PLL RECV - old state: " + primaryState.ToString() + " new state: " + newState.ToString());

            primaryState = newState;
        }
 public abstract void HandleMessage(FunctionCodeSecondary fcs, bool dir, bool dfc,
                                    int address, byte[] msg, int userDataStart, int userDataLength);