示例#1
0
        /// <summary>
        /// Performs a manufacturer procedure 37 to tell the meter to get ready for
        /// firmware download
        /// </summary>
        /// <param name="strFilePath">path to the f/w file to download</param>
        /// <returns>ProcedureResultCodes</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 11/15/13 AF  3.50.03	       Class re-architecture - Cloned from CENTRON_AMI
        // 01/06/14 DLG 3.50.19        Class re-architecture - Moved from ICS_Gateway to
        //                             CommonFirmwareDownload.
        // 02/03/14 AF  3.50.30 TQ9508 We needed to reverse the order of the bytes in the device class
        //                             before adding it to the parameter list
        // 02/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        //
        private FWDownloadResult EnterFirmwareDownloadMode(string strFilePath)
        {
            //Construct the parameters for mfg proc 37 and execute the procedure
            FileInfo fi = new FileInfo(strFilePath);

            byte[] bybuf        = new byte[CANSIDevice.FW_HEADER_LENGTH];
            byte[] byParameters = null;
            byte[] byImageSize  = new byte[CANSIDevice.IMAGE_SIZE_FIELD_LEN];
            byte[] byChunkSize  = new byte[CANSIDevice.CHUNK_SIZE_FIELD_LEN];
            byte[] ProcResponse;
            ProcedureResultCodes ProcResult  = ProcedureResultCodes.INVALID_PARAM;
            FWDownloadResult     FWResult    = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ICommModVersions     CommModVers = m_ANSIDevice as ICommModVersions;

            try
            {
                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                   "Initiating Firmware Download");

                // Most of the procedure parameters are in the f/w file header
                FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Read(bybuf, 0, CANSIDevice.FW_HEADER_LENGTH);
                fs.Close();

                byParameters = new byte[CANSIDevice.INIT_FW_DOWNLOAD_THIRD_PARTY_LEN];

                byParameters.Initialize();

                // CRC LSB first
                byParameters[0] = bybuf[1];
                byParameters[1] = bybuf[0];

                // Retrieve the parameters out of the header
                Array.Copy(bybuf, 5, byParameters, 2, 9);

                // image size
                byImageSize = BitConverter.GetBytes((int)fi.Length);
                Array.Copy(byImageSize, 0, byParameters, 11, CANSIDevice.IMAGE_SIZE_FIELD_LEN);

                byChunkSize = BitConverter.GetBytes(m_ANSIDevice.FWDLBlockSize);
                Array.Copy(byChunkSize, 0, byParameters, 15, CANSIDevice.CHUNK_SIZE_FIELD_LEN);

                // Add the device class
                // The meter needs the Device Class in the reverse order that it is stored in the firmware file
                byParameters[17] = bybuf[17];
                byParameters[18] = bybuf[16];
                byParameters[19] = bybuf[15];
                byParameters[20] = bybuf[14];

                ProcResult = m_ANSIDevice.ExecuteProcedure(Procedures.INITIATE_FW_LOADER_SETUP,
                                                           byParameters,
                                                           out ProcResponse);

                if (ProcedureResultCodes.INVALID_PARAM == ProcResult)
                {
                    // The Firmware load did not work.  At some point during development they added
                    //  more detail in the Response, so we can read the byte and see what the error is
                    switch (ProcResponse[0])
                    {
                    case 1:
                        FWResult = FWDownloadResult.FW_IMAGE_TOO_BIG;
                        break;

                    case 2:
                        FWResult = FWDownloadResult.HW_REVISION_OUTSIDE_RANGE;
                        break;

                    case 3:
                        FWResult = FWDownloadResult.HW_VERSION_OUTSIDE_RANGE;
                        break;

                    case 10:
                        FWResult = FWDownloadResult.FW_TYPE_IS_INVALID;
                        break;

                    case 11:
                        FWResult = FWDownloadResult.ZIGBEE_FW_TYPE_INVALID;
                        break;

                    default:
                        FWResult = FWDownloadResult.INVALID_CONFIG;
                        break;
                    }
                }
                else
                {
                    FWResult = TranslateProcedureResult(ProcResult);
                }
            }
            catch (PSEMException PSEMExp)
            {
                //TODO - This does not catch the error for same version when the device is an ITRU
                if (CommModVers != null)
                {
                    if (PSEMResponse.Err == PSEMExp.PSEMResponse &&
                        (byte)FirmwareType.ICSFW == byParameters[6] &&
                        CommModVers.CommModuleVersion == byParameters[2] &&
                        CommModVers.CommModuleRevision == byParameters[3] &&
                        CommModVers.CommModuleBuild == byParameters[4])
                    {
                        //This is how an attempt to download the same OW ICS comm module firmware
                        //version will fail.
                        FWResult = FWDownloadResult.ICS_SAME_VERSION_REJECTION;
                    }
                }
                else
                {
                    // Log it and pass it up
                    m_Logger.WriteException(this, PSEMExp);
                    throw (PSEMExp);
                }
            }
            catch (Exception e)
            {
                // Log it and pass it up
                m_Logger.WriteException(this, e);
                throw (e);
            }

            return(FWResult);
        }
示例#2
0
        /// <summary>
        /// This method just downloads the firmware file blocks to the device for a
        /// given range of blocks.  Use 1-based indexing for blocks.
        /// </summary>
        /// <param name="path">Complete path to the firmware file</param>
        /// <param name="usStartBlock">The first block to download.</param>
        /// <param name="usEndBlock">The last block to download.</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 11/15/13 AF  3.50.03	       Class re-architecture - Cloned from CENTRON_AMI
        // 01/06/14 DLG 3.50.19        Class re-architecture - Moved from ICS_Gateway to
        //                             CommonFirmwareDownload.
        // 02/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        //
        public FWDownloadResult DownloadFWBlocks(string path, ushort usStartBlock, ushort usEndBlock)
        {
            FWDownloadResult Result           = FWDownloadResult.SUCCESS;
            PSEMResponse     ProtocolResponse = PSEMResponse.Ok;
            byte             byEventNumber    = 0;
            ushort           idTable          = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
            ushort           usNumberChunks   = 0;
            ushort           usIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                byte[] bybuffer = new byte[streamFile.Length];

                streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                streamFile.Position = 0;

                switch (bybuffer[9])
                {
                case (byte)FirmwareType.ICSFW:
                {
                    byEventNumber = CANSIDevice.COMM_EVENT_NUMBER;
                    idTable       = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
                    break;
                }

                default:
                {
                    throw new NotImplementedException("Table not yet supported");
                }
                }

                m_ANSIDevice.BuildPendingHeader(ref streamHeader, false, false,
                                                byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                usNumberChunks = (ushort)(streamFile.Length / m_ANSIDevice.FWDLBlockSize);

                if (streamFile.Length != m_ANSIDevice.FWDLBlockSize * usNumberChunks)
                {
                    usNumberChunks++;
                }

                m_ANSIDevice.OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                                      "Firmware Download",
                                                                      "Downloading..."));

                ushort usSendSize = m_ANSIDevice.FWDLBlockSize;

                //Make sure the start block is not less than 1
                if (usStartBlock < 1)
                {
                    usStartBlock = 1;
                }
                //Make sure the end block is not greater than the actual number of FW blocks.
                if (usEndBlock > usNumberChunks)
                {
                    usEndBlock = usNumberChunks;
                }

                for (usIndex = (ushort)(usStartBlock - 1);
                     (usIndex < usEndBlock) && (PSEMResponse.Ok == ProtocolResponse);
                     usIndex++)
                {
                    // The last chunk could be smaller
                    if (usNumberChunks - 1 == usIndex)
                    {
                        usSendSize = (ushort)(streamFile.Length % m_ANSIDevice.FWDLBlockSize);
                        // If no remainder then it is a full packet
                        if (0 == usSendSize)
                        {
                            usSendSize = m_ANSIDevice.FWDLBlockSize;
                        }
                    }

                    streamHeader.Position = 0;
                    streamPSEM.Position   = 0;
                    streamPSEM.SetLength(0);
                    streamHeader.WriteTo(streamPSEM);
                    streamPSEM.Write(bybuffer, usIndex * m_ANSIDevice.FWDLBlockSize, usSendSize);

                    ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                          usIndex * m_ANSIDevice.FWDLBlockSize,
                                                          streamPSEM.ToArray());
                    m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                }

                // Translate Protocol result
                Result = TranslateProtocolResult(ProtocolResponse);

                streamFile.Close();

                m_ANSIDevice.OnHideProgress(new EventArgs());
            }

            catch (Exception e)
            {
                // Log it and pass it up
                m_ANSIDevice.OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }
示例#3
0
        /// <summary>
        /// Downloads the firmware file to the device but does NOT
        /// activate.  On download failure, the pending table is cleared.
        /// </summary>
        /// <param name="path">Complete path to the firmware file</param>
        /// <param name="eventCode">event code activation method</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 11/15/13 AF  3.50.03	       Class re-architecture - Cloned from CENTRON_AMI
        // 01/06/14 DLG 3.50.19        Class re-architecture - Moved from ICS_Gateway to
        //                             CommonFirmwareDownload.
        // 02/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        //
        public FWDownloadResult DownloadFWNoActivate(string path, PendingEventRecord.PendingEventCode eventCode)
        {
            FWDownloadResult Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            PSEMResponse     ProtocolResponse = PSEMResponse.Ok;
            byte             byEventNumber    = 0;
            ushort           idTable          = (ushort)CANSIDevice.FWDLTableIds.RegisterFWTbl | CANSIDevice.PENDING_BIT;
            ushort           usNumberChunks   = 0;
            ushort           intIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                Result = EnterFirmwareDownloadMode(path);

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.ICSFW:
                    {
                        byEventNumber = CANSIDevice.COMM_EVENT_NUMBER;
                        idTable       = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not yet supported");
                    }
                    }

                    m_ANSIDevice.BuildPendingHeader(ref streamHeader, false, false, byEventNumber, eventCode);

                    usNumberChunks = (ushort)(streamFile.Length / m_ANSIDevice.FWDLBlockSize);

                    if (streamFile.Length != m_ANSIDevice.FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    m_ANSIDevice.OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                                          "Firmware Download",
                                                                          "Downloading..."));

                    ushort usSendSize = m_ANSIDevice.FWDLBlockSize;

                    for (intIndex = 0;
                         (intIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         intIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == intIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % m_ANSIDevice.FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = m_ANSIDevice.FWDLBlockSize;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, intIndex * m_ANSIDevice.FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * m_ANSIDevice.FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    // If any write failed, give up and clear the pending table
                    if (PSEMResponse.Ok != ProtocolResponse)
                    {
                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    m_ANSIDevice.OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                // Log it and pass it up
                m_ANSIDevice.OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }
示例#4
0
        public FWDownloadResult DownloadFW(string path, ref ushort usBlockIndex, bool blnRetry = false, bool blnActivate = true)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
            ushort usNumberChunks = 0;
            //A non-zero starting block means we are need to pick up were we left off.
            bool blnResumeFWDL = (0 != usBlockIndex);

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                if (true == blnResumeFWDL)
                {
                    Result = FWDownloadResult.SUCCESS;

                    m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                       "Resuming Firmware Download @ Block " + usBlockIndex.ToString());
                }
                else
                {
                    // Tell the meter to enter firmware download mode
                    Result = EnterFirmwareDownloadMode(path);
                }

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.ICSFW:
                    {
                        byEventNumber = CANSIDevice.COMM_EVENT_NUMBER;
                        idTable       = (ushort)CANSIDevice.FWDLTableIds.CommModuleFWTbl | CANSIDevice.PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not supported");
                    }
                    }

                    m_ANSIDevice.BuildPendingHeader(ref streamHeader, false, false,
                                                    byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / m_ANSIDevice.FWDLBlockSize);

                    if (streamFile.Length != m_ANSIDevice.FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    m_ANSIDevice.OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                                          "Firmware Download",
                                                                          "Downloading..."));

                    ushort usSendSize = m_ANSIDevice.FWDLBlockSize;

                    for (;
                         (usBlockIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         usBlockIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == usBlockIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % m_ANSIDevice.FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = m_ANSIDevice.FWDLBlockSize;
                            }
                        }

                        m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                           "Firmware Download - Sending Block " + usBlockIndex.ToString());

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, usBlockIndex * m_ANSIDevice.FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              usBlockIndex * m_ANSIDevice.FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    //Check on success and then activate the table
                    if (PSEMResponse.Ok == ProtocolResponse)
                    {
                        ProcResult = ProcedureResultCodes.COMPLETED;

                        if (ProcResult == ProcedureResultCodes.COMPLETED)
                        {
                            if (true == blnActivate)
                            {
                                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                                   "Activating Firmware Download");

                                // Activate the pending table using mfg proc 69
                                ProcResult = m_ANSIDevice.ActivateFWDLTable(idTable, (byte)FirmwareType.ICSFW, bybuffer[5], bybuffer[6], bybuffer[7], bybuffer[8]);

                                Result = TranslateProcedureResult(ProcResult);
                            }
                        }
                        else
                        {
                            //TODO - not sure this is the correct error
                            Result = FWDownloadResult.SECURITY_ERROR;
                        }

                        m_ANSIDevice.OnStepProgress(new ProgressEventArgs());
                    }
                    else //PSEMResponse.Ok != ProtocolResponse
                    {
                        //Decrement the block index so we make sure we restart on the block that we failed on.
                        usBlockIndex--;

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    m_ANSIDevice.OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                m_Logger.WriteException(this, e);

                if (false == blnRetry)
                {
                    // Log it and pass it up
                    m_ANSIDevice.OnHideProgress(new EventArgs());

                    throw e;
                }
                else
                {
                    Result = FWDownloadResult.WRITE_ERROR;
                }
            }

            return(Result);
        }
        /// <summary>
        /// Downloads the firmware file to the device but does NOT
        /// activate.  On download failure, the pending table is cleared.
        /// </summary>
        /// <param name="path">Complete path to the firmware file</param>
        /// <param name="eventCode">event code activation method</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 10/05/06 AF  7.35.00  N/A   Created
        // 10/18/06 AF  7.40.00  N/A   Removed wait within the main loop
        // 05/13/08 AF  1.50.24        Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39        Added M2 Gateway support
        // 03/21/12 JJJ 2.60.xx        Added support for ChoiceConnect FW
        // 08/17/12 AF  2.60.55        Added support for RF Mesh FW and RF Mesh Config
        // 02/07/14 jrf 3.50.32 419257 Modified to use a dynamic FWDL block size based on the negotiated
        //                             PSEM packet size.
        // 06/15/15 mah 4.50.140 577669 Added a retry if a busy response was received
        // 08/24/16 PGH 4.70.15 701952     Added HAN OTA Firmware
        public FWDownloadResult DownloadFWNoActivate(string path, PendingEventRecord.PendingEventCode eventCode)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            ushort intIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                Result = EnterFirmwareDownloadMode(path);

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HAN_OTA_FW:
                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not yet supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false, byEventNumber, eventCode);

                    usNumberChunks = (ushort)(streamFile.Length / FWDLBlockSize);

                    if (streamFile.Length != FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = FWDLBlockSize;

                    for (intIndex = 0;
                         (intIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         intIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == intIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = FWDLBlockSize;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, intIndex * FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * FWDLBlockSize,
                                                              streamPSEM.ToArray());

                        // WR 577669 - The fwdl process is failing on ICS meters with a device busy status.  The intent of the next
                        // paragraph is to recognize that the meter may be off doing other operations when we first tried to download
                        // a block.

                        if (ProtocolResponse == PSEMResponse.Bsy)
                        {
                            // Wait for the device to complete it's current task, then retry to download the same block

                            Thread.Sleep(1500); // 1.5 seconds is an arbitary value - the intent is to give the meter enough time to
                                                // complete it's work

                            ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                                  intIndex * FWDLBlockSize,
                                                                  streamPSEM.ToArray());
                        }
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    // If any write failed, give up and clear the pending table
                    if (PSEMResponse.Ok != ProtocolResponse)
                    {
                        // Write failed, so clear the pending table
                        ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                       PendingEventRecord.PendingEventCode.NonTimeTrigger);

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                // Log it and pass it up
                OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }
        /// <summary>
        /// Downloads the firmware file to the meter and activates it.
        /// The activation will cause the meter to drop the psem task so meter log off must
        /// follow this function call on success.  This method supports resuming
        /// a previous failed FWDL.
        /// </summary>
        /// <param name="path">Complete file path of the firmware file</param>
        /// <param name="usBlockIndex">Dual purpose parameter. The passed in value indicates
        /// which block to begin downloading. The passed out parameter indicates which block to
        /// resume downloading in case there was a failure. This can then passed in again to
        /// restart the download at the point where it left off.</param>
        /// <param name="blnRetry">Whether or not to leave the FWDL in a state
        /// to permit subsequent retries at point of faliure. If false the pending table
        /// will be cleared on failure.</param>
        /// <param name="blnActivate">Whether or not to activate the firmware.</param>
        /// <returns>Itron.Metering.Device.FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version ID Number Description
        // -------- --- ------- -- ------ ---------------------------------------
        // 08/28/06 AF  7.35.00    N/A    Created
        // 09/15/06 AF  7.35.00    N/A    Added Catch for TimeOutException
        // 10/18/06 AF  7.40.00    N/A    Removed wait within the main loop
        // 05/13/08 AF  1.50.24           Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39           Added M2 Gateway support
        // 08/18/11 AF  2.52.05           Added support for authentication using a hash code
        // 08/26/11 AF  2.52.08           Added support for Cisco f/w
        // 09/22/11 AF  2.52.21    N/A    Added support for Cisco config file f/w d/l - TODO remove when no longer needed
        // 10/12/11 AF  2.53.00           Changed the Cisco Comm fw enum name
        // 03/22/12 JJJ 2.60.xx           Added support for ChoiceConnect FW
        // 05/10/12 JJJ 2.60.xx           Tweaked FW Type passed to AuthenticateFWDL if ChoiceConnect, make RFLAN
        // 04/19/13 jrf 2.80.21 TQ 7639   Adding support for ICS comm module FWDL.
        // 07/08/13 jrf 2.80.51 TC 13201  Created to support retries of FWDL.
        // 07/15/13 jrf 2.80.?? TC 15062  Added parameter to control activation.
        // 08/22/13 jrf 2.85.26 WR 420902 Decrementing the block index on a failed block write, so
        //                                on a retry we will start back on the correct block.
        // 11/07/13 AF  3.50.02 TQ9508,9514 Have to activate the pending table using mfg proc 69 rather than std proc 13
        //                                  for I-210 and kV2c ICM firmware
        //  11/15/13 AF  3.50.03	    Class re-architecture - removed code specific to ICS_Gateway
        // 12/02/13 jrf 3.50.10            Refactored code used to modify the FWType byte to it's own method.
        // 02/07/14 jrf 3.50.32 WR 419257  Modified to use a dynamic FWDL block size based on the negotiated
        //                                 PSEM packet size.
        // 08/24/16 PGH 4.70.15 701952     Added HAN OTA Firmware
        // 02/06/17 AF  4.71.07 743128     Added supported for ICM modem firmware
        // 03/10/17 AF  4.71.09 749833     Renamed the firmware type because 37 is for Verizon LTE only
        // 12/05/17 AF  4.73.00 Task 469253 Added back the verizon modem fwdl
        // 12/06/17 AF  4.73.00 Task 469254 Added ATT/Rogers modem fwdl
        //
        public FWDownloadResult DownloadFW(string path, ref ushort usBlockIndex, bool blnRetry = false, bool blnActivate = true)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            //A non-zero starting block means we are need to pick up were we left off.
            bool blnResumeFWDL = (0 != usBlockIndex);

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                if (true == blnResumeFWDL)
                {
                    Result = FWDownloadResult.SUCCESS;
                }
                else
                {
                    // Tell the meter to enter firmware download mode
                    Result = EnterFirmwareDownloadMode(path);
                }


                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    case (byte)FirmwareType.ICSFW:
                    case (byte)FirmwareType.ICS_MODEM_FW_Sierra_Verizon_LTE:
                    case (byte)FirmwareType.ICS_MODEM_FW_Sierra_ATT_Rogers_Bell_LTE:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HAN_OTA_FW:
                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false,
                                       byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / FWDLBlockSize);

                    if (streamFile.Length != FWDLBlockSize * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = FWDLBlockSize;

                    for (;
                         (usBlockIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         usBlockIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == usBlockIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % FWDLBlockSize);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = FWDLBlockSize;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, usBlockIndex * FWDLBlockSize, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              usBlockIndex * FWDLBlockSize,
                                                              streamPSEM.ToArray());
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    //Check on success and then activate the table
                    if (PSEMResponse.Ok == ProtocolResponse)
                    {
                        if (FWDLLogSupported)
                        {
                            //Construct the hash code and call the procedure to authenticate
                            CENTRON_AMI_FW_File FWFile = new CENTRON_AMI_FW_File(path);
                            byte[] FWHashCode          = FWFile.HashCode;

                            if ((bybuffer[9] != (byte)FirmwareType.ICSFW) && (bybuffer[9] != (byte)FirmwareType.ICS_MODEM_FW_Sierra_Verizon_LTE))
                            {
                                //Some devices may require this byte to be adjusted.
                                bybuffer[9] = SelectFWTypeByte(bybuffer[9]);

                                ProcResult = AuthenticateFWDL(idTable, bybuffer[9], FWHashCode);
                            }
                            else //Skip authenticate for ICS comm module and modem FWDL
                            {
                                ProcResult = ProcedureResultCodes.COMPLETED;
                            }
                        }
                        else
                        {
                            ProcResult = ProcedureResultCodes.COMPLETED;
                        }

                        if (ProcResult == ProcedureResultCodes.COMPLETED)
                        {
                            if (true == blnActivate)
                            {
                                // Activate the pending table using std proc 13
                                ProcResult = ActivatePendingTable(false, false, byEventNumber,
                                                                  PendingEventRecord.PendingEventCode.NonTimeTrigger);

                                Result = TranslateProcedureResult(ProcResult);
                            }
                        }
                        else
                        {
                            if (false == blnRetry)
                            {
                                //We couldn't authenticate using the hash code so activation will fail
                                ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                               PendingEventRecord.PendingEventCode.NonTimeTrigger);
                            }

                            //TODO - not sure this is the correct error
                            Result = FWDownloadResult.SECURITY_ERROR;
                        }

                        OnStepProgress(new ProgressEventArgs());
                    }
                    else //PSEMResponse.Ok != ProtocolResponse
                    {
                        //Decrement the block index so we make sure we restart on the block that we failed on.
                        usBlockIndex--;

                        if (false == blnRetry)
                        {
                            // Write failed, so clear the pending table
                            ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                           PendingEventRecord.PendingEventCode.NonTimeTrigger);
                        }

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                if (false == blnRetry)
                {
                    // Log it and pass it up
                    OnHideProgress(new EventArgs());
                    m_Logger.WriteException(this, e);
                    throw e;
                }
                else
                {
                    Result = FWDownloadResult.WRITE_ERROR;
                }
            }

            return(Result);
        }
示例#7
0
        /// <summary>
        /// Downloads the firmware file to the meter and activates it.
        /// On download failure, the pending table is cleared.  The activation
        /// will cause the meter to drop the psem task so meter log off must
        /// follow this function call
        /// </summary>
        /// <param name="path">Complete file path of the firmware file</param>
        /// <returns>Itron.Metering.Device.FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 08/28/06 AF  7.35.00  N/A   Created
        // 09/15/06 AF  7.35.00  N/A   Added Catch for TimeOutException
        // 10/18/06 AF  7.40.00  N/A   Removed wait within the main loop
        // 05/13/08 AF  1.50.24        Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39        Added M2 Gateway support
        // 08/18/11 AF  2.52.05        Added support for authentication using a hash code
        // 08/26/11 AF  2.52.08        Added support for Cisco f/w
        // 09/22/11 AF  2.52.21  N/A   Added support for Cisco config file f/w d/l - TODO remove when no longer needed
        // 10/12/11 AF  2.53.00        Changed the Cisco Comm fw enum name
        // 03/22/12 JJJ 2.60.xx        Added support for ChoiceConnect FW
        // 05/10/12 JJJ 2.60.xx        Tweaked FW Type passed to AuthenticateFWDL if ChoiceConnect, make RFLAN
        //
        public FWDownloadResult DownloadFW(string path)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            ushort intIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                // Tell the meter to enter firmware download mode
                Result = EnterFirmwareDownloadMode(path);

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false,
                                       byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / BLOCK_SIZE);

                    if (streamFile.Length != BLOCK_SIZE * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = BLOCK_SIZE;

                    for (intIndex = 0;
                         (intIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         intIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == intIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % BLOCK_SIZE);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = BLOCK_SIZE;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, intIndex * BLOCK_SIZE, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * BLOCK_SIZE,
                                                              streamPSEM.ToArray());
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    //Check on success and then activate the table
                    if (PSEMResponse.Ok == ProtocolResponse)
                    {
                        if (FWDLLogSupported)
                        {
                            //Construct the hash code and call the procedure to authenticate
                            CENTRON_AMI_FW_File FWFile = new CENTRON_AMI_FW_File(path);
                            byte[] FWHashCode          = FWFile.HashCode;

                            // if MSM ChoiceConnect meter and ChoiceConnect FWDL request, spoof RFLAN FWDL
                            CENTRON_AMI AmiDevice = this as CENTRON_AMI;
                            if (AmiDevice != null &&
                                bybuffer[9] == (byte)FirmwareType.ChoiceConnectFW &&
                                AmiDevice.IsChoiceConnectMsmMeter)
                            {
                                bybuffer[9] = (byte)FirmwareType.RFLANFW;
                            }

                            ProcResult = AuthenticateFWDL(idTable, bybuffer[9], FWHashCode);
                        }
                        else
                        {
                            ProcResult = ProcedureResultCodes.COMPLETED;
                        }

                        if (ProcResult == ProcedureResultCodes.COMPLETED)
                        {
                            // Activate the pending table
                            ProcResult = ActivatePendingTable(false, false, byEventNumber,
                                                              PendingEventRecord.PendingEventCode.NonTimeTrigger);

                            Result = TranslateProcedureResult(ProcResult);
                        }
                        else
                        {
                            //We couldn't authenticate using the hash code so activation will fail
                            ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                           PendingEventRecord.PendingEventCode.NonTimeTrigger);

                            //TODO - not sure this is the correct error
                            Result = FWDownloadResult.SECURITY_ERROR;
                        }

                        OnStepProgress(new ProgressEventArgs());
                    }
                    else
                    {
                        // Write failed, so clear the pending table
                        ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                       PendingEventRecord.PendingEventCode.NonTimeTrigger);

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                // Log it and pass it up
                OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }
示例#8
0
        /// <summary>
        /// Performs a manufacturer procedure 37 to tell the meter to get ready for
        /// firmware download
        /// </summary>
        /// <param name="strFilePath">path to the f/w file to download</param>
        /// <returns>ProcedureResultCodes</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 08/21/06 AF  7.35.00 N/A     Created
        // 09/05/06 AF  7.35.00         Corrected the order of the data in the
        //                             procedure parameters
        // 10/04/06 AF  7.40.00 N/A     Moved from CENTRON_AMI.cs
        // 07/31/07 KRC 8.10.16 3058    Adding more detailed errors;
        // 01/23/12 RCG 2.53.33 191589 Adding the Device Class to the parameter list in order to support Gas Ranger Extended FW DL
        // 05/10/12 JJJ 2.60.xx        Tweaking FW Type so Register sees ChoiceConnect FW as RFLAN FW

        private FWDownloadResult EnterFirmwareDownloadMode(string strFilePath)
        {
            //Construct the parameters for mfg proc 37 and execute the procedure
            FileInfo fi = new FileInfo(strFilePath);
            bool     bIsThirdPartyFWDownload = this is M2_Gateway == false && VersionChecker.CompareTo(FWRevision, CENTRON_AMI.VERSION_LITHIUM_3_12) >= 0;

            byte[] bybuf        = new byte[FW_HEADER_LENGTH];
            byte[] byParameters = null;
            byte[] byImageSize  = new byte[IMAGE_SIZE_FIELD_LEN];
            byte[] byChunkSize  = new byte[CHUNK_SIZE_FIELD_LEN];
            byte[] ProcResponse;
            ProcedureResultCodes ProcResult = ProcedureResultCodes.INVALID_PARAM;
            FWDownloadResult     FWResult   = FWDownloadResult.UNKNOWN_DRIVER_ERROR;

            try
            {
                m_Logger.WriteLine(Logger.LoggingLevel.Functional,
                                   "Initiating Firmware Download");

                // Most of the procedure parameters are in the f/w file header
                FileStream fs = new FileStream(strFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Read(bybuf, 0, FW_HEADER_LENGTH);
                fs.Close();

                if (bIsThirdPartyFWDownload == true)
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_THIRD_PARTY_LEN];
                }
                else
                {
                    byParameters = new byte[INIT_FW_DOWNLOAD_PARAM_LEN];
                }

                byParameters.Initialize();

                // CRC LSB first
                byParameters[0] = bybuf[1];
                byParameters[1] = bybuf[0];

                // Retrieve the parameters out of the header
                Array.Copy(bybuf, 5, byParameters, 2, 9);

                // if MSM ChoiceConnect meter and ChoiceConnect FWDL request, spoof RFLAN FWDL
                CENTRON_AMI AmiDevice = this as CENTRON_AMI;
                if (AmiDevice != null &&
                    byParameters[6] == (byte)FirmwareType.ChoiceConnectFW &&
                    AmiDevice.IsChoiceConnectMsmMeter)
                {
                    byParameters[6] = (byte)FirmwareType.RFLANFW;
                }

                // image size
                byImageSize = BitConverter.GetBytes((int)fi.Length);
                Array.Copy(byImageSize, 0, byParameters, 11, IMAGE_SIZE_FIELD_LEN);

                // chunk size -- 64 or 128 bytes; hard coded here to 128
                byChunkSize = BitConverter.GetBytes(BLOCK_SIZE);
                Array.Copy(byChunkSize, 0, byParameters, 15, CHUNK_SIZE_FIELD_LEN);

                if (bIsThirdPartyFWDownload == true)
                {
                    // The Device Class is a required parameter for 3rd Party Firmware Downloads
                    // The meter needs this in the reverse order that it is stored in the firmware file
                    byParameters[17] = bybuf[17];
                    byParameters[18] = bybuf[16];
                    byParameters[19] = bybuf[15];
                    byParameters[20] = bybuf[14];
                }

                ProcResult = ExecuteProcedure(Procedures.INITIATE_FW_LOADER_SETUP,
                                              byParameters,
                                              out ProcResponse);


                if (ProcedureResultCodes.INVALID_PARAM == ProcResult)
                {
                    // The Firmware load did not work.  At some point during development they added
                    //  more detail in the Response, so we can read the byte and see what the error is
                    switch (ProcResponse[0])
                    {
                    case 1:
                        FWResult = FWDownloadResult.FW_IMAGE_TOO_BIG;
                        break;

                    case 2:
                        FWResult = FWDownloadResult.HW_REVISION_OUTSIDE_RANGE;
                        break;

                    case 3:
                        FWResult = FWDownloadResult.HW_VERSION_OUTSIDE_RANGE;
                        break;

                    case 10:
                        FWResult = FWDownloadResult.FW_TYPE_IS_INVALID;
                        break;

                    case 11:
                        FWResult = FWDownloadResult.ZIGBEE_FW_TYPE_INVALID;
                        break;

                    default:
                        FWResult = FWDownloadResult.INVALID_CONFIG;
                        break;
                    }
                }
                else
                {
                    FWResult = TranslateProcedureResult(ProcResult);
                }
            }
            catch (Exception e)
            {
                // Log it and pass it up
                m_Logger.WriteException(this, e);
                throw (e);
            }


            return(FWResult);
        }
示例#9
0
        /// <summary>
        /// Downloads the firmware file to the device but does NOT
        /// activate.  On download failure, the pending table is cleared.
        /// </summary>
        /// <param name="path">Complete path to the firmware file</param>
        /// <returns>FWDownloadResult</returns>
        // Revision History
        // MM/DD/YY who Version Issue# Description
        // -------- --- ------- ------ ---------------------------------------
        // 10/05/06 AF  7.35.00  N/A   Created
        // 10/18/06 AF  7.40.00  N/A   Removed wait within the main loop
        // 05/13/08 AF  1.50.24        Removed IFirmwareDownload from the method name
        // 04/19/10 AF  2.40.39        Added M2 Gateway support
        // 03/21/12 JJJ 2.60.xx        Added support for ChoiceConnect FW
        // 08/17/12 AF  2.60.55        Added support for RF Mesh FW and RF Mesh Config
        //
        public FWDownloadResult DownloadFWNoActivate(string path)
        {
            FWDownloadResult     Result           = FWDownloadResult.UNKNOWN_DRIVER_ERROR;
            ProcedureResultCodes ProcResult       = ProcedureResultCodes.INVALID_PARAM;
            PSEMResponse         ProtocolResponse = PSEMResponse.Ok;
            byte   byEventNumber  = 0;
            ushort idTable        = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
            ushort usNumberChunks = 0;
            ushort intIndex;

            System.IO.FileStream   streamFile;
            System.IO.MemoryStream streamHeader = new System.IO.MemoryStream();
            System.IO.MemoryStream streamPSEM   = new System.IO.MemoryStream();

            try
            {
                Result = EnterFirmwareDownloadMode(path);

                if (FWDownloadResult.SUCCESS != Result)
                {
                    m_Logger.WriteLine(Logger.LoggingLevel.Detailed,
                                       "Initiate F/W Download procedure failed with result = "
                                       + Result);
                }
                else
                {
                    // Meter is ready to receive the firmware file
                    streamFile = new System.IO.FileStream(path, System.IO.FileMode.Open, FileAccess.Read);
                    byte[] bybuffer = new byte[streamFile.Length];

                    streamFile.Read(bybuffer, 0, (int)streamFile.Length);
                    streamFile.Position = 0;

                    switch (bybuffer[9])
                    {
                    case (byte)FirmwareType.RegisterFW:
                    case (byte)FirmwareType.M2GTWY:
                    case (byte)FirmwareType.DisplayFW:
                    {
                        byEventNumber = REGISTER_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.RegisterFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.ZigbeeFW:
                    {
                        byEventNumber = ZIGBEE_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.RFLANFW:
                    case (byte)FirmwareType.PLANFW:
                    case (byte)FirmwareType.CiscoCommFW:
                    case (byte)FirmwareType.CiscoCfgFW:
                    case (byte)FirmwareType.ChoiceConnectFW:
                    {
                        byEventNumber = COMM_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.CommModuleFWTbl | PENDING_BIT;
                        break;
                    }

                    case (byte)FirmwareType.HANDevFW:
                    {
                        byEventNumber = HAN_DEV_EVENT_NUMBER;
                        idTable       = (ushort)PendingTableIds.HANDeviceFWTbl | PENDING_BIT;
                        break;
                    }

                    default:
                    {
                        throw new NotImplementedException("Table not yet supported");
                    }
                    }

                    BuildPendingHeader(ref streamHeader, false, false,
                                       byEventNumber, PendingEventRecord.PendingEventCode.NonTimeTrigger);

                    usNumberChunks = (ushort)(streamFile.Length / BLOCK_SIZE);

                    if (streamFile.Length != BLOCK_SIZE * usNumberChunks)
                    {
                        usNumberChunks++;
                    }

                    OnShowProgress(new ShowProgressEventArgs(1, usNumberChunks + 1,
                                                             "Firmware Download",
                                                             "Downloading..."));

                    ushort usSendSize = BLOCK_SIZE;

                    for (intIndex = 0;
                         (intIndex < usNumberChunks) && (PSEMResponse.Ok == ProtocolResponse);
                         intIndex++)
                    {
                        // The last chunk could be smaller
                        if (usNumberChunks - 1 == intIndex)
                        {
                            usSendSize = (ushort)(streamFile.Length % BLOCK_SIZE);
                            // If no remainder then it is a full packet
                            if (0 == usSendSize)
                            {
                                usSendSize = BLOCK_SIZE;
                            }
                        }

                        streamHeader.Position = 0;
                        streamPSEM.Position   = 0;
                        streamPSEM.SetLength(0);
                        streamHeader.WriteTo(streamPSEM);
                        streamPSEM.Write(bybuffer, intIndex * BLOCK_SIZE, usSendSize);

                        ProtocolResponse = m_PSEM.OffsetWrite((ushort)idTable,
                                                              intIndex * BLOCK_SIZE,
                                                              streamPSEM.ToArray());
                        OnStepProgress(new ProgressEventArgs());
                    }

                    // Translate Protocol result
                    Result = TranslateProtocolResult(ProtocolResponse);

                    streamFile.Close();

                    // If any write failed, give up and clear the pending table
                    if (PSEMResponse.Ok != ProtocolResponse)
                    {
                        // Write failed, so clear the pending table
                        ProcResult = ClearPendingTable(false, false, byEventNumber,
                                                       PendingEventRecord.PendingEventCode.NonTimeTrigger);

                        Result = FWDownloadResult.WRITE_ERROR;
                    }
                    OnHideProgress(new EventArgs());
                }
            }

            catch (Exception e)
            {
                // Log it and pass it up
                OnHideProgress(new EventArgs());
                m_Logger.WriteException(this, e);
                throw e;
            }

            return(Result);
        }