Exemplo n.º 1
0
        private void SendFrame(AshFrame ashFrame)
        {
            switch (ashFrame.GetFrameType())
            {
            case AshFrame.FrameType.ACK:
                _statsTxAcks++;
                break;

            case AshFrame.FrameType.DATA:
                _statsTxData++;
                // Set the frame number
                ((AshFrameData)ashFrame).SetFrmNum(_frmNum);
                _frmNum = (_frmNum + 1) & 0x07;

                // DATA frames need to go into a sent queue so we can retry if needed
                _sentQueue.Enqueue((AshFrameData)ashFrame);
                break;

            case AshFrame.FrameType.NAK:
                _statsTxNaks++;
                break;

            default:
                break;
            }

            OutputFrame(ashFrame);
        }
Exemplo n.º 2
0
        private void OutputFrame(AshFrame ashFrame)
        {
            ashFrame.SetAckNum(_ackNum);
            Log.Debug("--> TX ASH frame: {Frame}", ashFrame);

            // Send the data
            int[]  data  = ashFrame.GetOutputBuffer();
            byte[] bytes = new byte[data.Length];
            for (int i = 0; i < data.Length; i++)
            {
                bytes[i] = (byte)data[i];
            }
            _port.Write(bytes);

            // Only start the timer for data and reset frames
            if (ashFrame is AshFrameData || ashFrame is AshFrameRst)
            {
                _sentTime = DateTime.Now;
                StartRetryTimer();
            }
        }
Exemplo n.º 3
0
        private void ParserTaskLoop()
        {
            Log.Debug("AshFrameHandler parser task started");

            int exceptionCnt = 0;

            while (!_parserCancellationToken.IsCancellationRequested)
            {
                try
                {
                    int[] packetData = GetPacket();
                    if (packetData == null)
                    {
                        continue;
                    }

                    AshFrame packet        = AshFrame.CreateFromInput(packetData);
                    AshFrame responseFrame = null;
                    if (packet == null)
                    {
                        Log.Debug("<-- RX ASH error: BAD PACKET {Frame}", FrameToString(packetData));

                        // Send a NAK
                        responseFrame = new AshFrameNak(_ackNum);
                    }
                    else
                    {
                        Log.Debug("<-- RX ASH frame: {Frame}", packet.ToString());

                        // Reset the exception counter
                        exceptionCnt = 0;

                        // Extract the flags for DATA/ACK/NAK frames
                        switch (packet.GetFrameType())
                        {
                        case AshFrame.FrameType.DATA:
                            _statsRxData++;

                            // Always use the ackNum - even if this frame is discarded
                            AckSentQueue(packet.GetAckNum());

                            AshFrameData dataPacket = (AshFrameData)packet;

                            // Check for out of sequence frame number
                            if (packet.GetFrmNum() == _ackNum)
                            {
                                // Frame was in sequence - prepare the response
                                _ackNum       = (_ackNum + 1) & 0x07;
                                responseFrame = new AshFrameAck(_ackNum);

                                // Get the EZSP frame
                                EzspFrameResponse response = EzspFrame.CreateHandler(dataPacket.GetDataBuffer());
                                Log.Verbose("ASH RX EZSP: {Response}", response);
                                if (response == null)
                                {
                                    Log.Debug("ASH: No frame handler created for {Packet}", packet);
                                }
                                else
                                {
                                    NotifyTransactionComplete(response);
                                    HandleIncomingFrame(response);
                                }
                            }
                            else if (!dataPacket.GetReTx())
                            {
                                // Send a NAK - this is out of sequence and not a retransmission
                                Log.Debug("ASH: Frame out of sequence - expected {Expected}, received {Received}", _ackNum, packet.GetFrmNum());
                                responseFrame = new AshFrameNak(_ackNum);
                            }
                            else
                            {
                                // Send an ACK - this was out of sequence but was a retransmission
                                responseFrame = new AshFrameAck(_ackNum);
                            }
                            break;

                        case AshFrame.FrameType.ACK:
                            _statsRxAcks++;
                            AckSentQueue(packet.GetAckNum());
                            break;

                        case AshFrame.FrameType.NAK:
                            _statsRxNaks++;
                            SendRetry();
                            break;

                        case AshFrame.FrameType.RSTACK:
                            // Stack has been reset!
                            HandleReset((AshFrameRstAck)packet);
                            break;

                        case AshFrame.FrameType.ERROR:
                            // Stack has entered FAILED state
                            HandleError((AshFrameError)packet);
                            break;

                        default:
                            break;
                        }
                    }

                    // Due to possible I/O buffering, it is important to note that the Host could receive several
                    // valid or invalid frames after triggering a reset of the NCP. The Host must discard all frames
                    // and errors until a valid RSTACK frame is received.
                    if (!_stateConnected)
                    {
                        continue;
                    }

                    // Send the next frame
                    // Note that ASH protocol requires the host always sends an ack.
                    // Piggybacking on data packets is not allowed
                    if (responseFrame != null)
                    {
                        SendFrame(responseFrame);
                    }

                    SendNextFrame();
                }
                catch (Exception e)
                {
                    Log.Error(e, "AshFrameHandler Exception: ", e);

                    if (exceptionCnt++ > 10)
                    {
                        Log.Error("AshFrameHandler exception count exceeded: {Exception}");
                        _parserCancellationToken.Cancel();
                    }
                }
            }
            Log.Debug("AshFrameHandler exited.");
        }