using System; using System.Text; using DTS.Common.Enums.Communication; using DTS.Common.Enums.DASFactory; using DTS.Common.ICommunication; using DTS.Common.Utilities; namespace DTS.DASLib.Command.SLICE.DownloadCommands { /// /// This was ported from FirmwareTestUtility where it was written by Loc Pham /// it is being included for /// 10573 implement SW side of single command/streaming download /// this command can be used to collect data that has been collecting in a buffer /// from download streaming /// public class GetNextDownloadStreamDataSamples : EventDataCommands { protected override Commands Command => Commands.GetNextDownloadStreamDataSamples; public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock) : base(sock) { baseCommand = new CommandPacket(); LogCommands = false; baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples"); } public GetNextDownloadStreamDataSamples(DTS.Common.Interface.DASFactory.ICommunication sock, int msTimeout) : base(sock, msTimeout) { baseCommand = new CommandPacket(); LogCommands = false; baseCommand.SetCommand((byte)Commands.GetNextDownloadStreamDataSamples, "GetNextDownloadStreamDataSamples"); } public DownloadByteConverter DlData { get; private set; } private ushort _lastSequenceProcessed = ushort.MaxValue; private const int MAX_SEQUENCE_DIFF = 1000; public void ProcessData() { var bytes = baseResponse.ToBytes(); var headerCrc = response.HeaderCRC; response.ComputeCRCs(); if (headerCrc != response.HeaderCRC) { DlData = null; return; } DlData = new DownloadByteConverter(bytes); if (null == DlData) { return; } if (_lastSequenceProcessed == DlData.SeqNumber) { DlData = null; return; } var delta = Math.Abs(DlData.SeqNumber - _lastSequenceProcessed); if (delta > MAX_SEQUENCE_DIFF && ushort.MaxValue != _lastSequenceProcessed && 0 != DlData.SeqNumber) { //per loc we shouldn't get here, the old code in the FWTU would apparently unintentionally throw an exception //I've preserved that code in comments below throw new Exception("sequence number overflow"); //DlData = null; //_lastSequenceProcessed = DlData.SeqNumber; //return; } _lastSequenceProcessed = DlData.SeqNumber; } /// /// We need to override SyncExecute because we don't want to send anything (that would tell the G5 to stop sending). Instead we just want to /// read whatever is out there. Otherwise this is mostly cut and paste of normal SyncExecute with some streamlining for our specific case. /// public override void SyncExecute() { // this is a try/finally to handle the ExecuteIsBusy try { DlData = null; // there can be only one! recorder.ExecuteIsBusy = true; if (recorder.IsCanceled()) { throw new CanceledException(); } UserCallback = null; UserCallbackData = null; IsSynchronous = true; SyncEvent.Reset(); recorder.PseudoExecute(new byte[0], ExecuteCallback, null, IO_Timeout); var syncExecTimeout = IO_Timeout; try { if (!WaitWithCondition.Wait(SyncEvent, syncExecTimeout, recorder.CancelEvent)) { //timeout LogString("SyncExecute: timeout"); throw new TimeoutException(MakeLogString("SyncExecute: timeout")); } } catch (WaitWithCondition.ConditionMetException) { throw new CanceledException(); } // we didn't timeout, check the result switch (ComReport.Result) { case CommunicationConstantsAndEnums.CommunicationResult.Canceled: throw new CanceledException(); case CommunicationConstantsAndEnums.CommunicationResult.ReceiveOK: if (baseResponse == null) { LogString("SyncExecute: ReceiveOK but response==null!"); LogCommand(false); } else if (baseResponse.Status != DFConstantsAndEnums.CommandStatus.StatusNoError) { // didn't go well var msg = MakeLogString("SyncExecute: response.Status = " + baseResponse.Status); LogCommand(false); switch (baseResponse.Status) { case DFConstantsAndEnums.CommandStatus.StatusInvalidModeForCommand: throw new CommandException(CommandErrorReason.InvalidMode, msg); case DFConstantsAndEnums.CommandStatus.StatusUnimplemented: case DFConstantsAndEnums.CommandStatus.StatusInvalidCommand: case DFConstantsAndEnums.CommandStatus.StatusInvalidCommandType: throw new NotImplementedException(msg); } var ex = new Exception(msg); ex.Data.Add("Status", baseResponse.Status); throw ex; } // everything is fine, let it exit if (LogCommands) { LogCommand(false); } break; case CommunicationConstantsAndEnums.CommunicationResult.ReceiveFailed: { var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result); LogCommand(false); throw new CommandException(CommandErrorReason.ReceiveFailed, msg); } case CommunicationConstantsAndEnums.CommunicationResult.ReceiveTimeout: { var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result); LogCommand(false); throw new CommandException(CommandErrorReason.ReceiveFailed, msg); } case CommunicationConstantsAndEnums.CommunicationResult.SendFailed: case CommunicationConstantsAndEnums.CommunicationResult.SendTimeout: { var msg = MakeLogString("SyncExecute: ComReport.Result == " + ComReport.Result); LogCommand(false); throw new CommandException(CommandErrorReason.SendFailed, msg); } default: { var msg = MakeLogString("SyncExecute: Unknown ComReport.Result == " + ComReport.Result); LogCommand(false); throw new Exception(msg); } } } finally { recorder.ExecuteIsBusy = false; } } } }