LCOV - code coverage report
Current view: top level - src/tc_tm - tc_acceptance.c (source / functions) Hit Total Coverage
Test: trace.info Lines: 98 154 63.6 %
Date: 2023-02-20 11:47:18 Functions: 6 9 66.7 %

          Line data    Source code
       1             : /*------------------------------------------------------------------------------
       2             : --  Solar Orbiter's Low Frequency Receiver Flight Software (LFR FSW),
       3             : --  This file is a part of the LFR FSW
       4             : --  Copyright (C) 2012-2018, Plasma Physics Laboratory - CNRS
       5             : --
       6             : --  This program is free software; you can redistribute it and/or modify
       7             : --  it under the terms of the GNU General Public License as published by
       8             : --  the Free Software Foundation; either version 2 of the License, or
       9             : --  (at your option) any later version.
      10             : --
      11             : --  This program is distributed in the hope that it will be useful,
      12             : --  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : --  GNU General Public License for more details.
      15             : --
      16             : --  You should have received a copy of the GNU General Public License
      17             : --  along with this program; if not, write to the Free Software
      18             : --  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      19             : -------------------------------------------------------------------------------*/
      20             : /*--                  Author : Paul Leroy
      21             : --                   Contact : Alexis Jeandet
      22             : --                      Mail : alexis.jeandet@lpp.polytechnique.fr
      23             : ----------------------------------------------------------------------------*/
      24             : /** Functions related to TeleCommand acceptance.
      25             :  *
      26             :  * @file
      27             :  * @author P. LEROY
      28             :  *
      29             :  * A group of functions to handle TeleCommands parsing.\n
      30             :  *
      31             :  */
      32             : 
      33             : #include "tc_tm/tc_acceptance.h"
      34             : #include <stdio.h>
      35             : 
      36             : unsigned int lookUpTableForCRC[CONST_256] = { 0 };
      37             : 
      38             : //**********************
      39             : // GENERAL USE FUNCTIONS
      40           0 : unsigned int Crc_opt(unsigned char D, unsigned int Chk)
      41             : {
      42             :     /** This function generate the CRC for one byte and returns the value of the new syndrome.
      43             :      *
      44             :      * @param D is the current byte of data.
      45             :      * @param Chk is the current syndrom value.
      46             :      *
      47             :      * @return the value of the new syndrome on two bytes.
      48             :      *
      49             :      */
      50             : 
      51        5472 :     return (((Chk << SHIFT_1_BYTE) & BYTE0_MASK)
      52        2736 :         ^ lookUpTableForCRC[((Chk >> SHIFT_1_BYTE) ^ D) & BYTE1_MASK]);
      53             : }
      54             : 
      55           1 : void initLookUpTableForCRC(void)
      56             : {
      57             :     /** This function is used to initiates the look-up table for fast CRC computation.
      58             :      *
      59             :      * The global table lookUpTableForCRC[256] is initiated.
      60             :      *
      61             :      */
      62             :     unsigned int tmp;
      63             : 
      64         257 :     for (unsigned int i = 0; i < CONST_256; i++)
      65             :     {
      66         256 :         tmp = 0;
      67         256 :         if ((i & BIT_0) != 0)
      68             :         {
      69         128 :             tmp = tmp ^ CONST_CRC_0;
      70             :         }
      71         256 :         if ((i & BIT_1) != 0)
      72             :         {
      73         128 :             tmp = tmp ^ CONST_CRC_1;
      74             :         }
      75         256 :         if ((i & BIT_2) != 0)
      76             :         {
      77         128 :             tmp = tmp ^ CONST_CRC_2;
      78             :         }
      79         256 :         if ((i & BIT_3) != 0)
      80             :         {
      81         128 :             tmp = tmp ^ CONST_CRC_3;
      82             :         }
      83         256 :         if ((i & BIT_4) != 0)
      84             :         {
      85         128 :             tmp = tmp ^ CONST_CRC_4;
      86             :         }
      87         256 :         if ((i & BIT_5) != 0)
      88             :         {
      89         128 :             tmp = tmp ^ CONST_CRC_5;
      90             :         }
      91         256 :         if ((i & BIT_6) != 0)
      92             :         {
      93         128 :             tmp = tmp ^ CONST_CRC_6;
      94             :         }
      95         256 :         if ((i & BIT_7) != 0)
      96             :         {
      97         128 :             tmp = tmp ^ CONST_CRC_7;
      98             :         }
      99         256 :         lookUpTableForCRC[i] = tmp;
     100             :     }
     101           1 : }
     102             : 
     103           0 : void GetCRCAsTwoBytes(
     104             :     const unsigned char* data, unsigned char* crcAsTwoBytes, unsigned int sizeOfData)
     105             : {
     106             :     /** This function calculates a two bytes Cyclic Redundancy Code.
     107             :      *
     108             :      * @param data points to a buffer containing the data on which to compute the CRC.
     109             :      * @param crcAsTwoBytes points points to a two bytes buffer in which the CRC is stored.
     110             :      * @param sizeOfData is the number of bytes of *data* used to compute the CRC.
     111             :      *
     112             :      * The specification of the Cyclic Redundancy Code is described in the following document:
     113             :      * ECSS-E-70-41-A.
     114             :      *
     115             :      */
     116             : 
     117          64 :     unsigned int Chk = CRC_RESET;
     118        2800 :     for (unsigned int j = 0; j < sizeOfData; j++)
     119             :     {
     120        5472 :         Chk = Crc_opt(data[j], Chk);
     121             :     }
     122          64 :     crcAsTwoBytes[0] = (unsigned char)(Chk >> SHIFT_1_BYTE);
     123          64 :     crcAsTwoBytes[1] = (unsigned char)(Chk & BYTE1_MASK);
     124           0 : }
     125             : 
     126             : //*********************
     127             : // ACCEPTANCE FUNCTIONS
     128          64 : int tc_parser(const ccsdsTelecommandPacket_t* const TCPacket, unsigned int estimatedPacketLength,
     129             :     unsigned char* computed_CRC)
     130             : {
     131             :     /** This function parses TeleCommands.
     132             :      *
     133             :      * @param TC points to the TeleCommand that will be parsed.
     134             :      * @param estimatedPacketLength is the PACKET_LENGTH field calculated from the effective length
     135             :      * of the received packet.
     136             :      *
     137             :      * @return Status code of the parsing.
     138             :      *
     139             :      * The parsing checks:
     140             :      * - process id
     141             :      * - category
     142             :      * - length: a global check is performed and a per subtype check also
     143             :      * - type
     144             :      * - subtype
     145             :      * - crc
     146             :      *
     147             :      */
     148             : 
     149             :     int status;
     150             :     int status_crc;
     151             :     unsigned char pid;
     152             :     unsigned char category;
     153             :     unsigned int packetLength;
     154             :     unsigned char packetType;
     155             :     unsigned char packetSubtype;
     156             :     unsigned char sid;
     157             : 
     158          64 :     status = CCSDS_TM_VALID;
     159             : 
     160             :     // APID check *** APID on 2 bytes
     161         128 :     pid = ((TCPacket->packetID[0] & BITS_PID_0) << SHIFT_4_BITS)
     162          64 :         + ((TCPacket->packetID[1] >> SHIFT_4_BITS)
     163             :             & BITS_PID_1); // PID = 11 *** 7 bits xxxxx210 7654xxxx
     164          64 :     category
     165          64 :         = (TCPacket->packetID[1] & BITS_CAT); // PACKET_CATEGORY = 12 *** 4 bits xxxxxxxx xxxx3210
     166          64 :     packetLength = (TCPacket->packetLength[0] * CONST_256) + TCPacket->packetLength[1];
     167          64 :     packetType = TCPacket->serviceType;
     168          64 :     packetSubtype = TCPacket->serviceSubType;
     169          64 :     sid = TCPacket->sourceID;
     170             : 
     171          64 :     if (pid != CCSDS_PROCESS_ID) // CHECK THE PROCESS ID
     172             :     {
     173           0 :         status = ILLEGAL_APID;
     174             :     }
     175             :     // CHECK THE CATEGORY
     176          64 :     if (status == CCSDS_TM_VALID && category != CCSDS_PACKET_CATEGORY)
     177             :     {
     178           0 :         status = ILLEGAL_APID;
     179             :     }
     180             :     // CHECK THE PACKET_LENGTH FIELD AND THE ESTIMATED PACKET_LENGTH COMPLIANCE
     181          64 :     if (status == CCSDS_TM_VALID && packetLength != estimatedPacketLength)
     182             : 
     183             :     {
     184           0 :         status = WRONG_LEN_PKT;
     185             :     }
     186             :     // CHECK THAT THE PACKET DOES NOT EXCEED THE MAX SIZE
     187          64 :     if (status == CCSDS_TM_VALID && packetLength > CCSDS_TC_PKT_MAX_SIZE)
     188             :     {
     189           0 :         status = WRONG_LEN_PKT;
     190             :     }
     191          64 :     if (status == CCSDS_TM_VALID) // CHECK THE TYPE
     192             :     {
     193         128 :         status = tc_check_type(packetType);
     194             :     }
     195          64 :     if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE
     196             :     {
     197          64 :         status = tc_check_type_subtype(packetType, packetSubtype);
     198             :     }
     199          64 :     if (status == CCSDS_TM_VALID) // CHECK THE SID
     200             :     {
     201          64 :         status = tc_check_sid(sid);
     202             :     }
     203          64 :     if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE AND LENGTH COMPLIANCE
     204             :     {
     205          64 :         status = tc_check_length(packetSubtype, packetLength);
     206             :     }
     207          64 :     status_crc = tc_check_crc(TCPacket, estimatedPacketLength, computed_CRC);
     208          64 :     if (status == CCSDS_TM_VALID) // CHECK CRC
     209             :     {
     210          64 :         status = status_crc;
     211             :     }
     212             : 
     213          64 :     return status;
     214             : }
     215             : 
     216           0 : int tc_check_type(unsigned char packetType)
     217             : {
     218             :     /** This function checks that the type of a TeleCommand is valid.
     219             :      *
     220             :      * @param packetType is the type to check.
     221             :      *
     222             :      * @return Status code CCSDS_TM_VALID or ILL_TYPE.
     223             :      *
     224             :      */
     225             : 
     226             :     int status;
     227             : 
     228          64 :     status = ILL_TYPE;
     229             : 
     230          64 :     if ((packetType == TC_TYPE_GEN) || (packetType == TC_TYPE_TIME))
     231             :     {
     232          64 :         status = CCSDS_TM_VALID;
     233             :     }
     234             : 
     235          64 :     return status;
     236             : }
     237             : 
     238          64 : int tc_check_type_subtype(unsigned char packetType, unsigned char packetSubType)
     239             : {
     240             :     /** This function checks that the subtype of a TeleCommand is valid and coherent with the type.
     241             :      *
     242             :      * @param packetType is the type of the TC.
     243             :      * @param packetSubType is the subtype to check.
     244             :      *
     245             :      * @return Status code CCSDS_TM_VALID or ILL_SUBTYPE.
     246             :      *
     247             :      */
     248             : 
     249             :     int status;
     250             : 
     251          64 :     switch (packetType)
     252             :     {
     253             :         case TC_TYPE_GEN:
     254         456 :             if ((packetSubType == TC_SUBTYPE_RESET) || (packetSubType == TC_SUBTYPE_LOAD_COMM)
     255         127 :                 || (packetSubType == TC_SUBTYPE_LOAD_NORM)
     256          63 :                 || (packetSubType == TC_SUBTYPE_LOAD_BURST)
     257          63 :                 || (packetSubType == TC_SUBTYPE_LOAD_SBM1)
     258         126 :                 || (packetSubType == TC_SUBTYPE_LOAD_SBM2) || (packetSubType == TC_SUBTYPE_DUMP)
     259          88 :                 || (packetSubType == TC_SUBTYPE_ENTER) || (packetSubType == TC_SUBTYPE_UPDT_INFO)
     260          50 :                 || (packetSubType == TC_SUBTYPE_EN_CAL) || (packetSubType == TC_SUBTYPE_DIS_CAL)
     261          50 :                 || (packetSubType == TC_SUBTYPE_LOAD_K) || (packetSubType == TC_SUBTYPE_DUMP_K)
     262          25 :                 || (packetSubType == TC_SUBTYPE_LOAD_FBINS)
     263             :                 || (packetSubType == TC_SUBTYPE_LOAD_FILTER_PAR))
     264             :             {
     265          64 :                 status = CCSDS_TM_VALID;
     266             :             }
     267             :             else
     268             :             {
     269           0 :                 status = ILL_SUBTYPE;
     270             :             }
     271             :             break;
     272             : 
     273             :         case TC_TYPE_TIME:
     274           0 :             if (packetSubType == TC_SUBTYPE_UPDT_TIME)
     275             :             {
     276           0 :                 status = CCSDS_TM_VALID;
     277             :             }
     278             :             else
     279             :             {
     280           0 :                 status = ILL_SUBTYPE;
     281             :             }
     282             :             break;
     283             : 
     284             :         default:
     285           0 :             status = ILL_SUBTYPE;
     286             :             break;
     287             :     }
     288             : 
     289          64 :     return status;
     290             : }
     291             : 
     292          64 : int tc_check_sid(unsigned char sid)
     293             : {
     294             :     /** This function checks that the sid of a TeleCommand is valid.
     295             :      *
     296             :      * @param sid is the sid to check.
     297             :      *
     298             :      * @return Status code CCSDS_TM_VALID or CORRUPTED.
     299             :      *
     300             :      */
     301             : 
     302          64 :     int status = WRONG_SRC_ID;
     303             : 
     304          67 :     if ((sid == SID_TC_MISSION_TIMELINE) || (sid == SID_TC_TC_SEQUENCES)
     305             :         || (sid == SID_TC_RECOVERY_ACTION_CMD) || (sid == SID_TC_BACKUP_MISSION_TIMELINE)
     306          65 :         || (sid == SID_TC_DIRECT_CMD) || (sid == SID_TC_SPARE_GRD_SRC1)
     307           2 :         || (sid == SID_TC_SPARE_GRD_SRC2) || (sid == SID_TC_OBCP) || (sid == SID_TC_SYSTEM_CONTROL)
     308           1 :         || (sid == SID_TC_AOCS) || (sid == SID_TC_RPW_INTERNAL))
     309             :     {
     310          64 :         status = CCSDS_TM_VALID;
     311             :     }
     312             : 
     313          64 :     return status;
     314             : }
     315             : 
     316          64 : int tc_check_length(unsigned char packetSubType, unsigned int length)
     317             : {
     318             :     /** This function checks that the subtype and the length are compliant.
     319             :      *
     320             :      * @param packetSubType is the subtype to check.
     321             :      * @param length is the length to check.
     322             :      *
     323             :      * @return Status code CCSDS_TM_VALID or ILL_TYPE.
     324             :      *
     325             :      */
     326             : 
     327          64 :     int status = CCSDS_TM_VALID;
     328             : 
     329          64 :     switch (packetSubType)
     330             :     {
     331             :         case TC_SUBTYPE_RESET:
     332           1 :             if (length != (TC_LEN_RESET - CCSDS_TC_TM_PACKET_OFFSET))
     333             :             {
     334           0 :                 status = WRONG_LEN_PKT;
     335             :             }
     336             :             else
     337             :             {
     338           1 :                 status = CCSDS_TM_VALID;
     339             :             }
     340             :             break;
     341             :         case TC_SUBTYPE_LOAD_COMM:
     342           0 :             if (length != (TC_LEN_LOAD_COMM - CCSDS_TC_TM_PACKET_OFFSET))
     343             :             {
     344           0 :                 status = WRONG_LEN_PKT;
     345             :             }
     346             :             else
     347             :             {
     348           0 :                 status = CCSDS_TM_VALID;
     349             :             }
     350             :             break;
     351             :         case TC_SUBTYPE_LOAD_NORM:
     352           0 :             if (length != (TC_LEN_LOAD_NORM - CCSDS_TC_TM_PACKET_OFFSET))
     353             :             {
     354           0 :                 status = WRONG_LEN_PKT;
     355             :             }
     356             :             else
     357             :             {
     358           0 :                 status = CCSDS_TM_VALID;
     359             :             }
     360             :             break;
     361             :         case TC_SUBTYPE_LOAD_BURST:
     362           0 :             if (length != (TC_LEN_LOAD_BURST - CCSDS_TC_TM_PACKET_OFFSET))
     363             :             {
     364           0 :                 status = WRONG_LEN_PKT;
     365             :             }
     366             :             else
     367             :             {
     368           0 :                 status = CCSDS_TM_VALID;
     369             :             }
     370             :             break;
     371             :         case TC_SUBTYPE_LOAD_SBM1:
     372           0 :             if (length != (TC_LEN_LOAD_SBM1 - CCSDS_TC_TM_PACKET_OFFSET))
     373             :             {
     374           0 :                 status = WRONG_LEN_PKT;
     375             :             }
     376             :             else
     377             :             {
     378           0 :                 status = CCSDS_TM_VALID;
     379             :             }
     380             :             break;
     381             :         case TC_SUBTYPE_LOAD_SBM2:
     382           0 :             if (length != (TC_LEN_LOAD_SBM2 - CCSDS_TC_TM_PACKET_OFFSET))
     383             :             {
     384           0 :                 status = WRONG_LEN_PKT;
     385             :             }
     386             :             else
     387             :             {
     388           0 :                 status = CCSDS_TM_VALID;
     389             :             }
     390             :             break;
     391             :         case TC_SUBTYPE_DUMP:
     392          26 :             if (length != (TC_LEN_DUMP - CCSDS_TC_TM_PACKET_OFFSET))
     393             :             {
     394           0 :                 status = WRONG_LEN_PKT;
     395             :             }
     396             :             else
     397             :             {
     398          26 :                 status = CCSDS_TM_VALID;
     399             :             }
     400             :             break;
     401             :         case TC_SUBTYPE_ENTER:
     402          12 :             if (length != (TC_LEN_ENTER - CCSDS_TC_TM_PACKET_OFFSET))
     403             :             {
     404           0 :                 status = WRONG_LEN_PKT;
     405             :             }
     406             :             else
     407             :             {
     408          12 :                 status = CCSDS_TM_VALID;
     409             :             }
     410             :             break;
     411             :         case TC_SUBTYPE_UPDT_INFO:
     412           0 :             if (length != (TC_LEN_UPDT_INFO - CCSDS_TC_TM_PACKET_OFFSET))
     413             :             {
     414           0 :                 status = WRONG_LEN_PKT;
     415             :             }
     416             :             else
     417             :             {
     418           0 :                 status = CCSDS_TM_VALID;
     419             :             }
     420             :             break;
     421             :         case TC_SUBTYPE_EN_CAL:
     422           0 :             if (length != (TC_LEN_EN_CAL - CCSDS_TC_TM_PACKET_OFFSET))
     423             :             {
     424           0 :                 status = WRONG_LEN_PKT;
     425             :             }
     426             :             else
     427             :             {
     428           0 :                 status = CCSDS_TM_VALID;
     429             :             }
     430             :             break;
     431             :         case TC_SUBTYPE_DIS_CAL:
     432           0 :             if (length != (TC_LEN_DIS_CAL - CCSDS_TC_TM_PACKET_OFFSET))
     433             :             {
     434           0 :                 status = WRONG_LEN_PKT;
     435             :             }
     436             :             else
     437             :             {
     438           0 :                 status = CCSDS_TM_VALID;
     439             :             }
     440             :             break;
     441             :         case TC_SUBTYPE_LOAD_K:
     442           0 :             if (length != (TC_LEN_LOAD_K - CCSDS_TC_TM_PACKET_OFFSET))
     443             :             {
     444           0 :                 status = WRONG_LEN_PKT;
     445             :             }
     446             :             else
     447             :             {
     448           0 :                 status = CCSDS_TM_VALID;
     449             :             }
     450             :             break;
     451             :         case TC_SUBTYPE_DUMP_K:
     452           0 :             if (length != (TC_LEN_DUMP_K - CCSDS_TC_TM_PACKET_OFFSET))
     453             :             {
     454           0 :                 status = WRONG_LEN_PKT;
     455             :             }
     456             :             else
     457             :             {
     458           0 :                 status = CCSDS_TM_VALID;
     459             :             }
     460             :             break;
     461             :         case TC_SUBTYPE_LOAD_FBINS:
     462           0 :             if (length != (TC_LEN_LOAD_FBINS - CCSDS_TC_TM_PACKET_OFFSET))
     463             :             {
     464           0 :                 status = WRONG_LEN_PKT;
     465             :             }
     466             :             else
     467             :             {
     468           0 :                 status = CCSDS_TM_VALID;
     469             :             }
     470             :             break;
     471             :         case TC_SUBTYPE_LOAD_FILTER_PAR:
     472          25 :             if (length != (TC_LEN_LOAD_FILTER_PAR - CCSDS_TC_TM_PACKET_OFFSET))
     473             :             {
     474           0 :                 status = WRONG_LEN_PKT;
     475             :             }
     476             :             else
     477             :             {
     478          25 :                 status = CCSDS_TM_VALID;
     479             :             }
     480             :             break;
     481             :         case TC_SUBTYPE_UPDT_TIME:
     482           0 :             if (length != (TC_LEN_UPDT_TIME - CCSDS_TC_TM_PACKET_OFFSET))
     483             :             {
     484           0 :                 status = WRONG_LEN_PKT;
     485             :             }
     486             :             else
     487             :             {
     488           0 :                 status = CCSDS_TM_VALID;
     489             :             }
     490             :             break;
     491             :         default: // if the subtype is not a legal value, return ILL_SUBTYPE
     492           0 :             status = ILL_SUBTYPE;
     493             :             break;
     494             :     }
     495             : 
     496          64 :     return status;
     497             : }
     498             : 
     499          64 : int tc_check_crc(const ccsdsTelecommandPacket_t* const TCPacket, unsigned int length,
     500             :     unsigned char* computed_CRC)
     501             : {
     502             :     /** This function checks the CRC validity of the corresponding TeleCommand packet.
     503             :      *
     504             :      * @param TCPacket points to the TeleCommand packet to check.
     505             :      * @param length is the length of the TC packet.
     506             :      *
     507             :      * @return Status code CCSDS_TM_VALID or INCOR_CHECKSUM.
     508             :      *
     509             :      */
     510             : 
     511          64 :     int status = CCSDS_TM_VALID;
     512          64 :     const unsigned char* const CCSDSContent = (const unsigned char*)TCPacket->packetID;
     513             : 
     514          64 :     GetCRCAsTwoBytes(CCSDSContent, computed_CRC,
     515             :         length + CCSDS_TC_TM_PACKET_OFFSET
     516             :             - BYTES_PER_CRC); // 2 CRC bytes removed from the calculation of the CRC
     517             : 
     518          64 :     if (computed_CRC[0] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC])
     519             :     {
     520           0 :         status = INCOR_CHECKSUM;
     521             :     }
     522          64 :     else if (computed_CRC[1] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - 1])
     523             :     {
     524           0 :         status = INCOR_CHECKSUM;
     525             :     }
     526             : 
     527          64 :     return status;
     528             : }

Generated by: LCOV version 1.14