FreeCalypso > hg > freecalypso-sw
diff gsm-fw/ccd/csn1_sx.c @ 648:970d6199f2c5
gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Thu, 04 Sep 2014 05:48:57 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/ccd/csn1_sx.c Thu Sep 04 05:48:57 2014 +0000 @@ -0,0 +1,687 @@ +/* ++----------------------------------------------------------------------------- +| Project : CCD +| Modul : csn1_sx.c ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose : Definition of encoding and decoding functions for CSN1_S0 elements ++----------------------------------------------------------------------------- +*/ +/* + * standard definitions like GLOBAL, UCHAR, ERROR etc. + */ +#include "typedefs.h" +#include "header.h" + + +/* + * Prototypes of ccd (USE_DRIVER EQ undef) for prototypes only + * look at ccdapi.h + */ +#undef USE_DRIVER +#include "ccdapi.h" + +/* + * Types and functions for bit access and manipulation + */ +#include "ccd_globs.h" +#include "bitfun.h" + +/* + * Prototypes of ccd internal functions + */ +#include "ccd.h" + +/* + * Declaration of coder/decoder tables + */ +#include "ccdtable.h" +#include "ccddata.h" + +/* + * Need memory allocation functions for dynamic arrays (pointers) + */ +#ifdef DYNAMIC_ARRAYS +#include "vsi.h" +#include <string.h> +#endif + + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : CCD (6144) MODULE : CCD | +| STATE : code ROUTINE : cdc_csn1_sx_decode | ++--------------------------------------------------------------------+ + + PURPOSE : The encoded IE consists of one bit for presence flag and + a value part. + In case of CSN1_S1 only if the flag bit is equal 1 the + value part will follow it. + In case of CSN1_S0 only if the flag bit is equal 0 the + value part will follow it. +*/ + +SHORT cdc_csn1_sx_decode (int flag, const ULONG e_ref, T_CCD_Globs *globs) +{ + ULONG repeat, max_rep, act_offset; + ULONG amount = 1; + BOOL is_variable; + ULONG cix_ref, num_prolog_steps, prolog_step_ref; +#ifdef DYNAMIC_ARRAYS + U8 *old_pstruct = NULL; + U8 *addr = NULL; +#endif + +#ifdef DEBUG_CCD + #ifndef CCD_SYMBOLS + TRACE_CCD (globs, "cdc_csn1_sx_decode()"); + #else + TRACE_CCD (globs, "cdc_csn1_sx_decode() %s", ccddata_get_alias((USHORT) e_ref, 1)); + #endif +#endif + + globs->SeekTLVExt = FALSE; + + cix_ref = melem[e_ref].calcIdxRef; + num_prolog_steps = calcidx[cix_ref].numPrologSteps; + prolog_step_ref = calcidx[cix_ref].prologStepRef; + + /* + * If this element is conditional, check the condition. + */ + if (calcidx[cix_ref].numCondCalcs NEQ 0 + AND ! ccd_conditionOK (e_ref, globs)) + return 1; + + /* + * If this element has a defined prologue + * we have to process it before decoding the bitstream. + */ + if (num_prolog_steps) + { + ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); + } + + if (melem[e_ref].repType NEQ ' ') + { + is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs); + /* Structured IE is to be handeled as bitstring.*/ + if (melem[e_ref].repType == 's') + { + repeat--; + } + } + else + { + is_variable = FALSE; + repeat = 1; + } + +#ifdef DYNAMIC_ARRAYS + /* + * Check for pointer types; allocate memory if necessary. + * May overwrite globs->pstruct (and initialize globs->pstructOffs to 0). + */ + if ( is_pointer_type(e_ref) ) + { + U32 cSize; + + /* + * Find size to allocate; + * - Read from mcomp or mvar according to type + */ + cSize = (ULONG)((melem[e_ref].elemType EQ 'F' OR + melem[e_ref].elemType EQ 'R') + ? mvar[melem[e_ref].elemRef].cSize + : mcomp[melem[e_ref].elemRef].cSize + ) * repeat; + + /* + * Allocate additional memory + */ + addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS); + + /* If no memory, log error and return immediately */ + if (addr EQ NULL) { + ccd_setError (globs, ERR_NO_MEM, + BREAK, + (USHORT) -1); + return 1; + } + else + memset (addr, 0, (size_t)cSize); + + /* + * Memory allocated; + */ + } +#endif + + if (melem[e_ref].elemType NEQ 'S') + { + /* + * Element is not a SPARE. Setup the struct pointer. + */ + globs->pstructOffs = melem[e_ref].structOffs; + + + if (is_variable) + { + UBYTE *addr_v_xxx = NULL; + UBYTE *addr_c_xxx; + UBYTE act_continue_array; + + + if (melem[e_ref].optional) + { + /* + * For optional elements we must set the valid-flag, + * if there is at least one element in the message. + * Therefore we store the address of the valid flag. + */ + /* Dynamic array addition. + * Postpone optional flag setting for non-code transparent + * pointer types ('P', 'Q', 'R'). + * For these types, the optional flag is the pointer itself. + * These types cannot be set yet, as the pointer may be + * preceeded by a counter octet, a union tag id octet etc. + */ + if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R') + addr_v_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++); + } + /* + * For variable sized elements store the min-value + * as counter into the C-Structure (c_xxx). + */ + addr_c_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++); + if (max_rep > 255) + globs->pstructOffs++; + + /* + * Store the initial offset + */ + + act_offset = (ULONG) globs->pstructOffs; + +#ifdef DYNAMIC_ARRAYS + if ( is_pointer_type(e_ref) ) + { + /* + * 1. Save old "globs->pstruct" variables + * 2. Store pointer to freshly allocated memory area in structure + * 3. Initialize pstruct to point to the freshly allocated memory area. + * 4. Initialize pstructOffs to 0 to start decoding at offset 0 + * in the new memory area. + */ + old_pstruct = globs->pstruct; + *(U8 **)(globs->pstruct + globs->pstructOffs) = addr; + globs->pstruct = addr; + globs->pstructOffs = 0; + } +#endif + + /* + * repType ='i': + * Repeat this element (if it is an array) until we detect a + * flag indicating absence. + * + * repType ='v' and 'c': + * Repeat the IE and leave the loop. + * + * In both cases we expect a 0 at first. + */ + if ((melem[e_ref].repType == 'v') || (melem[e_ref].repType == 'c')) + { + amount = repeat; + } + repeat = 0; + act_continue_array = globs->continue_array; + globs->continue_array = TRUE; + + while (globs->continue_array) + { + if (flag == 0xFF) /* CSN1_SH type*/ + { + if (bf_readBit(globs) != GET_HL_PREV(1)) + break; + } + else + { + if (bf_readBit(globs) != flag) + break; + } + /* + * Flag is set, we must decode the element + */ + + cdc_decodeElemvalue (e_ref, &amount, globs); + + if (++repeat > max_rep) + { + /* + * Too many repetitions means error in encoded message. + */ + ccd_setError (globs, ERR_MAX_REPEAT, + BREAK, + (USHORT) (globs->bitpos), + (USHORT) -1); + return 1; + } + else if (melem[e_ref].repType EQ 'v') + { + repeat = amount; + break; + } + /* + * Recalculate the struct offset for repeatable IEs. + */ + if (is_variable_type(e_ref)) + { + globs->pstructOffs = (USHORT)(act_offset + + (repeat * mvar[melem[e_ref].elemRef].cSize)); + } + else + { + globs->pstructOffs = (USHORT)(act_offset + + (repeat * mcomp[melem[e_ref].elemRef].cSize)); + } + } + globs->continue_array = act_continue_array; + +#ifdef DYNAMIC_ARRAYS + /* + * Restore globs->pstruct + */ + if (old_pstruct NEQ NULL) + { + globs->pstruct = old_pstruct; + } +#endif + + if (addr_v_xxx NEQ NULL) + { + /* + * For optional elements set the valid-flag + * In this case the pointer addr_c_xxx does not mark + * the counter. It points to the valid flag. + */ + if (repeat > 0) + *addr_v_xxx++ = (UBYTE) TRUE; + } + /* + * Store the number of digits into the c_xxx variable if there is one. + */ + if (max_rep > 65535) + { + ULONG *addr_c_xxx_u32; + addr_c_xxx_u32 = (ULONG *)addr_c_xxx; + *addr_c_xxx_u32 = repeat; + } + else if (max_rep > 255) + { + USHORT *addr_c_xxx_u16; + addr_c_xxx_u16 = (USHORT *)addr_c_xxx; + *addr_c_xxx_u16 = (USHORT) repeat; + } + else + *addr_c_xxx = (UBYTE) repeat; + } + /* + * IE is not defined as an array. + */ + else + { + BOOL elemPresent; + + if (flag == 0xFF) + elemPresent = (bf_readBit(globs) EQ GET_HL_PREV(1)); + else + elemPresent = (bf_readBit(globs) == flag); + + if (elemPresent) + { + if (melem[e_ref].optional) + { + /* + * For optional elements set the valid-flag. + */ + globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE; + } + + /* + * Flag is set, we must decode the element. + */ + cdc_decodeElemvalue (e_ref, &repeat, globs); + /* + * process the epilogue expression for this element if there is any + */ + if (num_prolog_steps) + { + if ( (calc[prolog_step_ref+1].operation EQ 'K') + || (calc[prolog_step_ref+1].operation EQ 'C') + || (calc[prolog_step_ref+1].operation EQ 's')) + { + ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); + } + } + } + } + } + + return 1; +} +#endif /* !RUN_FLASH */ + +#ifndef RUN_FLASH +/* ++--------------------------------------------------------------------+ +| PROJECT : CCD (6144) MODULE : CDC_GSM | +| STATE : code ROUTINE : cdc_csn1_sx_encode | ++--------------------------------------------------------------------+ + + PURPOSE : Encoding of the CSN1 element. + 1) GSM Type CSN1 S1 element + This element consists of a 1 bit valid flag and a + value part. If the element is valid (the v_xxx + components is TRUE in the decoded message) a 1 bit will + be coded followed by the coding of the value part. + Otherwise a 0 bit will be coded. + + 2) GSM Type CSN1 S0 element + This element consists of a single bit valid flag and a + value part, too. But in this case the presence flag is + set to 0. If the element is present (the v_xxx component + is TRUE in the decoded message) a 0 bit will be coded + followed by the encoded value part. Otherwise a 1 bit + will be encoded. +*/ + +SHORT cdc_csn1_sx_encode (int flag, const ULONG e_ref, T_CCD_Globs *globs) +{ + ULONG i, repeat=1, amount=1; + USHORT cSize = 0, startOffset; + int elemPresent; + ULONG cix_ref, num_prolog_steps, prolog_step_ref; +#ifdef DYNAMIC_ARRAYS + U8 *old_pstruct = NULL; +#endif + +#ifdef DEBUG_CCD + #ifndef CCD_SYMBOLS + TRACE_CCD (globs, "cdc_csn1_sx_encode()"); + #else + TRACE_CCD (globs, "cdc_csn1_sx_encode() %s", ccddata_get_alias((USHORT) e_ref, 1)); + #endif +#endif + + cix_ref = melem[e_ref].calcIdxRef; + num_prolog_steps = calcidx[cix_ref].numPrologSteps; + prolog_step_ref = calcidx[cix_ref].prologStepRef; + /* + * If this element is conditional, check the condition. + */ + if (calcidx[cix_ref].numCondCalcs NEQ 0 + AND ! ccd_conditionOK (e_ref, globs)) + return 1; + + /* + * If this element has a defined prologue + * we have to process it before decoding the bitstream. + */ + if (num_prolog_steps) + { + ccd_performOperations (num_prolog_steps, prolog_step_ref, globs); + } + + if (melem[e_ref].elemType NEQ 'S') + { + UBYTE act_continue_array; + + act_continue_array = globs->continue_array; + globs->continue_array = TRUE; + /* + * Element is not a SPARE. + * Setup the offset into the C-structure for this element + */ + globs->pstructOffs = melem[e_ref].structOffs; + + if (melem[e_ref].optional) + { + /* + * For optional elements check the valid-flag in the C-struct. + * Spare elements does not have a corresponding valid flag. + */ + /* Dynamic array addition. + * Postpone optional flag setting for non-code transparent + * pointer types ('P', 'Q', 'R'). + * For these types, the optional flag is the pointer itself. + * These types cannot be set yet, as the pointer may be + * preceeded by a counter octet, a union tag id octet etc. + */ + if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R') + { + if (globs->pstruct[globs->pstructOffs++] == FALSE) + { + /* + * The IE should not be present in the message so we code + * a single bit + * for CSN1_S1 as 0, + * for CSN1_S0 as 1 and + * for CSN1_SH as GET_HL(0) + */ + if (flag == 0xFF) + elemPresent = GET_HL(0); + else + elemPresent = flag ^ 0x00000001; + bf_writeBit (elemPresent, globs); + return 1; + } +#ifdef DEBUG_CCD + else if (globs->pstruct [melem[e_ref].structOffs] != TRUE) + { + TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d", + e_ref); + } +#endif + } + } + + /* As a default amount =1 due to initialization. */ + if (melem[e_ref].repType EQ 'i') + { + /* The actual number of elements belonging to the array is unknown. + * The user should have written the desired number to the C-Structure + * (c_xxx). CCD reads the number of these variable repeatable elements + * out of this C-Structure (c_xxx) and encodes each element with a + * preceeding bit set to '0'. The last element is followed by a bit + * set to '1' to indicate the end of this array. + * If the number of repeats given by the C-Structure exceeds the + * allowed value (maxRepeat) CCD gives a warning! + */ + if (melem[e_ref].maxRepeat > 255) + { + ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++)); + repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat); + if (repeat < count) + ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, + (USHORT) e_ref, globs->pstruct + globs->pstructOffs); + } + else + { + repeat = (ULONG) MINIMUM (globs->pstruct[globs->pstructOffs], + melem[e_ref].maxRepeat); + if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) ) + ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, + (USHORT) e_ref, globs->pstruct + globs->pstructOffs); + } + amount = 1; + globs->pstructOffs++; + } + else + if (melem[e_ref].repType EQ 'v') + { + /* The number of elements belonging to the array depends on the value + * of another element. The user should have written this number to the + * C-Structure (c_xxx). + * CCD reads the number of these variable repeatable elements out of + * this C-Structure (c_xxx). + * If the number of repetitions given by the C-Structure exceeds the + * allowed value (maxRepeat) CCD gives a warning! + */ + if (melem[e_ref].maxRepeat > 255) + { + ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++)); + amount = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat); + if (amount < count) + ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, + (USHORT) e_ref, globs->pstruct + globs->pstructOffs); + } + else + { + amount = (ULONG)MINIMUM (globs->pstruct[globs->pstructOffs], + melem[e_ref].maxRepeat); + if ( amount < (ULONG) (globs->pstruct[globs->pstructOffs]) ) + ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, + (USHORT) e_ref, globs->pstruct + globs->pstructOffs); + } + repeat = 1; + globs->pstructOffs++; + } + else + if (melem[e_ref].repType EQ 'c') + { + amount = (ULONG) melem[e_ref].maxRepeat; + repeat = 1; + } + else + if (melem[e_ref].repType == 's') + { + BOOL is_variable; + ULONG max_rep; + + is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs); + /* Substract one bit which will be spent on the (CSN.1) flag. */ + amount = repeat - 1; + repeat = 1; + } + if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i') + { + cSize = (USHORT)((melem[e_ref].elemType EQ 'V' OR + melem[e_ref].elemType EQ 'R' OR melem[e_ref].elemType EQ 'F') + ? mvar[melem[e_ref].elemRef].cSize + : mcomp[melem[e_ref].elemRef].cSize + ); + + startOffset = (USHORT) globs->pstructOffs; + } + + /* Dynamic array addition. + * Check for non-code transparent pointer types ('P', 'Q', 'R'). + * For these types, the optional flag is the pointer itself. + * ASSUMPTION: The pointer may be preceeded by a counter octet, + * a union tag id octet etc., but it is up to CCDGEN to ensure + * word alignment (by inserting alignment bytes). Therefore + * we just read from globs->pstruct[globs->pstructOffs]. + */ +#ifdef DEBUG_CCD + /* Check pointer alignment and re-align if necessary (should never happen) */ + if ( is_pointer_type(e_ref) AND ((globs->pstructOffs & 3) NEQ 0)) { + TRACE_CCD (globs, "cdc_csn1_sx_encode(): Pointer misaligned! pstruct=0x08x," + " pstructOffs=0x%08x", globs->pstruct, globs->pstructOffs); + globs->pstructOffs = (globs->pstructOffs + 3) & 3; + } +#endif +#ifdef DYNAMIC_ARRAYS + /* + * Perform pointer dereference for pointer types. + * Also, check optionality for these types. + */ + if ( is_pointer_type(e_ref) ) { + U8 *deref_pstruct; + + /* Get pointer value */ + deref_pstruct = *(U8 **)&globs->pstruct[globs->pstructOffs]; + + /* + * Strictly speaking the 'D' to 'F' types should not need this + * check (should have returned after the optionality check above), + * but it will catch stray NULL pointers (or uninitialized + * valid flags) + */ + if (ccd_check_pointer(deref_pstruct) != ccdOK ) + { + ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, + &globs->pstruct[globs->pstructOffs]); + return 1; + } + /* + * Pointer not NULL; + * 1. Save old globs->pstruct and assign pointer to globs->pstruct + * as new base. + * 2. Set pstructOffs to 0 (zero) as the next offset will start + * in the new memory area. + */ + old_pstruct = globs->pstruct; + globs->pstruct = deref_pstruct; + startOffset = 0; + } +#endif /* DYNAMIC_ARRAYS */ + + for (i=0; i < repeat; i++) + { + /* + * The IE should be present in the message so we code 0 bit. + */ + if (flag == 0xFF) + elemPresent = GET_HL(1); + else + elemPresent = flag; + + bf_writeBit (elemPresent, globs); + if (cSize) + { + /* + * Calculate the offset if it is an array. + */ + globs->pstructOffs = (USHORT)(startOffset + (i * cSize)); + } + /* + * Encode the value. + */ + cdc_encodeElemvalue (e_ref, amount, globs); + } + +#ifdef DYNAMIC_ARRAYS + if ( old_pstruct NEQ NULL ) + globs->pstruct = old_pstruct; +#endif + + if ((melem[e_ref].repType == 'i') && (globs->continue_array == TRUE)) + { + /* + * For fields of variable length we code a 1 flag + * to mark the end of the array. + */ + if (flag == 0xFF) + elemPresent = GET_HL(0); + else + elemPresent = flag ^ 0x00000001; + bf_writeBit (elemPresent, globs); + } + globs->continue_array = act_continue_array; + } + + return 1; +} +#endif /* !RUN_FLASH */