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 + " !"); } }
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); } } }
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); }
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; }
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);