// Create a command general message. public int CreateGeneralMessage(bool verified, byte cmd, ushort receiver, ushort sender, byte flagsRS, byte senderId, byte dataLen, byte[] pData, byte bufferIndex) { if (dataLen > (Manager.MaxPacketSize - ProtocolConstants.GENERAL_OVERHEADS_SIZE)) { return(-1); } int idx = Manager.IoBuffersFreeHeap.Allocate(); if (idx != -1) { PacketBuffer b = Manager.IoBuffers[idx]; byte pid = verified ? ProtocolConstants.PID_GENERAL_V : ProtocolConstants.PID_GENERAL; b.flagsPid = pid; b.dNetIf = ProtocolConstants.NETIF_UNSET; b.iNetIf = ProtocolConstants.NETIF_UNSET; b.pktLen = (byte)(ProtocolConstants.GENERAL_OVERHEADS_SIZE + dataLen); b.sync(ProtocolConstants.BYTE_SYNC); b.negPidPid(Primitives.NibbleToPid(pid)); b.destination(LinkMonitor.Destination); // TODO: set destination. b.arg(0); b.receiver(receiver); b.sender(sender); b.senderId(senderId); b.flagsRS(flagsRS); b.command(cmd); b.dataLength(dataLen); byte dataIndex = ProtocolConstants.GENERAL_DATA_ARRAY_OFFSET; byte[] p = b.buffer; for (byte k = 0; k < dataLen; k++) { p[dataIndex++] = pData[bufferIndex + k]; } b.UpdateCheckSum(b.pktLen); } return(idx); }
// Submit a handshake command to link WriteQ. // For example, Resend Vno command, ping, reply, etc. public int SendLinkHandshakePacket(byte pid, ushort destination, byte arg) { int idx = Manager.IoBuffersFreeHeap.Allocate(); if (idx != -1) { PacketBuffer b = Manager.IoBuffers[idx]; b.flagsPid = pid; b.dNetIf = ProtocolConstants.NETIF_UNSET; b.iNetIf = ProtocolConstants.NETIF_UNSET; b.pktLen = ProtocolConstants.HANDSHAKE_PACKET_SIZE; b.sync(ProtocolConstants.BYTE_SYNC); b.negPidPid(Primitives.NibbleToPid(pid)); b.destination(destination); b.arg(arg); b.UpdateCheckSum(b.pktLen); if (IoNetIf.LinkWriteQueue.PushFirst(idx) == -1) { Manager.IoBuffersFreeHeap.Release(idx); return(-1); } } return(idx); }
public static string DumpHandshake(PacketBuffer b) { return("{" + String.Format("pid={0:x2},arg={1:x2}", b.negPidPid() & ProtocolConstants.PID_MASK, b.arg()) + "}\n"); }
// Perform a handshake request received from link. // Consults original message for r,s details, ports=0, flags=0. // TODO: check what happens when a master is pinged etc. Ok? public void PerformLinkHandshake(PacketBuffer hp) { int idx; byte arg = hp.arg(); // TODO: Check packet is for us first. switch (hp.negPidPid() & ProtocolConstants.PID_MASK) { case ProtocolConstants.PID_PING: // We received a ping. Now send a reply. if (arg >= ProtocolConstants.PID_ARG_BAUD_MIN) { switch (arg) { case ProtocolConstants.PID_ARG_RESET: IoNetIf.ResetLinkDriver(); break; case ProtocolConstants.PID_ARG_SLAVE: break; case ProtocolConstants.PID_ARG_MULTI: break; case ProtocolConstants.PID_ARG_MASTER: break; default: // BAUD: Request to change baud rate. IoNetIf.IoNetIfDevice.PerformBaudAction(IoNetIf.DeviceContextIndex, (byte)(arg - ProtocolConstants.PID_ARG_BAUD_MIN), ProtocolConstants.BAUD_ACTION_SAVE); break; } } else { // Set linkLastInputVno=(VNO_SIZE-1) & linkLastOutputVno=0 ? CheckOrderMissingQ(arg, false); IoNetIf.duplexPingReply |= LinkMonitor.DUX_PING_RECEIVED; } // Send a reply with Arg = num messages waiting. // TODO: unless Q contains Msg destined to sender: use "more" msg code. int num = IoNetIf.LinkWriteQueue.Size(); // Arg = num messages waiting. SendLinkHandshakePacket(ProtocolConstants.PID_REPLY, LinkMonitor.Destination, // hp.destination(), // TODO: This should be the linkAdrs. (byte)((num > 255) ? 255 : num)); break; case ProtocolConstants.PID_REPLY: //TODO: Now stop pinging. // arg=number of waiting messages. // If arg>0 read some messages. IoNetIf.duplexNumWaiting = arg; IoNetIf.duplexPingReply |= LinkMonitor.DUX_REPLY_RECEIVED; break; case ProtocolConstants.PID_RESEND: // Resend a message. idx = FindVnoInVerifyQueue(IoNetIf.LinkVerifyQueue, arg); if (idx == -1) { SendLinkHandshakePacket(ProtocolConstants.PID_CANCEL, hp.destination(), arg); } else if (IoNetIf.LinkWriteQueue.FindFirstOccurrenceIndex(idx) == -1) { PacketBuffer b = Manager.IoBuffers[idx]; b.flagsPid |= ProtocolConstants.META_FLAGS_RESEND; if (IoNetIf.LinkWriteQueue.PushFirst(idx) == -1) { Manager.IoBuffersFreeHeap.Release(idx); } } break; case ProtocolConstants.PID_CANCEL: // Remove message from missingQ. IoNetIf.LinkMissingQueue.RemoveFirstOccurrence(arg); break; default: break; } // TODO: IoNetIf.activityTimeout=Primitives.GetBabelMilliTicker() + LinkMonitor.CONX_ACTIVITY_TIMEOUT; IoNetIf.baudTimeout = Primitives.GetBabelMilliTicker() + LinkMonitor.BAUD_RATE_TIMEOUT; // Reset timer after input from specific sender. }