view gsm-fw/ccd/asn1_seq.c @ 1034:405b5469abc4 default tip

top README: repository change notice
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 12 Jun 2016 19:06:34 +0000
parents 970d6199f2c5
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  
|  Modul   : asn1_seq.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 ASN1_SEQUENCE
|             elements 
+----------------------------------------------------------------------------- 
*/ 

#define ASN1_SEQ_C

/*
 * Standard definitions like 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 and constants in the common part of ccd
 */
#include "ccd.h"
#include "ccd_codingtypes.h"

/*
 * Declaration of coder/decoder tables
 */
#include "ccdtable.h"
#include "ccddata.h"

EXTERN T_FUNC_POINTER codec[MAX_CODEC_ID+1][2];

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : asn1_seq               |
| STATE   : code                    ROUTINE : Read_SEQ_BitMap        |
+--------------------------------------------------------------------+

  PURPOSE : Decode the bit-map preamble for OPTIONAL elements 
            or those with DEFAULT value.
*/
void Read_SEQ_BitMap (const ULONG first_elem, const ULONG last_elem, T_CCD_Globs *globs)
{
  ULONG elem = first_elem;
  while (elem < last_elem)
  {
    if (melem[elem].optional)
    {
      /* 
       * For optional elements read the corresponding bit in the preamble
       * and set the valid flag in the C-Structure to it.
       */             
      if (melem[elem].elemType < 'P' OR melem[elem].elemType > 'R')
      {
        globs->pstruct[melem[elem].structOffs] = (UBYTE) bf_readBit(globs);
      }
      else
      {
        if(bf_readBit(globs)) /*elemType P, Q or R*/
        {
          /*If present set the pointer to -1 (0xFFFF) - anything else than NULL, because the 
          element is present*/
          *(void**) &globs->pstruct[melem[elem].structOffs] = (void *) 0xFFFF;
        }
        else /*Not present set the pointer to NULL*/
          *(void**) &globs->pstruct[melem[elem].structOffs] = NULL;
      
      }
    }
    /* 
     * For optional elements read the corresponding bit in the preamble
     * and set the valid flag in the C-structure to it.
     */
    else if (melem[elem].codingType EQ CCDTYPE_ASN1_INTEGER)
    {       
      /* 
       * Check if this variable has a default value.
       * As long as the DEFAULT values are given with ranges it is right to
       * look for isDefault in the second entry in mval.cdg.
       * There is no valid flag for elements with default value. But we use
       * the first byte of this element within the C-structure for giving a
       * signal to this function. The only simple type which has DEFAULT is INTEGER.
       */
      if (mval[mvar[melem[elem].elemRef].valueDefs+1].isDefault EQ 2)
      {
        globs->pstruct[melem[elem].structOffs] = (UBYTE) bf_readBit(globs);
      }           
    }
    elem++;
  }
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_GSM                |
| STATE   : code                    ROUTINE : cdc_asn1_seq_decode    |
+--------------------------------------------------------------------+

  PURPOSE : Decoding of the SEQUENCE and SEQUENCE OF type for UMTS
            The element can be a field of fixed or variable length.
            It can contain OPTIONAL elements or integer elements with 
            a DEFAULT value. 
            A special case is when the element is a so called msg_data. 
            According to CCDDATA a message is made of a msg_type and 
            a msg_data part. If the msg_data has a coding type of 
            ASN1_SEQUENCE this function is called.
            In this case CCD needs to pass over the msg_type by 
            incrementing globs->pstruct. A msg_data sequence can not 
            be optional. Nor it can be an array of msg_data. 
            If the sequence is not a msg_data this function is called 
            as an equivalent to ccd_decodeComposition. Hence the 
            increment on globs->ccd_recurs_level. A non-msg_data 
            sequence can be optional or an array.    
*/ 
SHORT cdc_asn1_seq_decode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs)
{
  ULONG  repeat=1, max_rep=1; 
  ULONG  cSize, first_elem, last_elem, elem;
  UBYTE  *old_pstruct;
#ifdef DEBUG_CCD
	static S8 trace_nesting_level = -1;
#endif

#ifdef DEBUG_CCD
	#ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_asn1_seq_decode()");
	#else
	TRACE_CCD (globs, "cdc_asn1_seq_decode() %s", mcomp[melem[e_ref].elemRef].name);
	#endif
#endif

  /* 
   * This function is called as an equivalent to ccd_decodeComposition.  
   * Hence the increment on globs->ccd_recurs_level.
   */
  globs->ccd_recurs_level ++;

  /* 
   * Set pstrcutOffs and max_rep. 
   * Check the valid flag in case of optional elements.
   */
  if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK)
  {
    globs->ccd_recurs_level --;
    return 1;
  }

  /*
   * Prepare for decoding of the same sequence type up to max_rep times.
   * Set the upper and lower bound of elemRef for processing of each repeatition.
   * Read the C-size to go ahead in the C-structure after each repeatition.
   */
  switch (melem[e_ref].elemType)
  {
    case 'C':
    case 'D':
    case 'E':
    case 'P':
    case 'Q':
              elem       = (ULONG) melem[e_ref].elemRef;
              first_elem = (ULONG) mcomp[elem].componentRef;
              last_elem  = first_elem + mcomp[elem].numOfComponents;
              cSize      = (ULONG) mcomp[elem].cSize;
              break;
    case 'F':
    case 'R':
              first_elem = e_ref;
              last_elem  = e_ref + 1;
              cSize      = (ULONG) mvar[e_ref].cSize;
              break;
    default:
              ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, 
                        (USHORT) (globs->bitpos), (USHORT) -1);
              return 1;
         
  };
  /*
   * Store the current value of the C-structure pointer.  
   * After decoding the SEQUENCE component we will set the pointer 
   * to this stored value. Then we will use pstructOffs for pointing   
   * to the next element.
   */
  old_pstruct = globs->pstruct;
#ifdef DYNAMIC_ARRAYS
  /*
   * Allocate memory for this whole composition, if elemType is
   * one of the pointer types.
   */
  if ( is_pointer_type(e_ref))
  {
    if ( PER_allocmem_and_update(e_ref, max_rep, globs) NEQ ccdOK )
    {
    /* No memory - Return.  Error already set in function call above. */
    globs->ccd_recurs_level --;
    return 1;
    }

  }
#endif
  globs->pstruct += globs->pstructOffs;

  /*
   * Decode all elements of the field.
   */
  while (repeat <= max_rep)
  {
    Read_SEQ_BitMap (first_elem, last_elem, globs);
    elem = first_elem;
    
    /*
     * Decode all elements of the array
     */
#ifdef DEBUG_CCD
		trace_nesting_level++;
#endif
    while (elem < last_elem)
    {
#ifdef ERR_TRC_STK_CCD
      /* 
       * Save the value for tracing in error case.
       */
      globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem;
#endif /* ERR_TRC_STK_CCD */

#ifdef DEBUG_CCD
	#ifndef CCD_SYMBOLS
		TRACE_CCD (globs, "decoding level %d element %d", trace_nesting_level, elem - first_elem);
	#else
    TRACE_CCD (globs, "decoding level %d element %d '%s'",trace_nesting_level, elem - first_elem, ccddata_get_alias((USHORT) elem, 1));
	#endif
#endif

      /*
       * Use the jump-table for selecting the decode function.
       * Possible types are 0, ASN1_INTEGER, BITSTRING, ASN1_CHOICE and 
       * ASN1_SEQUENCE. In case of 0 function cdc_STD_decode will be called.
       */
			(void) codec[melem[elem].codingType][DECODE_FUN]
                                            (c_ref, elem, globs);
      elem ++;
    }
#ifdef DEBUG_CCD
		trace_nesting_level--;
#endif

    /*
     * Set the pointer of the C-structure on the next element.
     */
    globs->pstruct += cSize; 

    repeat ++;
  }

  /*
   * Prepare for decoding the next element.
   */
  globs->pstruct = old_pstruct;
  globs->ccd_recurs_level--;

  return 1;
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : asn1_seq               |
| STATE   : code                    ROUTINE : Write_SEQ_BitMap       |
+--------------------------------------------------------------------+

  PURPOSE : Encode the bit-map preamble for OPTIONAL elements 
            or those with DEFAULT value.
*/
void Write_SEQ_BitMap (const ULONG first_elem, const ULONG last_elem, T_CCD_Globs *globs)
{
  ULONG elem = first_elem;
    while (elem < last_elem)
    {
      if (melem[elem].optional)
      {
        /* 
         * For optional elements read the valid flag in the C-Structure  
         * and overwrite the corresponding bit in the preamble.
         */             

#if defined _TOOLS_
        int patch;
        U16 stelem;
        stelem = globs->error_stack[globs->ccd_recurs_level];
        globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem;
        patch = ccd_patch (globs, 1);
        globs->error_stack[globs->ccd_recurs_level] = stelem;
        if (patch)
        {
          bf_writeBit(1, globs);
          elem++;
          continue;
        }
#endif /* _TOOLS_ */

#ifdef DYNAMIC_ARRAYS
	    if ( is_pointer_type(elem) )
      {
	      BOOL   present;
	      /*
	       * Check for NULL pointer (== notPresent/not valid) for this element.
	       */
	      present = (*(U8 **)(globs->pstruct + melem[elem].structOffs) NEQ NULL);
	      /*
	       * Double check for 'D' to 'F' types. Both NULL pointer and
	       * valid flag. (Strictly not necessary, but may catch uninitialized
	       * flags/pointers).
	       */
	      if (present AND (melem[elem].elemType >= 'D' AND
			       melem[elem].elemType <= 'F')) 
        {
	        present = (BOOL)globs->pstruct[melem[elem].structOffs];
	      }
	      bf_writeBit(present, globs);
	    } 
      else
#endif
	      bf_writeBit((BOOL)globs->pstruct[melem[elem].structOffs], globs);
      }
      else if (melem[elem].codingType EQ CCDTYPE_ASN1_INTEGER)
      {       
        /* 
         * Check if this variable has a default value.
         * As long as the DEFAULT values are given with ranges it is right to
         * look for isDefault in the second entry in mval.cdg.
         * There is no valid flag for elements with default value. So we need
         * to read the value from C-structure and compare it with the DEFAULT 
         * value given in the mval table. The only simple type which has 
         * DEFAULT is INTEGER. 
         */
        if (mval[mvar[melem[elem].elemRef].valueDefs+1].isDefault EQ 2)
        {
          U32 value=0;
          UBYTE *p;
          /*
           * setup the read pointer to the element in the C-structure
           */
#ifdef DYNAMIC_ARRAYS
          if ( is_pointer_type(elem) )
          {
            /*
             * NULL pointers should be caught as part of the optionality
             * check in PER_CommonBegin()
             */
            p = *(U8 **)(globs->pstruct + globs->pstructOffs);
            if (ccd_check_pointer(p) != ccdOK)
            {
               ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) elem, 
                                &globs->pstruct[globs->pstructOffs]);
               return;
            }
          }
          else
#endif
          p = globs->pstruct + melem[elem].structOffs;
          /*
           * Default values are all positive and small values (< 64K)
           * in the current version of umts. The cases 'L' and 'C' are added
           * to be ready for a future change where we need also a check of
           * possible errors through type casting.
           */
          switch (mvar[melem[elem].elemRef].cType)
          {
            case 'B':
                      value = (U32)*(UBYTE *) p;
                      break;
            case 'C':
                      value = (U32)(S32)*(S8 *) p;
                      break;
            case 'S':
                      value = (U32)(*(USHORT *) p);
                      break;
            case 'T':
                      value = (U32)(S32)*(S16 *) p;
                      break;
            case 'L':
                      value = (U32)*(S32 *) p;
                      break;
            case 'M':
                      value = (U32)*(U32 *) p;
                      break;
            default:
                      ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) -1);
                      break;
          }
          /* 
           * Compare the value to be encoded with the default value. 
           * Write the presence flag into the preamble.
           */
          if (value EQ (U32)mval[mvar[melem[elem].elemRef].valueDefs+1].startValue)
          {
            bf_writeBit(0, globs);
          }
          else
          {
            bf_writeBit(1, globs);
          }
        }           
      }
      elem++;
    }
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_GSM                |
| STATE   : code                    ROUTINE : cdc_asn1_seq_encode    |
+--------------------------------------------------------------------+

  PURPOSE : Decoding of the SEQUENCE and SEQUENCE OF type for UMTS
            The element can be a field of fixed or variable length.
            It can contain OPTIONAL elements or integer elements with 
            a DEFAULT value. 
            A special case is when the element is a so called msg_data. 
            According to CCDDATA a message is made of a msg_type and 
            a msg_data part. If the msg_data has a coding type of 
            ASN1_SEQUENCE this function is called.
            In this case CCD needs to pass over the msg_type by 
            incrementing globs->pstruct. A msg_data sequence can not 
            be optional. Nor it can be an array of msg_data. 
            If the sequence is not a msg_data this function is called 
            as an equivalent to ccd_encodeComposition. Hence the 
            increment on globs->ccd_recurs_level. A non-msg_data 
            sequence can be optional or an array.
*/
SHORT cdc_asn1_seq_encode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs)
{
  ULONG  repeat=1, max_rep=1; 
  ULONG  cSize, first_elem, last_elem, elem;
  UBYTE  *old_pstruct;
#ifdef DEBUG_CCD
	static S8 trace_nesting_level = -1;
#endif

#ifdef DEBUG_CCD
	#ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_asn1_seq_encode()");
	#else
	TRACE_CCD (globs, "cdc_asn1_seq_encode() %s", mcomp[melem[e_ref].elemRef].name);
	#endif
#endif

  /* 
   * This function is called as an equivalent to ccd_encodeComposition.
   * Hence the increment on globs->ccd_recurs_level.
   */
  globs->ccd_recurs_level ++;

  /* 
   * Set pstrcutOffs and max_rep. 
   * Check the valid flag in case of optional elements.
   */
  if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK)
  {
    globs->ccd_recurs_level --;
    return 1;
  }

  /*
   * Prepare for encoding of the same sequence type up to max_rep times.
   * Set the upper and lower bound of elemRef for processing of each repeatition.
   * Read the C-size to go ahead in the C-structure after each repeatition.
   */ 
  switch (melem[e_ref].elemType)
  {
    case 'C':
    case 'D':
    case 'E':
    case 'P':
    case 'Q':
    {
              elem       = (ULONG) melem[e_ref].elemRef;
              first_elem = (ULONG) mcomp[elem].componentRef;
              last_elem  = first_elem + mcomp[elem].numOfComponents;
              cSize      = (ULONG) mcomp[elem].cSize;
              break;
    }
    case 'F':
    case 'R':
    {
              first_elem = e_ref;
              last_elem  = e_ref + 1;           
              cSize      = (ULONG) mvar[e_ref].cSize;
              break;
    }
    default:
              ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, 
                        (USHORT) (globs->bitpos), (USHORT) -1);
              return 1;
         
  }
  /*
   * Store the current value of the C-structure pointer.  
   * After encoding the SEQUENCE component we will set the pointer 
   * to this stored value. Then we will use pstructOffs for pointing
   * to the next element.  
   */  
  old_pstruct = globs->pstruct;
  globs->pstruct += globs->pstructOffs;

#ifdef DYNAMIC_ARRAYS
  if ( is_pointer_type(e_ref) ) {
    if (ccd_check_pointer(*(U8 **)globs->pstruct) == ccdOK)
    {
      globs->pstruct = *(U8 **) globs->pstruct;
    }
    else
    {
       ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, 
                        &globs->pstruct[globs->pstructOffs]);
       return 1;
    }
  }
#endif


  /*
   * Encode all elements of the field.
   */
  while (repeat <= max_rep)
  { 
    Write_SEQ_BitMap (first_elem, last_elem, globs); 

    /*
     * Encode all elements
     */
#ifdef DEBUG_CCD
		trace_nesting_level++;
#endif

    elem = first_elem;
    while (elem < last_elem)
    {
#ifdef ERR_TRC_STK_CCD
      /* 
       * Save the value for tracing in error case.
       */
      globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem;
#endif /* ERR_TRC_STK_CCD */    
#ifdef DEBUG_CCD
	#ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "encoding level %d element %d", trace_nesting_level, elem - first_elem);
	#else
    TRACE_CCD (globs, "encoding level %d element %d '%s'", trace_nesting_level, elem - first_elem ,ccddata_get_alias((USHORT) elem, 1));
	#endif
#endif

#if defined _TOOLS_
      if (!ccd_patch (globs, 0))
#endif /* _TOOLS_ */
      /*
       * Use the jump-table for selecting the code function.
       * Possible types are 0, ASN1_INTEGER, BITSTRING, ASN1_CHOICE and 
       * ASN1_SEQUENCE. In case of 0 function cdc_STD_encode will be called.
       */
      (void) codec[melem[elem].codingType][ENCODE_FUN]
                                            (c_ref, elem, globs);
      /*
       * Set the elemRef to the next element.
       */
      elem ++;
    }
#ifdef DEBUG_CCD
		trace_nesting_level--;
#endif
    /*
     * Set the pointer of the C-structure on the next element.
     */ 
    globs->pstruct += cSize;

    repeat ++;
  }

  /*
   * Prepare for encoding the next element.
   */
  globs->pstruct = old_pstruct;
  globs->ccd_recurs_level--;
  return 1;
}
#endif /* !RUN_INT_RAM */