GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/tc_acceptance.c Lines: 155 158 98.1 %
Date: 2018-11-13 11:16:07 Branches: 125 128 97.7 %

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
1116364
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
1116364
    return(((Chk << SHIFT_1_BYTE) & BYTE0_MASK)^lookUpTableForCRC [(((Chk >> SHIFT_1_BYTE)^D) & BYTE1_MASK)]);
52
}
53
54
94
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
24158
    for (i=0; i<CONST_256; i++)
66
    {
67
24064
        tmp = 0;
68
24064
        if((i & BIT_0) != 0) {
69
12032
            tmp = tmp ^ CONST_CRC_0;
70
        }
71
24064
        if((i & BIT_1) != 0) {
72
12032
            tmp = tmp ^ CONST_CRC_1;
73
        }
74
24064
        if((i & BIT_2) != 0) {
75
12032
            tmp = tmp ^ CONST_CRC_2;
76
        }
77
24064
        if((i & BIT_3) != 0) {
78
12032
            tmp = tmp ^ CONST_CRC_3;
79
        }
80
24064
        if((i & BIT_4) != 0) {
81
12032
            tmp = tmp ^ CONST_CRC_4;
82
        }
83
24064
        if((i & BIT_5) != 0) {
84
12032
            tmp = tmp ^ CONST_CRC_5;
85
        }
86
24064
        if((i & BIT_6) != 0) {
87
12032
            tmp = tmp ^ CONST_CRC_6;
88
        }
89
24064
        if((i & BIT_7) != 0) {
90
12032
            tmp = tmp ^ CONST_CRC_7;
91
        }
92
24064
        lookUpTableForCRC[i] = tmp;
93
    }
94
94
}
95
96
42177
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
42177
    Chk = CRC_RESET; // reset the syndrom to all ones
111
1158541
    for (j=0; j<sizeOfData; j++) {
112
1116364
        Chk = Crc_opt(data[j], Chk);
113
    }
114
42177
    crcAsTwoBytes[0] = (unsigned char) (Chk >> SHIFT_1_BYTE);
115
42177
    crcAsTwoBytes[1] = (unsigned char) (Chk & BYTE1_MASK);
116
42177
}
117
118
//*********************
119
// ACCEPTANCE FUNCTIONS
120
42177
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
42177
    status = CCSDS_TM_VALID;
149
150
    // APID check *** APID on 2 bytes
151
84354
    pid             = ((TCPacket->packetID[0] & BITS_PID_0) << SHIFT_4_BITS)
152
42177
            + ( (TCPacket->packetID[1] >> SHIFT_4_BITS) & BITS_PID_1 );   // PID = 11 *** 7 bits xxxxx210 7654xxxx
153
42177
    category        = (TCPacket->packetID[1] & BITS_CAT);         // PACKET_CATEGORY = 12 *** 4 bits xxxxxxxx xxxx3210
154
42177
    packetLength    = (TCPacket->packetLength[0] * CONST_256) + TCPacket->packetLength[1];
155
42177
    packetType      = TCPacket->serviceType;
156
42177
    packetSubtype   = TCPacket->serviceSubType;
157
42177
    sid             = TCPacket->sourceID;
158
159
42177
    if ( pid != CCSDS_PROCESS_ID )  // CHECK THE PROCESS ID
160
    {
161
132
        status = ILLEGAL_APID;
162
    }
163
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE CATEGORY
164
    {
165
42045
        if ( category != CCSDS_PACKET_CATEGORY )
166
        {
167
66
            status = ILLEGAL_APID;
168
        }
169
    }
170
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE PACKET_LENGTH FIELD AND THE ESTIMATED PACKET_LENGTH COMPLIANCE
171
    {
172
41979
        if (packetLength != estimatedPacketLength ) {
173
66
            status = WRONG_LEN_PKT;
174
        }
175
    }
176
42177
    if (status == CCSDS_TM_VALID)   // CHECK THAT THE PACKET DOES NOT EXCEED THE MAX SIZE
177
    {
178
41913
        if ( packetLength > CCSDS_TC_PKT_MAX_SIZE ) {
179
            status = WRONG_LEN_PKT;
180
        }
181
    }
182
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE TYPE
183
    {
184
41913
        status = tc_check_type( packetType );
185
    }
186
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE SUBTYPE
187
    {
188
33653
        status = tc_check_type_subtype( packetType, packetSubtype );
189
    }
190
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE SID
191
    {
192
33521
        status = tc_check_sid( sid );
193
    }
194
42177
    if (status == CCSDS_TM_VALID)   // CHECK THE SUBTYPE AND LENGTH COMPLIANCE
195
    {
196
30238
        status = tc_check_length( packetSubtype, packetLength );
197
    }
198
42177
    status_crc = tc_check_crc( TCPacket, estimatedPacketLength, computed_CRC );
199
42177
    if (status == CCSDS_TM_VALID )  // CHECK CRC
200
    {
201
30180
        status = status_crc;
202
    }
203
204
42177
    return status;
205
}
206
207
41913
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
41913
    status = ILL_TYPE;
220
221
41913
    if ( (packetType == TC_TYPE_GEN) || (packetType == TC_TYPE_TIME))
222
    {
223
33653
        status = CCSDS_TM_VALID;
224
    }
225
226
41913
    return status;
227
}
228
229
33653
int tc_check_type_subtype( unsigned char packetType, unsigned char packetSubType )
230
{
231
    /** This function checks that the subtype of a TeleCommand is valid and coherent with the type.
232
     *
233
     * @param packetType is the type of the TC.
234
     * @param packetSubType is the subtype to check.
235
     *
236
     * @return Status code CCSDS_TM_VALID or ILL_SUBTYPE.
237
     *
238
     */
239
240
    int status;
241
242
33653
    switch(packetType)
243
    {
244
    case TC_TYPE_GEN:
245




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


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




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