/*********************************************************** * File: decode.c * * C code for file search and AMS-02 data decode functions * * History: * 20071106 - created by X.Cai * 20071114 - First release by X.Cai ***********************************************************/ #include //---------------------------------------------------------- // Include files //---------------------------------------------------------- #include "decode.h" //---------------------------------------------------------- // Definitions //---------------------------------------------------------- //---------------------------------------------------------- // typedef, struct and enum //---------------------------------------------------------- typedef struct __stream_info_t { int apid; int seq; struct __stream_info_t *next; } stream_info_t; //---------------------------------------------------------- // Global variables //---------------------------------------------------------- //---------------------------------------------------------- // Local variables //---------------------------------------------------------- /* Frame error messages */ static char *frame_error_msg[] = { "Frame OK", "Unknown APID in frame", "Frame Checksum error", "Frame CRC error", "Wrong frame size", "Wrong frame sequence", "Unknown error code", }; /* Stream info list */ static stream_info_t *stream_info = NULL; /* Frame error messages */ static char *block_error_msg[] = { "Block OK", "Wrong frame link point", "Wrong block input", "Wrong block size", "Fail to allocate buffer", "Wrong CRC", "Unknown error code", }; /* Node names */ static char *node_names[] = { "JMDC-0", "JMDC-1", "JMDC-2", "JMDC-3", "JMDC-0", "JMDC-1", "JMDC-2", "JMDC-3", // 000 - 007 "JMDC-0", "JMDC-1", "JMDC-2", "JMDC-3", "JMDC-0", "JMDC-1", "JMDC-2", "JMDC-3", // 008 - 015 "JMDC-H", "JMDC-L", "JMDC-D", "JMDC-M", "N-X014", "N-X015", "ACOP_N", "JMDC-A", // 016 - 023 "CAB-A", "CAB-B", "CAB-P", "CAB-S", "CCEB-A", "CCEB-B", "CCEB-P", "CCEB-S", // 024 - 031 "EPD-0A", "EPD-0B", "EPD-0P", "EPD-0S", "EPD-1A", "EPD-1B", "EPD-1P", "EPD-1S", // 032 - 039 "JPD-A", "JPD-B", "JPD-P", "JPD-S", "MPD-A", "MPD-B", "MPD-P", "MPD-S", // 040 - 047 "PDS-A", "PDS-B", "PDS-P", "PDS-S", "RPD-0A", "RPD-0B", "RPD-0P", "RPD-0S", // 048 - 055 "RPD-1A", "RPD-1B", "RPD-1P", "RPD-1S", "SPD-0A", "SPD-0B", "SPD-0P", "SPD-0S", // 056 - 063 "SPD-1A", "SPD-1B", "SPD-1P", "SPD-1S", "SPD-2A", "SPD-2B", "SPD-2P", "SPD-2S", // 064 - 071 "SPD-3A", "SPD-3B", "SPD-3P", "SPD-3S", "TPD-0A", "TPD-0B", "TPD-0P", "TPD-0S", // 072 - 079 "TPD-1A", "TPD-1B", "TPD-1P", "TPD-1S", "TPD-2A", "TPD-2B", "TPD-2P", "TPD-2S", // 080 - 087 "TPD-3A", "TPD-3B", "TPD-3P", "TPD-3S", "TPD-4A", "TPD-4B", "TPD-4P", "TPD-4S", // 088 - 095 "TPD-5A", "TPD-5B", "TPD-5P", "TPD-5S", "TPD-6A", "TPD-6B", "TPD-6P", "TPD-6S", // 096 - 103 "TPD-7A", "TPD-7B", "TPD-7P", "TPD-7S", "TTCE-A", "TTCE-B", "TTCE-P", "TTCE-S", // 104 - 111 "UPD-0A", "UPD-0B", "UPD-0P", "UPD-0S", "UPD-1A", "UPD-1B", "UPD-1P", "UPD-1S", // 112 - 119 "UGPD-A", "UGPD-B", "UGPD-P", "UGPD-S", "CAB-A", "CAB-B", "CAB-P", "CAB-S", // 120 - 127 "JINJ-0", "JINJ-1", "JINJ-2", "JINJ-3", "JINJ-P", "JINJ-S", "JINJ-T", "JINJ-Q", // 128 - 135 "JLV1-A", "JLV1-B", "JLV1-P", "JLV1-S", "ETRG0A", "ETRG0B", "ETRG0P", "ETRG0S", // 136 - 143 "ETRG1A", "ETRG1B", "ETRG1P", "ETRG1S", "N-X094", "N-X095", "JF-E0A", "JF-E0B", // 144 - 151 "JF-E0P", "JF-E0S", "JF-E1A", "JF-E1B", "JF-E1P", "JF-E1S", "JF-R0A", "JF-R0B", // 152 - 159 "JF-R0P", "JF-R0S", "JF-R1A", "JF-R1B", "JF-R1P", "JF-R1S", "JF-T0A", "JF-T0B", // 160 - 167 "JF-T0P", "JF-T0S", "JF-T1A", "JF-T1B", "JF-T1P", "JF-T1S", "JF-T2A", "JF-T2B", // 168 - 175 "JF-T2P", "JF-T2S", "JF-T3A", "JF-T3B", "JF-T3P", "JF-T3S", "JF-T4A", "JF-T4B", // 176 - 183 "JF-T4P", "JF-T4S", "JF-T5A", "JF-T5B", "JF-T5P", "JF-T5S", "JF-T6A", "JF-T6B", // 184 - 191 "JF-T6P", "JF-T6S", "JF-T7A", "JF-T7B", "JF-T7P", "JF-T7S", "JF-U0A", "JF-U0B", // 192 - 199 "JF-U0P", "JF-U0S", "JF-U1A", "JF-U1B", "JF-U1P", "JF-U1S", "EDR00A", "EDR00B", // 200 - 207 "EDR00P", "EDR01A", "EDR01B", "EDR01P", "EDR02A", "EDR02B", "EDR02P", "EDR03A", // 208 - 215 "EDR03B", "EDR03P", "EDR04A", "EDR04B", "EDR04P", "EDR05A", "EDR05B", "EDR05P", // 216 - 223 "EDR10A", "EDR10B", "EDR10P", "EDR11A", "EDR11B", "EDR11P", "EDR12A", "EDR12B", // 224 - 231 "EDR12P", "EDR13A", "EDR13B", "EDR13P", "EDR14A", "EDR14B", "EDR14P", "EDR15A", // 232 - 239 "EDR15B", "EDR15P", "RDR00A", "RDR00B", "RDR01A", "RDR01B", "RDR02A", "RDR02B", // 240 - 247 "RDR03A", "RDR03B", "RDR04A", "RDR04B", "RDR05A", "RDR05B", "RDR10A", "RDR10B", // 248 - 255 "RDR11A", "RDR11B", "RDR12A", "RDR12B", "RDR13A", "RDR13B", "RDR14A", "RDR14B", // 256 - 263 "RDR15A", "RDR15B", "SDR-0A", "SDR-0B", "SDR-0P", "SDR-0S", "SDR-1A", "SDR-1B", // 264 - 271 "SDR-1P", "SDR-1S", "SDR-2A", "SDR-2B", "SDR-2P", "SDR-2S", "SDR-3A", "SDR-3B", // 272 - 279 "SDR-3P", "SDR-3S", "TDR00A", "TDR00B", "TDR01A", "TDR01B", "TDR02A", "TDR02B", // 280 - 287 "TDR03A", "TDR03B", "TDR04A", "TDR04B", "TDR05A", "TDR05B", "TDR06A", "TDR06B", // 288 - 295 "TDR07A", "TDR07B", "TDR08A", "TDR08B", "TDR09A", "TDR09B", "TDR0AA", "TDR0AB", // 296 - 303 "TDR0BA", "TDR0BB", "TDR10A", "TDR10B", "TDR11A", "TDR11B", "TDR12A", "TDR12B", // 304 - 311 "TDR13A", "TDR13B", "TDR14A", "TDR14B", "TDR15A", "TDR15B", "TDR16A", "TDR16B", // 312 - 319 "TDR17A", "TDR17B", "TDR18A", "TDR18B", "TDR19A", "TDR19B", "TDR1AA", "TDR1AB", // 320 - 327 "TDR1BA", "TDR1BB", "TDR20A", "TDR20B", "TDR21A", "TDR21B", "TDR22A", "TDR22B", // 328 - 335 "TDR23A", "TDR23B", "TDR24A", "TDR24B", "TDR25A", "TDR25B", "TDR26A", "TDR26B", // 336 - 343 "TDR27A", "TDR27B", "TDR28A", "TDR28B", "TDR29A", "TDR29B", "TDR2AA", "TDR2AB", // 344 - 351 "TDR2BA", "TDR2BB", "TDR30A", "TDR30B", "TDR31A", "TDR31B", "TDR32A", "TDR32B", // 352 - 359 "TDR33A", "TDR33B", "TDR34A", "TDR34B", "TDR35A", "TDR35B", "TDR36A", "TDR36B", // 360 - 367 "TDR37A", "TDR37B", "TDR38A", "TDR38B", "TDR39A", "TDR39B", "TDR3AA", "TDR3AB", // 368 - 375 "TDR3BA", "TDR3BB", "TDR40A", "TDR40B", "TDR41A", "TDR41B", "TDR42A", "TDR42B", // 376 - 383 "TDR43A", "TDR43B", "TDR44A", "TDR44B", "TDR45A", "TDR45B", "TDR46A", "TDR46B", // 384 - 391 "TDR47A", "TDR47B", "TDR48A", "TDR48B", "TDR49A", "TDR49B", "TDR4AA", "TDR4AB", // 392 - 399 "TDR4BA", "TDR4BB", "TDR50A", "TDR50B", "TDR51A", "TDR51B", "TDR52A", "TDR52B", // 400 - 407 "TDR53A", "TDR53B", "TDR54A", "TDR54B", "TDR55A", "TDR55B", "TDR56A", "TDR56B", // 408 - 415 "TDR57A", "TDR57B", "TDR58A", "TDR58B", "TDR59A", "TDR59B", "TDR5AA", "TDR5AB", // 416 - 423 "TDR5BA", "TDR5BB", "TDR60A", "TDR60B", "TDR61A", "TDR61B", "TDR62A", "TDR62B", // 424 - 431 "TDR63A", "TDR63B", "TDR64A", "TDR64B", "TDR65A", "TDR65B", "TDR66A", "TDR66B", // 432 - 439 "TDR67A", "TDR67B", "TDR68A", "TDR68B", "TDR69A", "TDR69B", "TDR6AA", "TDR6AB", // 440 - 447 "TDR6BA", "TDR6BB", "TDR70A", "TDR70B", "TDR71A", "TDR71B", "TDR72A", "TDR72B", // 448 - 455 "TDR73A", "TDR73B", "TDR74A", "TDR74B", "TDR75A", "TDR75B", "TDR76A", "TDR76B", // 456 - 463 "TDR77A", "TDR77B", "TDR78A", "TDR78B", "TDR79A", "TDR79B", "TDR7AA", "TDR7AB", // 464 - 471 "TDR7BA", "TDR7BB", "UDR00A", "UDR00B", "UDR00P", "UDR01A", "UDR01B", "UDR01P", // 472 - 479 "UDR02A", "UDR02B", "UDR02P", "UDR03A", "UDR03B", "UDR03P", "UDR04A", "UDR04B", // 480 - 487 "UDR04P", "UDR05A", "UDR05B", "UDR05P", "UDR10A", "UDR10B", "UDR10P", "UDR11A", // 488 - 495 "UDR11B", "UDR11P", "UDR12A", "UDR12B", "UDR12P", "UDR13A", "UDR13B", "UDR13P", // 496 - 503 "UDR14A", "UDR14B", "UDR14P", "UDR15A", "UDR15B", "UDR15P", "N-X1FE", "N-X1FF", // 504 - 511 }; static char *jinj_ports_short[] = { "T2", "T3", "U1", "T0", "S1", "S1", "S0", "S0", "U0", "T1", "R0", "R1", "E0", "E1", "L1", "L1", "T4", "T5", "S2", "S2", "S3", "S3", "T6", "T7", }; static char *jinj_ports_long[] = { "JINFT2", "JINFT3", "JINFU1", "JINFT0", "SDR-1A", "SDR-1B", "SDR-0A", "SDR-0B", "JINFU0", "JINFT1", "JINFR0", "JINFR1", "JINFE0", "JINFE1", "JLV1-A", "JLV1-B", "JINFT4", "JINFT5", "SDR-2A", "SDR-2B", "SDR-3A", "SDR-3B", "JINFT6", "JINFT7", }; static int jinj_levels[] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, }; //---------------------------------------------------------- // Function: decode_swap16 // Swap two bytes in 16-bit words. // (Source and destination can be the same) // // Inputs: // src ----- Source address // dest ---- Destination address // nw ------ Number of words // // Return: // None //---------------------------------------------------------- void decode_swap16(unsigned short *src, unsigned short *dest, int nw) { int i; for ( i = 0; i < nw; i++ ) { dest[i] = ((src[i] & 0xFF) << 8) | (src[i] >> 8); } } //---------------------------------------------------------- // Function: _frame_chksum (local) // Calculate checksum16 // // Inputs: // data ---- Data inputs // size ---- Number of bytes // mode ---- mode (0 - big endian, 1 - little endian, 2 - byte) // // Return: // checksum value //---------------------------------------------------------- unsigned short _frame_chksum16(unsigned char *data, int size, int mode) { int i; unsigned short chksum; for ( chksum = 0, i = 0; i < size; i += 2 ) { switch ( mode ) { /* Byte mode */ case 2: chksum += data[i]; chksum += data[i+1]; break; /* little endian word */ case 1: chksum += ((data[i+1] << 8) | data[i]); break; /* big endian word */ case 0: default: chksum += ((data[i] << 8) | data[i+1]); break; } } return chksum; } //---------------------------------------------------------- // Function: _frame_crc16 (local) // Calculate CRC for frame // // Inputs: // data ---- Data inputs // size ---- Number of bytes // // Return: // crc value //---------------------------------------------------------- #define POLYNOMIAL 0x1021 static unsigned short crc16_table[256]; static int __crc_table_init = 1; unsigned short _frame_crc16(unsigned char *data, int size) { int i, j; unsigned short crc; unsigned short tmp; /* Initialize CRC table */ if ( __crc_table_init ) { __crc_table_init = 0; for (i = 0; i < 256; i++) { crc = i << 8; for (j = 0; j < 8; j++) { if (crc & 0x8000) crc = (crc << 1) ^ POLYNOMIAL; else crc <<= 1; } crc16_table[i]=crc; } } /* Calculate CRC */ crc = 0xFFFF; while (size--) { tmp = (unsigned short) *data++; tmp^= (crc >> 8); crc = (crc << 8) ^ *(crc16_table + tmp); } return(crc); } //---------------------------------------------------------- // Function: _frame_randomize (local) // Randomize frame data // // Inputs: // data ---- Data inputs // size ---- Number of bytes // // Return: // None //---------------------------------------------------------- static unsigned char random_table[510]; static int __rand_table_init = 1; void _frame_randomize(unsigned char *data, int size) { unsigned char rr = 0xff; int i, j; /* Initialize table */ if ( __rand_table_init ) { __rand_table_init = 0; /* Loop to fill table */ for ( i = 0; i < 510; i++ ) { /* fill data */ random_table[i] = rr; /* Calculate the next byte */ for ( j = 0; j < 8; j++ ) rr = ((rr ^ (rr << 3) ^ (rr << 5) ^ (rr << 7)) & 0x80) ? (rr << 1) + 1 : (rr << 1); } } /* Randomize the data */ for (i = 0; i < size; i++) data[i] ^= random_table[i % 510]; } //---------------------------------------------------------- // Function: decode_frame_errmsg // Return frame error message // // Inputs: // errcode ---- Error code // // Return: // Error message string //---------------------------------------------------------- char *decode_frame_errmsg(int errcode) { if ( errcode < 0 ) errcode = -errcode; if ( errcode > FE_LAST ) return frame_error_msg[FE_LAST + 1]; return frame_error_msg[errcode]; } //---------------------------------------------------------- // Function: decode_frame_header // Decode frame primary header only // // Inputs: // frm ---- Frame input // // Return: // None //---------------------------------------------------------- int decode_frame_header(frame_t *frm) { unsigned short word; unsigned char *frame = frm->frame; /* get APID */ word = (frame[0] << 8) | frame[1]; frm->apid = FRAME_APID(word); /* get Sequence number */ word = (frame[2] << 8) | frame[3]; frm->seq = FRAME_SEQ(word); /* Get size */ frm->size = ((frame[4] << 8) | frame[5]) + 7; if(frm->size>FRAME_MAX_SIZE){ frm->size=FRAME_MAX_SIZE; frm->end = frm->size; return -1; } frm->end = frm->size; frm->index = 0; return 0; } //---------------------------------------------------------- // Function: _frame_check_seq (local) // Check frame sequence // // Inputs: // frm ---- Frame to be checked // // Return: // = 0 : OK // < 0 : Error //---------------------------------------------------------- int _frame_check_seq(frame_t *frm) { stream_info_t **sii = &stream_info; stream_info_t *si = *sii; int ret; /* Find stream info */ while ( si != NULL ) { /* Compare APID */ if ( si->apid == frm->apid ) { /* Check frame sequence */ if ( frm->seq == FRAME_SEQ(si->seq + 1) ) ret = FE_OK; else ret = -FE_BADSEQ; /* Save sequence */ si->seq = frm->seq; return ret; } /* Get the next from list */ sii = &(si->next); si = *sii; } /* Create a new info */ si = (stream_info_t*)malloc(sizeof(stream_info_t)); if ( si != NULL ) { si->apid = frm->apid; si->seq = frm->seq; si->next = NULL; *sii = si; } return FE_OK; } //---------------------------------------------------------- // Function: decode_frame_check // Decode and check the whole frame // // Inputs: // frm ---- Frame input // // Return: // = 0 : OK // < 0 : Errors //---------------------------------------------------------- int decode_frame_check(frame_t *frm) { unsigned short word; register unsigned char *frame = frm->frame; if(!frame)return -FE_UNKNOWN; int i = 6; /* Frame secondary header */ word = (frame[0] << 8) | frame[1]; if ( FRAME_HAS_SHF(word) ) { i = 16; /* Time */ frm->time = (frame[6] << 24) | (frame[7] << 16) | (frame[8] << 8) | frame[9]; /* Checksum flag */ word = (frame[10] << 8) | frame[11]; frm->chksum = FRAME_HAS_CHK(word); } /* Different decoding for different streams */ switch ( frm->apid ) { /* HK data from 1553 */ case APID_AMSHK: //break; /* Fill frames */ case APID_AMSFILL: /* Science data */ case APID_AMSSCI: /* HK data from HRDL/RS422 */ case APID_AMSHKH: /* P2P frames */ case APID_AMSPPC: case APID_AMSPPR: /* get frame status word */ frm->fstat = (frame[i] << 8) | frame[i+1]; i += 2; break; /* Unknown streams */ default: return -FE_UNKNOWN; } /* Randomize */ if ( FSTAT_RANDOMIZED(frm->fstat) ) { printf("randomized\n"); _frame_randomize(&frame[i], (frm->size - i)); } if ( frm->chksum ) { frm->end -= 2; /* Take out the checksum */ word = (frame[frm->end] << 8) | frame[frm->end + 1]; if ( word != _frame_chksum16(frame, frm->end, 0) ) return -FE_CHKSUM; } /* CRC */ if ( FSTAT_HAS_CRC(frm->fstat) ) { if ( _frame_crc16(frame, frm->end) != 0 ) { return -FE_BADCRC; } else frm->end -= 2; /* Take out the CRC word */ } /* Check CHD */ if ( FSTAT_HAS_CHD(frm->fstat) ) { memcpy(frm->chd, (void *) &frame[i], 10); i += 10; } /* Prepare pointers */ frm->data = (unsigned char *) &frame[i]; frm->end -= i; /* Take out the headers */ /* Check frame sequence */ return _frame_check_seq(frm); } //---------------------------------------------------------- // Function: decode_block // Decode AMS block from frames // // Inputs: // frm ---- Frame input // blk ---- Block // // Return: // < 0 : Errors // // >= 0: // bit 16: // 0 - Block not finished // 1 - block finished // bits 0-15: // > 0 : Frame not finished // = 0 : Frame finished //---------------------------------------------------------- int decode_block(frame_t *frm, block_t *blk) { int link; unsigned short word; int remain = 0; int len; unsigned char *ptr; unsigned char *ptr0; /* New frame */ if ( frm->index == 0 ) { /* Get link */ link = FSTAT_LINK(frm->fstat); /* Fill frame has no AMS block */ if ( link == FSTAT_FILL ) return 0; /* No block and end of frame */ link *= 2; /* Change from word point to byte point */ /* New block */ if ( blk->index == BLOCK_HINDEX_FLAG ) { /* No block inside frame */ if ( link >= frm->end ) return 0; /* No block and end of frame */ frm->index = link; } /* Continue on block data */ else if ( blk->index >= 0 ) { /* Wrong link point */ remain = (blk->size - blk->index); /* Remain data size */ if ( remain < link ){ // cout << "remain < link "< link && link < frm->end) ){ // cout << "remain "<end<<" "<size<<" "<index<<" "<index<index != BLOCK_HINDEX_FLAG ) return -BE_BADBLKINP; /* End of frame */ if ( frm->index >= frm->end ){ return 0; /* No block and end of frame */ } } /* Get headers */ //if(blk->length>=10 || blk->length==2)blk->length=0; while ( blk->index < 0 ) { /* Get one word */ ptr = (frm->data + frm->index); ptr0=ptr; word = *ptr++ << 8; word |= *ptr++; frm->index += 2; /* Decode header word */ switch ( blk->index & BLOCK_HINDEX_MASK ) { case 0: /* Block size first word */ /* Long size format */ if ( word & BLOCK_L_MASK ) { blk->size = (word & 0x7FFF) << 16; blk->index = (BLOCK_HINDEX_FLAG | 1); /* SIZE_EXT */ blk->length=0; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; } /* Short size format */ else { blk->size = word; blk->length=0; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; /* No more block in the frame */ if ( blk->size == 0 ) return 0; /* Next */ blk->index = (BLOCK_HINDEX_FLAG | 2); /* Primary header */ } break; case 1: /* Block size the second word */ blk->size |= word; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->index = (BLOCK_HINDEX_FLAG | 2); /* Primary header */ if ( blk->size == 0 ) return -BE_BADSIZE; break; case 2: /* Primary header word */ blk->rr = BLOCK_RR(word); blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->rw = BLOCK_RW(word); blk->node = BLOCK_NODE(word); blk->type = BLOCK_TYPE(word); if ( blk->type == 0x1F ) { blk->type <<= 16; blk->index = (BLOCK_HINDEX_FLAG | 3); /* TYPE_EXT */ } else blk->index = (BLOCK_HINDEX_FLAG | 4); /* Secondary header */ blk->size -= 2; break; case 3: /* TYPE_EXT */ blk->type |= word; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->size -= 2; blk->index = (BLOCK_HINDEX_FLAG | 4); /* Secondary header */ break; case 4: /* Secondary header word */ blk->tag = word; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->size -= 2; if ( blk->rr != 0 ) blk->index = (BLOCK_HINDEX_FLAG | 5); /* secondary header time */ else blk->index = 0; /* End of header */ break; case 5: /* Secondary header time first word */ blk->time = (word << 16); blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->index = (BLOCK_HINDEX_FLAG | 6); blk->size -= 2; break; case 6: /* Secondary header time second word */ blk->time |= word; blk->data2[blk->length++]=*ptr0++; blk->data2[blk->length++]=*ptr0; blk->size -= 2; blk->index = 0; /* End of header */ break; } /* End of frame */ if ( frm->index >= frm->end ) { /* Zero length block finished at the end of frame */ if ( blk->index == 0 && blk->size == 0 ) return BLOCK_END_MARK; /* End of frame only */ else return 0; } } __move_block_data: /* Allocate data */ if ( blk->size > 0 && (blk->data == NULL || blk->index == 0) ) { blk->data = (unsigned char *) realloc(blk->data, blk->size); if ( blk->data == NULL ) return -BE_MALLOC; remain = blk->size - blk->index; } /* No more remain data */ if ( remain == 0 ) { return (BLOCK_END_MARK | (frm->end - frm->index)); } /* No more data in the frame */ if ( frm->index >= frm->end ) return 0; /* Copy data */ len = MIN(remain, (frm->end - frm->index)); memcpy((blk->data + blk->index), (frm->data + frm->index), len); frm->index += len; blk->index += len; /* End of block or end of frame */ return ((blk->index >= blk->size ? BLOCK_END_MARK : 0) | (frm->end - frm->index)); } //---------------------------------------------------------- // Function: decode_block_close // Close an AMS block // // Inputs: // blk ---- Block // // Return: // None //---------------------------------------------------------- void decode_block_close(block_t *blk) { blk->index = BLOCK_HINDEX_FLAG; if ( blk->data != NULL ) free(blk->data); blk->data = NULL; } //---------------------------------------------------------- // Function: decode_block_errmsg // Return block decode error message // // Inputs: // errcode ---- Error code // // Return: // Error message string //---------------------------------------------------------- char *decode_block_errmsg(int errcode) { if ( errcode < 0 ) errcode = -errcode; if ( errcode > BE_LAST ) return block_error_msg[BE_LAST + 1]; return block_error_msg[errcode]; } //---------------------------------------------------------- // Function: decode_subblock // Decode AMS sub-block from event data // // Inputs: // data ---- Input data // size ---- Maximum size of data // blk ----- Sub-block // // Return: // < 0 : Errors // > 0 : Sub-block size include the size word //---------------------------------------------------------- int decode_subblock(unsigned char *data, int size, block_t *blk) { unsigned short word; int i; int len; /* get size */ word = (data[0] << 8) | data[1]; /* Long size format */ if ( word & BLOCK_L_MASK ) { blk->size = ((word & 0x7FFF) << 16) | (data[2] << 8) | data[3]; i = 4; } /* Short size format */ else { blk->size = word; i = 2; } len = blk->size + i; /* Check size */ if ( len > size ) return -BE_BADSIZE; /* Get primary header */ word = (data[i] << 8) | data[i+1]; blk->rr = BLOCK_RR(word); blk->rw = BLOCK_RW(word); blk->node = BLOCK_NODE(word); blk->type = BLOCK_TYPE(word); i += 2; /* TYPE_EXT */ if ( blk->type == 0x1F ) { blk->type = (blk->type << 16) | (data[i] << 8) | data[i+1]; i += 2; } /* Data */ blk->size -= (i - 2); /* Exclude size word itself */ blk->data = &data[i]; return len; } //---------------------------------------------------------- // Function: decode_jmdc_block // Decode event JMDC sub-block // // Inputs: // data ---- Input data // size ---- Maximum size of data // jmdc ---- JMDC Sub-block // // Return: // < 0 : Errors // = 0 : Success //---------------------------------------------------------- int decode_jmdc_block(unsigned char *data, int size, evt_jmdc_t *jmdc) { /* Check size */ if ( size != 22 && size != 32 ) return -BE_BADSIZE; /* Get data */ jmdc->run_number = (data[ 0] << 24) | (data[ 1] << 16) | (data[ 2] << 8) | data[ 3]; jmdc->run_tag = (data[ 4] << 24) | (data[ 5] << 16) | (data[ 6] << 8) | data[ 7]; jmdc->event_number = (data[ 8] << 24) | (data[ 9] << 16) | (data[10] << 8) | data[11]; jmdc->time_sec = (data[12] << 24) | (data[13] << 16) | (data[14] << 8) | data[15]; jmdc->time_usec = (data[16] << 24) | (data[17] << 16) | (data[18] << 8) | data[19]; jmdc->status = (data[20] << 8) | data[21]; /* Check GPS data */ if ( HAS_JMDC_GPS(jmdc->status) ) { if ( size != 32 ) return -BE_BADSIZE; } else { if ( size != 22 ) return -BE_BADSIZE; } return 0; } //---------------------------------------------------------- // Function: decode_dsp_block // Decode event DSP node sub-block // // Inputs: // data ---- Input data // size ---- Maximum size of data // node ---- Node address // dsp ----- DSP node Sub-block // // Return: // < 0 : Errors // = 0 : Success //---------------------------------------------------------- int decode_dsp_block(unsigned char *data, int size, int node, evt_dsp_t *dsp) { unsigned short crc; /* Check CRC */ crc = _frame_crc16(data, size); if ( crc != 0 ) return -BE_BADCRC; /* Check node address */ dsp->node = node; switch (node) { /* JINJ */ case 128 ... 135: dsp->level = LEVEL_JINJ; /* Include two levels inside */ break; /* JINF */ case 150 ... 205: dsp->level = LEVEL_JINF; /* Include one level inside */ break; /* xDR and JLV1 */ default: dsp->level = LEVEL_XDR; /* Single block inside */ break; } /* Get event number */ dsp->event = (data[0] << 8) | data[1]; /* Get status word */ dsp->status = (data[size-4] << 8) | data[size-3]; dsp->port = dsp->status & 0x1F; /* prepare for data */ dsp->data = &data[2]; dsp->size = size - 6; dsp->index = 0; return 0; } //---------------------------------------------------------- // Function: decode_dsp_subblock // Decode DSP node inside sub-block // // Inputs: // data ---- Input data // size ---- Maximum size of data // dsp ----- DSP node Sub-block // // Return: // < 0 : Errors // > 0 : Total size (include size and status words) //---------------------------------------------------------- int decode_dsp_subblock(unsigned char *data, int size, evt_dsp_t *dsp) { int len; /* Check size */ len = ((data[0] << 8) | data[1]) * 2; /* in bytes */ len += 2; /* include size word */ if ( len > size ) return -BE_BADSIZE; /* Get status word */ dsp->status = (data[len-2] << 8) | data[len-1]; dsp->port = dsp->status & 0x1F; dsp->node=dsp->status & 0x1FF; /* prepare for data */ dsp->data = &data[2]; /* After the size word */ dsp->size = len - 4; /* Exclude size and status words */ dsp->index = 0; return len; } //---------------------------------------------------------- // Function: decode_node_name // Decode node name // // Inputs: // node ---- Node address // // Return: // Node name string //---------------------------------------------------------- char *decode_node_name(int node) { return node_names[node & 0x1FF]; } //---------------------------------------------------------- // Function: decode_jinj_port_short // Decode short names for JINJ ports // // Inputs: // port ---- Port number // // Return: // Port name string //---------------------------------------------------------- char *decode_jinj_port_short(int port) { return (jinj_ports_short[port % 24]); } //---------------------------------------------------------- // Function: decode_jinj_port_long // Decode long names for JINJ ports // // Inputs: // port ---- Port number // // Return: // Port name string //---------------------------------------------------------- char *decode_jinj_port_long(int port) { return (jinj_ports_long[port % 24]); } //---------------------------------------------------------- // Function: decode_jinj_level // Decode JINJ port to check if it is a JINF // // Inputs: // port ---- Port number // // Return: // 0 : Not JINF // 1 : JINF //---------------------------------------------------------- int decode_is_jinf(int port) { return (jinj_levels[port % 24]); } //---------------------------------------------------------- // Function: decode_find_jmdc // Find JMDc sub-block // // Inputs: // sub ----- sub-blocks // nsub ---- number of sub-blocks // // Return: // < 0 : Not find // Others : Index of sub-block //---------------------------------------------------------- int decode_find_jmdc(block_t *sub, int nsub) { int i; block_t *b; for ( i = 0; i < nsub; i++ ) { b = &sub[i]; if ( b->node < 22 && (b->type == 7 || b->type==5)) { return i; } } return -1; } //---------------------------------------------------------- // Function: decode_find_lv3 // Find level-3 sub-block // // Inputs: // sub ----- sub-blocks // nsub ---- number of sub-blocks // // Return: // < 0 : Not find // Others : Index of sub-block //---------------------------------------------------------- int decode_find_lv3(block_t *sub, int nsub) { int i; block_t *b; for ( i = 0; i < nsub; i++ ) { b = &sub[i]; if ( b->node < 22 && b->type == 6 ) { return i; } } return -1; }