GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/tc_acceptance.c Lines: 97 159 61.0 %
Date: 2018-10-29 14:12:44 Branches: 50 128 39.1 %

Line Branch Exec Source
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_acceptance.h"
34
#include <stdio.h>
35
36
unsigned int lookUpTableForCRC[CONST_256] = {0};
37
38
//**********************
39
// GENERAL USE FUNCTIONS
40
1612
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
1612
    return(((Chk << SHIFT_1_BYTE) & BYTE0_MASK)^lookUpTableForCRC [(((Chk >> SHIFT_1_BYTE)^D) & BYTE1_MASK)]);
52
}
53
54
1
void initLookUpTableForCRC( void )
55
{
56
    /** This function is used to initiates the look-up table for fast CRC computation.
57
     *
58
     * The global table lookUpTableForCRC[256] is initiated.
59
     *
60
     */
61
62
    unsigned int i;
63
    unsigned int tmp;
64
65
257
    for (i=0; i<CONST_256; i++)
66
    {
67
256
        tmp = 0;
68
256
        if((i & BIT_0) != 0) {
69
128
            tmp = tmp ^ CONST_CRC_0;
70
        }
71
256
        if((i & BIT_1) != 0) {
72
128
            tmp = tmp ^ CONST_CRC_1;
73
        }
74
256
        if((i & BIT_2) != 0) {
75
128
            tmp = tmp ^ CONST_CRC_2;
76
        }
77
256
        if((i & BIT_3) != 0) {
78
128
            tmp = tmp ^ CONST_CRC_3;
79
        }
80
256
        if((i & BIT_4) != 0) {
81
128
            tmp = tmp ^ CONST_CRC_4;
82
        }
83
256
        if((i & BIT_5) != 0) {
84
128
            tmp = tmp ^ CONST_CRC_5;
85
        }
86
256
        if((i & BIT_6) != 0) {
87
128
            tmp = tmp ^ CONST_CRC_6;
88
        }
89
256
        if((i & BIT_7) != 0) {
90
128
            tmp = tmp ^ CONST_CRC_7;
91
        }
92
256
        lookUpTableForCRC[i] = tmp;
93
    }
94
1
}
95
96
90
void GetCRCAsTwoBytes(unsigned char* data, unsigned char* crcAsTwoBytes, unsigned int sizeOfData)
97
{
98
    /** This function calculates a two bytes Cyclic Redundancy Code.
99
     *
100
     * @param data points to a buffer containing the data on which to compute the CRC.
101
     * @param crcAsTwoBytes points points to a two bytes buffer in which the CRC is stored.
102
     * @param sizeOfData is the number of bytes of *data* used to compute the CRC.
103
     *
104
     * The specification of the Cyclic Redundancy Code is described in the following document: ECSS-E-70-41-A.
105
     *
106
     */
107
108
    unsigned int Chk;
109
    int j;
110
90
    Chk = CRC_RESET; // reset the syndrom to all ones
111
1702
    for (j=0; j<sizeOfData; j++) {
112
1612
        Chk = Crc_opt(data[j], Chk);
113
    }
114
90
    crcAsTwoBytes[0] = (unsigned char) (Chk >> SHIFT_1_BYTE);
115
90
    crcAsTwoBytes[1] = (unsigned char) (Chk & BYTE1_MASK);
116
90
}
117
118
//*********************
119
// ACCEPTANCE FUNCTIONS
120
90
int tc_parser(ccsdsTelecommandPacket_t * TCPacket, unsigned int estimatedPacketLength, unsigned char *computed_CRC)
121
{
122
    /** This function parses TeleCommands.
123
     *
124
     * @param TC points to the TeleCommand that will be parsed.
125
     * @param estimatedPacketLength is the PACKET_LENGTH field calculated from the effective length of the received packet.
126
     *
127
     * @return Status code of the parsing.
128
     *
129
     * The parsing checks:
130
     * - process id
131
     * - category
132
     * - length: a global check is performed and a per subtype check also
133
     * - type
134
     * - subtype
135
     * - crc
136
     *
137
     */
138
139
    int status;
140
    int status_crc;
141
    unsigned char pid;
142
    unsigned char category;
143
    unsigned int packetLength;
144
    unsigned char packetType;
145
    unsigned char packetSubtype;
146
    unsigned char sid;
147
148
90
    status = CCSDS_TM_VALID;
149
150
    // APID check *** APID on 2 bytes
151
180
    pid             = ((TCPacket->packetID[0] & BITS_PID_0) << SHIFT_4_BITS)
152
90
            + ( (TCPacket->packetID[1] >> SHIFT_4_BITS) & BITS_PID_1 );   // PID = 11 *** 7 bits xxxxx210 7654xxxx
153
90
    category        = (TCPacket->packetID[1] & BITS_CAT);         // PACKET_CATEGORY = 12 *** 4 bits xxxxxxxx xxxx3210
154
90
    packetLength    = (TCPacket->packetLength[0] * CONST_256) + TCPacket->packetLength[1];
155
90
    packetType      = TCPacket->serviceType;
156
90
    packetSubtype   = TCPacket->serviceSubType;
157
90
    sid             = TCPacket->sourceID;
158
159
90
    if ( pid != CCSDS_PROCESS_ID )  // CHECK THE PROCESS ID
160
    {
161
        status = ILLEGAL_APID;
162
    }
163
90
    if (status == CCSDS_TM_VALID)   // CHECK THE CATEGORY
164
    {
165
90
        if ( category != CCSDS_PACKET_CATEGORY )
166
        {
167
            status = ILLEGAL_APID;
168
        }
169
    }
170
90
    if (status == CCSDS_TM_VALID)   // CHECK THE PACKET_LENGTH FIELD AND THE ESTIMATED PACKET_LENGTH COMPLIANCE
171
    {
172
90
        if (packetLength != estimatedPacketLength ) {
173
            status = WRONG_LEN_PKT;
174
        }
175
    }
176
90
    if (status == CCSDS_TM_VALID)   // CHECK THAT THE PACKET DOES NOT EXCEED THE MAX SIZE
177
    {
178
90
        if ( packetLength > CCSDS_TC_PKT_MAX_SIZE ) {
179
            status = WRONG_LEN_PKT;
180
        }
181
    }
182
90
    if (status == CCSDS_TM_VALID)   // CHECK THE TYPE
183
    {
184
90
        status = tc_check_type( packetType );
185
    }
186
90
    if (status == CCSDS_TM_VALID)   // CHECK THE SUBTYPE
187
    {
188
90
        status = tc_check_type_subtype( packetType, packetSubtype );
189
    }
190
90
    if (status == CCSDS_TM_VALID)   // CHECK THE SID
191
    {
192
90
        status = tc_check_sid( sid );
193
    }
194
90
    if (status == CCSDS_TM_VALID)   // CHECK THE SUBTYPE AND LENGTH COMPLIANCE
195
    {
196
90
        status = tc_check_length( packetSubtype, packetLength );
197
    }
198
90
    status_crc = tc_check_crc( TCPacket, estimatedPacketLength, computed_CRC );
199
90
    if (status == CCSDS_TM_VALID )  // CHECK CRC
200
    {
201
90
        status = status_crc;
202
    }
203
204
90
    return status;
205
}
206
207
90
int tc_check_type( unsigned char packetType )
208
{
209
    /** This function checks that the type of a TeleCommand is valid.
210
     *
211
     * @param packetType is the type to check.
212
     *
213
     * @return Status code CCSDS_TM_VALID or ILL_TYPE.
214
     *
215
     */
216
217
    int status;
218
219
90
    status = ILL_TYPE;
220
221
90
    if ( (packetType == TC_TYPE_GEN) || (packetType == TC_TYPE_TIME))
222
    {
223
90
        status = CCSDS_TM_VALID;
224
    }
225
    else
226
    {
227
        status = ILL_TYPE;
228
    }
229
230
90
    return status;
231
}
232
233
90
int tc_check_type_subtype( unsigned char packetType, unsigned char packetSubType )
234
{
235
    /** This function checks that the subtype of a TeleCommand is valid and coherent with the type.
236
     *
237
     * @param packetType is the type of the TC.
238
     * @param packetSubType is the subtype to check.
239
     *
240
     * @return Status code CCSDS_TM_VALID or ILL_SUBTYPE.
241
     *
242
     */
243
244
    int status;
245
246
90
    switch(packetType)
247
    {
248
    case TC_TYPE_GEN:
249




537
        if ( (packetSubType == TC_SUBTYPE_RESET)
250
90
             || (packetSubType == TC_SUBTYPE_LOAD_COMM)
251
179
             || (packetSubType == TC_SUBTYPE_LOAD_NORM) || (packetSubType == TC_SUBTYPE_LOAD_BURST)
252
89
             || (packetSubType == TC_SUBTYPE_LOAD_SBM1) || (packetSubType == TC_SUBTYPE_LOAD_SBM2)
253
89
             || (packetSubType == TC_SUBTYPE_DUMP)
254
89
             || (packetSubType == TC_SUBTYPE_ENTER)
255
             || (packetSubType == TC_SUBTYPE_UPDT_INFO)
256
             || (packetSubType == TC_SUBTYPE_EN_CAL)    || (packetSubType == TC_SUBTYPE_DIS_CAL)
257
             || (packetSubType == TC_SUBTYPE_LOAD_K)    || (packetSubType == TC_SUBTYPE_DUMP_K)
258
             || (packetSubType == TC_SUBTYPE_LOAD_FBINS)
259
             || (packetSubType == TC_SUBTYPE_LOAD_FILTER_PAR))
260
        {
261
90
            status = CCSDS_TM_VALID;
262
        }
263
        else
264
        {
265
            status = ILL_SUBTYPE;
266
        }
267
        break;
268
269
    case TC_TYPE_TIME:
270
        if (packetSubType == TC_SUBTYPE_UPDT_TIME)
271
        {
272
            status = CCSDS_TM_VALID;
273
        }
274
        else
275
        {
276
            status = ILL_SUBTYPE;
277
        }
278
        break;
279
280
    default:
281
        status = ILL_SUBTYPE;
282
        break;
283
    }
284
285
90
    return status;
286
}
287
288
90
int tc_check_sid( unsigned char sid )
289
{
290
    /** This function checks that the sid of a TeleCommand is valid.
291
     *
292
     * @param sid is the sid to check.
293
     *
294
     * @return Status code CCSDS_TM_VALID or CORRUPTED.
295
     *
296
     */
297
298
    int status;
299
300
90
    status = WRONG_SRC_ID;
301
302


183
    if ( (sid == SID_TC_MISSION_TIMELINE) || (sid == SID_TC_TC_SEQUENCES)   || (sid == SID_TC_RECOVERY_ACTION_CMD)
303
         || (sid == SID_TC_BACKUP_MISSION_TIMELINE)
304
91
         || (sid == SID_TC_DIRECT_CMD)       || (sid == SID_TC_SPARE_GRD_SRC1) || (sid == SID_TC_SPARE_GRD_SRC2)
305
2
         || (sid == SID_TC_OBCP)             || (sid == SID_TC_SYSTEM_CONTROL) || (sid == SID_TC_AOCS)
306
1
         || (sid == SID_TC_RPW_INTERNAL))
307
    {
308
90
        status = CCSDS_TM_VALID;
309
    }
310
    else
311
    {
312
        status = WRONG_SRC_ID;
313
    }
314
315
90
    return status;
316
}
317
318
90
int tc_check_length( unsigned char packetSubType, unsigned int length )
319
{
320
    /** This function checks that the subtype and the length are compliant.
321
     *
322
     * @param packetSubType is the subtype to check.
323
     * @param length is the length to check.
324
     *
325
     * @return Status code CCSDS_TM_VALID or ILL_TYPE.
326
     *
327
     */
328
329
    int status;
330
331
90
    status = LFR_SUCCESSFUL;
332
333




90
    switch(packetSubType)
334
    {
335
    case TC_SUBTYPE_RESET:
336
1
        if (length!=(TC_LEN_RESET-CCSDS_TC_TM_PACKET_OFFSET)) {
337
            status = WRONG_LEN_PKT;
338
        }
339
        else {
340
1
            status = CCSDS_TM_VALID;
341
        }
342
        break;
343
    case TC_SUBTYPE_LOAD_COMM:
344
        if (length!=(TC_LEN_LOAD_COMM-CCSDS_TC_TM_PACKET_OFFSET)) {
345
            status = WRONG_LEN_PKT;
346
        }
347
        else {
348
            status = CCSDS_TM_VALID;
349
        }
350
        break;
351
    case TC_SUBTYPE_LOAD_NORM:
352
        if (length!=(TC_LEN_LOAD_NORM-CCSDS_TC_TM_PACKET_OFFSET)) {
353
            status = WRONG_LEN_PKT;
354
        }
355
        else {
356
            status = CCSDS_TM_VALID;
357
        }
358
        break;
359
    case TC_SUBTYPE_LOAD_BURST:
360
        if (length!=(TC_LEN_LOAD_BURST-CCSDS_TC_TM_PACKET_OFFSET)) {
361
            status = WRONG_LEN_PKT;
362
        }
363
        else {
364
            status = CCSDS_TM_VALID;
365
        }
366
        break;
367
    case TC_SUBTYPE_LOAD_SBM1:
368
        if (length!=(TC_LEN_LOAD_SBM1-CCSDS_TC_TM_PACKET_OFFSET)) {
369
            status = WRONG_LEN_PKT;
370
        }
371
        else {
372
            status = CCSDS_TM_VALID;
373
        }
374
        break;
375
    case TC_SUBTYPE_LOAD_SBM2:
376
        if (length!=(TC_LEN_LOAD_SBM2-CCSDS_TC_TM_PACKET_OFFSET)) {
377
            status = WRONG_LEN_PKT;
378
        }
379
        else {
380
            status = CCSDS_TM_VALID;
381
        }
382
        break;
383
    case TC_SUBTYPE_DUMP:
384
        if (length!=(TC_LEN_DUMP-CCSDS_TC_TM_PACKET_OFFSET)) {
385
            status = WRONG_LEN_PKT;
386
        }
387
        else {
388
            status = CCSDS_TM_VALID;
389
        }
390
        break;
391
    case TC_SUBTYPE_ENTER:
392
89
        if (length!=(TC_LEN_ENTER-CCSDS_TC_TM_PACKET_OFFSET)) {
393
            status = WRONG_LEN_PKT;
394
        }
395
        else {
396
89
            status = CCSDS_TM_VALID;
397
        }
398
        break;
399
    case TC_SUBTYPE_UPDT_INFO:
400
        if (length!=(TC_LEN_UPDT_INFO-CCSDS_TC_TM_PACKET_OFFSET)) {
401
            status = WRONG_LEN_PKT;
402
        }
403
        else {
404
            status = CCSDS_TM_VALID;
405
        }
406
        break;
407
    case TC_SUBTYPE_EN_CAL:
408
        if (length!=(TC_LEN_EN_CAL-CCSDS_TC_TM_PACKET_OFFSET)) {
409
            status = WRONG_LEN_PKT;
410
        }
411
        else {
412
            status = CCSDS_TM_VALID;
413
        }
414
        break;
415
    case TC_SUBTYPE_DIS_CAL:
416
        if (length!=(TC_LEN_DIS_CAL-CCSDS_TC_TM_PACKET_OFFSET)) {
417
            status = WRONG_LEN_PKT;
418
        }
419
        else {
420
            status = CCSDS_TM_VALID;
421
        }
422
        break;
423
    case TC_SUBTYPE_LOAD_K:
424
        if (length!=(TC_LEN_LOAD_K-CCSDS_TC_TM_PACKET_OFFSET)) {
425
            status = WRONG_LEN_PKT;
426
        }
427
        else {
428
            status = CCSDS_TM_VALID;
429
        }
430
        break;
431
    case TC_SUBTYPE_DUMP_K:
432
        if (length!=(TC_LEN_DUMP_K-CCSDS_TC_TM_PACKET_OFFSET)) {
433
            status = WRONG_LEN_PKT;
434
        }
435
        else {
436
            status = CCSDS_TM_VALID;
437
        }
438
        break;
439
    case TC_SUBTYPE_LOAD_FBINS:
440
        if (length!=(TC_LEN_LOAD_FBINS-CCSDS_TC_TM_PACKET_OFFSET)) {
441
            status = WRONG_LEN_PKT;
442
        }
443
        else {
444
            status = CCSDS_TM_VALID;
445
        }
446
        break;
447
    case TC_SUBTYPE_LOAD_FILTER_PAR:
448
        if (length!=(TC_LEN_LOAD_FILTER_PAR-CCSDS_TC_TM_PACKET_OFFSET)) {
449
            status = WRONG_LEN_PKT;
450
        }
451
        else {
452
            status = CCSDS_TM_VALID;
453
        }
454
        break;
455
    case TC_SUBTYPE_UPDT_TIME:
456
        if (length!=(TC_LEN_UPDT_TIME-CCSDS_TC_TM_PACKET_OFFSET)) {
457
            status = WRONG_LEN_PKT;
458
        }
459
        else {
460
            status = CCSDS_TM_VALID;
461
        }
462
        break;
463
    default: // if the subtype is not a legal value, return ILL_SUBTYPE
464
        status = ILL_SUBTYPE;
465
        break    ;
466
    }
467
468
90
    return status;
469
}
470
471
90
int tc_check_crc( ccsdsTelecommandPacket_t * TCPacket, unsigned int length, unsigned char *computed_CRC )
472
{
473
    /** This function checks the CRC validity of the corresponding TeleCommand packet.
474
     *
475
     * @param TCPacket points to the TeleCommand packet to check.
476
     * @param length is the length of the TC packet.
477
     *
478
     * @return Status code CCSDS_TM_VALID or INCOR_CHECKSUM.
479
     *
480
     */
481
482
    int status;
483
    unsigned char * CCSDSContent;
484
485
90
    status = INCOR_CHECKSUM;
486
487
90
    CCSDSContent = (unsigned char*) TCPacket->packetID;
488
90
    GetCRCAsTwoBytes(CCSDSContent, computed_CRC, length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC); // 2 CRC bytes removed from the calculation of the CRC
489
490
90
    if (computed_CRC[0] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC]) {
491
        status = INCOR_CHECKSUM;
492
    }
493
90
    else if (computed_CRC[1] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET -1]) {
494
        status = INCOR_CHECKSUM;
495
    }
496
    else {
497
90
        status = CCSDS_TM_VALID;
498
    }
499
500
90
    return status;
501
}
502
503
504