view src/gpf/ccd/csn1_sx.c @ 5:1ea54a97e831

src/gpf: import of Magnetite src/gpf3
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 08:11:07 +0000
parents
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  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 */