Ejemplo n.º 1
0
        // 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);
        }
Ejemplo n.º 2
0
        // 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);
        }
Ejemplo n.º 3
0
 public static string DumpHandshake(PacketBuffer b)
 {
     return("{" + String.Format("pid={0:x2},arg={1:x2}", b.negPidPid() & ProtocolConstants.PID_MASK, b.arg()) + "}\n");
 }
Ejemplo n.º 4
0
        // 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.
        }
Ejemplo n.º 5
0
        // Called just before message is written to device.
        // Determine if packet needs modification.
        // Updates DUX & BAUD flags.
        // Returns verification action if needed.
        // TODO: set destination.
        public byte PreLinkWriteFilter(PacketBuffer b)
        {
            int  sumDiff      = 0;
            byte verifyAction = ProtocolConstants.VERIFY_ACTION_NONE;
            byte c            = (byte)(b.flagsPid & ProtocolConstants.META_FLAGS_PID);

            if (c == ProtocolConstants.PID_GENERAL_V)
            {
                // Sequence numbers are used to detect bad xfers.
                // Resends must be sent with the same Vno rather than a new Vno.
                if ((b.flagsPid & ProtocolConstants.META_FLAGS_RESEND) != 0)
                {
                    verifyAction = ProtocolConstants.VERIFY_ACTION_RESEND; // This stops vnoLastOutput being incremented below.
                }
                else
                {
                    verifyAction = ProtocolConstants.VERIFY_ACTION_NEW;
                    sumDiff      = (int)b.arg() - (int)IoNetIf.vnoLastOutput;
                    b.arg(IoNetIf.vnoLastOutput);
                }
            }
            else if (c == ProtocolConstants.PID_PING)
            {
                byte arg = b.arg();
                if (arg == 0)   // It's a basic ping, so set arg to vno.
                {
                    sumDiff = -(int)IoNetIf.vnoLastOutput;
                    b.arg(IoNetIf.vnoLastOutput);
                }
                else if (arg >= ProtocolConstants.PID_ARG_BAUD_MIN)
                {
                    switch (arg)
                    {
                    case ProtocolConstants.PID_ARG_RESET:
                        break;

                    case ProtocolConstants.PID_ARG_SLAVE:
                        break;

                    case ProtocolConstants.PID_ARG_MULTI:
                        break;

                    case ProtocolConstants.PID_ARG_MASTER:
                        break;

                    default:     // BAUD: Flag baud ping sent, set UART_*_SetBaudRate = netIfIndex.
                        // This is a broadcast to all on link.
                        IoNetIf.IoNetIfDevice.PerformBaudAction(IoNetIf.DeviceContextIndex,
                                                                (byte)(arg - ProtocolConstants.PID_ARG_BAUD_MIN),
                                                                ProtocolConstants.BAUD_ACTION_SIGNAL);
                        IoNetIf.baudTimeout = Primitives.GetBabelMilliTicker() + LinkMonitor.BAUD_RATE_TIMEOUT;     // Mark Baud broadcast for all.
                        break;
                    }
                }
                // DUX: need to block further writes.
                if ((IoNetIf.duplexKind & (byte)LINK_DUPLEX_KIND.LINK_DUPLEX_KIND_HALF) != 0)
                {
                    IoNetIf.duplexPingReply |= LinkMonitor.DUX_PING_SENT;
                    IoNetIf.duplexNumWaiting = (byte)0xffu;
                    IoNetIf.duplexMode       = (byte)DUX_MODE.DUX_RX;
                }
            }
            else if (c == ProtocolConstants.PID_REPLY)
            {
                IoNetIf.duplexPingReply |= LinkMonitor.DUX_REPLY_SENT;// DUX: flag reply sent.
            }
            // Update checksum: assume valid on entry & work out bit change.
            if (sumDiff != 0)
            {
                // newChkSum = oldChkSum + (oldSumBits - newSumBits).
                byte oldChkSum = b.buffer[b.pktLen - 1];
                b.buffer[b.pktLen - 1] = (byte)(((int)oldChkSum) + sumDiff);
            }
            return(verifyAction);
        }