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 556 : return (((Chk << SHIFT_1_BYTE) & BYTE0_MASK) 52 278 : ^ 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 17 : unsigned int Chk = CRC_RESET; 118 295 : for (unsigned int j = 0; j < sizeOfData; j++) 119 : { 120 556 : Chk = Crc_opt(data[j], Chk); 121 : } 122 17 : crcAsTwoBytes[0] = (unsigned char)(Chk >> SHIFT_1_BYTE); 123 17 : crcAsTwoBytes[1] = (unsigned char)(Chk & BYTE1_MASK); 124 0 : } 125 : 126 : //********************* 127 : // ACCEPTANCE FUNCTIONS 128 17 : 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 17 : status = CCSDS_TM_VALID; 159 : 160 : // APID check *** APID on 2 bytes 161 34 : pid = ((TCPacket->packetID[0] & BITS_PID_0) << SHIFT_4_BITS) 162 17 : + ((TCPacket->packetID[1] >> SHIFT_4_BITS) 163 : & BITS_PID_1); // PID = 11 *** 7 bits xxxxx210 7654xxxx 164 17 : category 165 17 : = (TCPacket->packetID[1] & BITS_CAT); // PACKET_CATEGORY = 12 *** 4 bits xxxxxxxx xxxx3210 166 17 : packetLength = (TCPacket->packetLength[0] * CONST_256) + TCPacket->packetLength[1]; 167 17 : packetType = TCPacket->serviceType; 168 17 : packetSubtype = TCPacket->serviceSubType; 169 17 : sid = TCPacket->sourceID; 170 : 171 17 : if (pid != CCSDS_PROCESS_ID) // CHECK THE PROCESS ID 172 : { 173 0 : status = ILLEGAL_APID; 174 : } 175 : // CHECK THE CATEGORY 176 17 : 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 17 : 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 17 : if (status == CCSDS_TM_VALID && packetLength > CCSDS_TC_PKT_MAX_SIZE) 188 : { 189 0 : status = WRONG_LEN_PKT; 190 : } 191 17 : if (status == CCSDS_TM_VALID) // CHECK THE TYPE 192 : { 193 34 : status = tc_check_type(packetType); 194 : } 195 17 : if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE 196 : { 197 17 : status = tc_check_type_subtype(packetType, packetSubtype); 198 : } 199 17 : if (status == CCSDS_TM_VALID) // CHECK THE SID 200 : { 201 17 : status = tc_check_sid(sid); 202 : } 203 17 : if (status == CCSDS_TM_VALID) // CHECK THE SUBTYPE AND LENGTH COMPLIANCE 204 : { 205 17 : status = tc_check_length(packetSubtype, packetLength); 206 : } 207 17 : status_crc = tc_check_crc(TCPacket, estimatedPacketLength, computed_CRC); 208 17 : if (status == CCSDS_TM_VALID) // CHECK CRC 209 : { 210 17 : status = status_crc; 211 : } 212 : 213 17 : 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 17 : status = ILL_TYPE; 229 : 230 17 : if ((packetType == TC_TYPE_GEN) || (packetType == TC_TYPE_TIME)) 231 : { 232 17 : status = CCSDS_TM_VALID; 233 : } 234 : 235 17 : return status; 236 : } 237 : 238 17 : 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 17 : switch (packetType) 252 : { 253 : case TC_TYPE_GEN: 254 39 : if ((packetSubType == TC_SUBTYPE_RESET) || (packetSubType == TC_SUBTYPE_LOAD_COMM) 255 13 : || (packetSubType == TC_SUBTYPE_LOAD_NORM) 256 6 : || (packetSubType == TC_SUBTYPE_LOAD_BURST) 257 6 : || (packetSubType == TC_SUBTYPE_LOAD_SBM1) 258 12 : || (packetSubType == TC_SUBTYPE_LOAD_SBM2) || (packetSubType == TC_SUBTYPE_DUMP) 259 6 : || (packetSubType == TC_SUBTYPE_ENTER) || (packetSubType == TC_SUBTYPE_UPDT_INFO) 260 0 : || (packetSubType == TC_SUBTYPE_EN_CAL) || (packetSubType == TC_SUBTYPE_DIS_CAL) 261 0 : || (packetSubType == TC_SUBTYPE_LOAD_K) || (packetSubType == TC_SUBTYPE_DUMP_K) 262 0 : || (packetSubType == TC_SUBTYPE_LOAD_FBINS) 263 : || (packetSubType == TC_SUBTYPE_LOAD_FILTER_PAR)) 264 : { 265 7 : status = CCSDS_TM_VALID; 266 : } 267 : else 268 : { 269 0 : status = ILL_SUBTYPE; 270 : } 271 : break; 272 : 273 : case TC_TYPE_TIME: 274 10 : if (packetSubType == TC_SUBTYPE_UPDT_TIME) 275 : { 276 10 : 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 17 : return status; 290 : } 291 : 292 17 : 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 17 : int status = WRONG_SRC_ID; 303 : 304 20 : 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 18 : || (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 17 : status = CCSDS_TM_VALID; 311 : } 312 : 313 17 : return status; 314 : } 315 : 316 17 : 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 17 : int status = CCSDS_TM_VALID; 328 : 329 17 : 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 0 : if (length != (TC_LEN_DUMP - CCSDS_TC_TM_PACKET_OFFSET)) 393 : { 394 0 : status = WRONG_LEN_PKT; 395 : } 396 : else 397 : { 398 0 : status = CCSDS_TM_VALID; 399 : } 400 : break; 401 : case TC_SUBTYPE_ENTER: 402 6 : if (length != (TC_LEN_ENTER - CCSDS_TC_TM_PACKET_OFFSET)) 403 : { 404 0 : status = WRONG_LEN_PKT; 405 : } 406 : else 407 : { 408 6 : 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 0 : if (length != (TC_LEN_LOAD_FILTER_PAR - CCSDS_TC_TM_PACKET_OFFSET)) 473 : { 474 0 : status = WRONG_LEN_PKT; 475 : } 476 : else 477 : { 478 0 : status = CCSDS_TM_VALID; 479 : } 480 : break; 481 : case TC_SUBTYPE_UPDT_TIME: 482 10 : if (length != (TC_LEN_UPDT_TIME - CCSDS_TC_TM_PACKET_OFFSET)) 483 : { 484 0 : status = WRONG_LEN_PKT; 485 : } 486 : else 487 : { 488 10 : 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 17 : return status; 497 : } 498 : 499 17 : 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 17 : int status = CCSDS_TM_VALID; 512 17 : const unsigned char* const CCSDSContent = (const unsigned char*)TCPacket->packetID; 513 : 514 17 : 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 17 : if (computed_CRC[0] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - BYTES_PER_CRC]) 519 : { 520 0 : status = INCOR_CHECKSUM; 521 : } 522 17 : else if (computed_CRC[1] != CCSDSContent[length + CCSDS_TC_TM_PACKET_OFFSET - 1]) 523 : { 524 0 : status = INCOR_CHECKSUM; 525 : } 526 : 527 17 : return status; 528 : }