view gsm-fw/ccd/asn1_choice_ext.c @ 1023:cd6002e3aefb

doc/Freerunner-Howto: apparently some people still use SHR, so mention it too
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Tue, 03 May 2016 13:48:39 +0000
parents 970d6199f2c5
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  
|  Modul   : asn1_choice_ext.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 :  Encoding and decoding functions for ASN1_CHOICE_EXTENSIBLE type
+----------------------------------------------------------------------------- 
*/ 

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

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

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

  PURPOSE : Decode PER extensible CHOICE type 

            The value of the union tag must be calculated from the encoded
            CHOICE index in the air message.
            For CHOICE alternatives within the extension root: the index 
            bit-size relates to max index value in the extension root.
            For CHOICE alternatives within the extension part: the index
            is encoded as a normally small non-negative whole number.

            For decoding the CHOICE alternative itself, call the same 
            function as for non-extensible CHOICE types.
*/
SHORT cdc_asn1_choice_ext_decode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs)
{
  U32    extensionBegin;
  T_ENUM UnionTag; /* default: only one alternative */
  ULONG  calc_ref = calcidx[melem[e_ref].calcIdxRef].condCalcRef;

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

  /* Don't do anything for empty choices */
  if (mcomp[melem[e_ref].elemRef].numOfComponents == 0)
  {
    return 1;
  }

  globs->pstructOffs = melem[e_ref].structOffs;

  /* For optional elements we have already set the valid flag in the 
   * C-structure. We have done it while processing ASN1_SEQ.
   */
  if ( ! cdc_isPresent(e_ref, globs) ) {
    return 1;
  }

  /*
   * Get max value of CHOICE index within the extension root.
   */
  if (calc_ref EQ NO_REF 
      OR 
      calc[calc_ref].operation NEQ 'P')
  {
    ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, 
                     globs->pstruct+globs->pstructOffs);
    return 1;
  }
  else
  {
    extensionBegin = calc[calc_ref].operand;
  }

  /* 
   * Read the extensinon bit.
   * If set to 1, read the CHOICE index as a normally samll
   * non-negative whole number. Otherwise read it according
   * to the bitSize of index in the extension root.
   */
  if (bf_readBit (globs) EQ 0)
  {
    /* CHOICE index is encoded only if there are more than one alternatives. */
    if (mcomp[melem[e_ref].elemRef].numOfComponents > 1)
    {
      UnionTag = (T_ENUM)bf_getBits (bitSize[extensionBegin], globs);
    }
    else
      UnionTag = 0;

    if (UnionTag >= (T_ENUM)extensionBegin)
    {
      ccd_recordFault (globs, ERR_ASN1_ENCODING, BREAK, (USHORT) e_ref, 
                       globs->pstruct+globs->pstructOffs);
    }
    PER_Decode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs);
  }
  else
  {
    U32 finalBP=0; 
    UnionTag = (T_ENUM)Read_NormallySmallNonNegativeWholeNr (globs);
    UnionTag += extensionBegin;
    finalBP = Read_OpenTpye_Length (globs)*8;
    finalBP += globs->bitpos;

    /*
     * For unknown extension skip over the octets.
     */
    if (UnionTag <= (T_ENUM)mcomp[melem[e_ref].elemRef].numOfComponents)
    {
      PER_Decode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs);
    }
    else
    {
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "Unknown extension with CHOICE index = %ld...skipped to the bit %ld", UnionTag, finalBP);
#endif
    }
    bf_setBitpos (finalBP, globs);
  }

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

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

  PURPOSE : Encode PER extensible CHOICE type
            
      Evaluate the union controller.
      1) It refers to a CHOICE alternative within the extension root:
         Set the extension bit to 0. 
         Write the CHOICE index. 
         Then encode the chosen alternative.
       ------------------------------------
      | extension  | CHOICE  | encoded     |
      | bit        | index   | alternative |
       ------------------------------------

      2) It refers to a CHOICE alternative within the extension list:
        Set the extension bit to 1. 
         Encode the CHOICE index as a normally small non-negative whole nr. 
         Skip over 6 bits dedicated to length determinant.
         Encode the chosen alternative. 
         Calculate the bit size of the encoded alternative.
         Encode the calculated bit size into the field of length 
         determinant. Right shift the encoded alternative, if 6 bits 
         are not enough for the length determinant.
       ------------------------------------------------
      | extension | CHOICE | length      | encoded     |
      | bit       | index  | determinant | alternative |
       ------------------------------------------------

            For encoding the CHOICE alternative itself, call the same 
            function as for non-extensible CHOICE types.
*/
SHORT cdc_asn1_choice_ext_encode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs)
{
  U16    startBitpos, Len, EndBitPos;
  T_ENUM UnionTag; /* default: only one alternative */
  U32    extensionBegin;
  ULONG  calc_ref= calcidx[melem[e_ref].calcIdxRef].condCalcRef;

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

  /* Don't do anything for empty choices */
  if (mcomp[melem[e_ref].elemRef].numOfComponents == 0)
  {
    return 1;
  }

  globs->pstructOffs = melem[e_ref].structOffs;

  /* For optional elements we have already set the valid flag in the
   * C-structure. We have done it while processing ASN1_SEQ.
   */
  if ( ! cdc_isPresent(e_ref, globs) )
    return 1;

  /*
   * Get max value of CHOICE index within the extension root.
   */
  if (calc_ref EQ NO_REF 
      OR 
      calc[calc_ref].operation NEQ 'P')
  {
    ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK,(USHORT) e_ref, 
                     globs->pstruct+globs->pstructOffs);
    return 1;
  }
  else
  {
    extensionBegin = calc[calc_ref].operand;
  }

  /*
   * Get the value of chosen index (= union controller).
   */
  UnionTag = *(T_ENUM *) (globs->pstruct+globs->pstructOffs);

  /*
   * The chosen alternative belongs to the extension list.
   */
  if ((U32)UnionTag >= extensionBegin)
  {
    /* Encode the extension bit first */
    bf_writeBit (1, globs);
    /* Encode the CHOICE index. */
    Write_NormallySmallNonNegativeWholeNr (((U32)UnionTag - extensionBegin), globs);

    /* Skip over the bits estimated for the length determinant. */
    bf_incBitpos (8, globs);
    startBitpos = globs->bitpos;
    PER_Encode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs);

    /* 
     * Check if zero padding bits are necessary. If encoding 
     * consumed no bits, insert a zero-octet in the bit string.
     * Then calculate length of the encoded open type in octets.
     */
    if ((Len = globs->bitpos - startBitpos) EQ 0)
    {
      bf_writeVal (0, 8, globs);
      Len = 1;
    }
    else 
    {
      if ((Len&7) NEQ 0)
      bf_incBitpos (8 - (Len&7), globs);		  
      Len = (U16)(globs->bitpos - startBitpos) >> 3;
    }
    EndBitPos = globs->bitpos;

    /* 
     * Encode the length determinant.
     */
    if (Len < 128)
    {
      bf_setBitpos (startBitpos-8, globs);
      Write_OpenTpye_Length ((U32)Len, globs);
    }
    /*
     * This case does not seem to happen very often.
     */
    else
    {
      ccd_recordFault (globs, ERR_ASN1_ENCODING, BREAK,(USHORT) e_ref, 
                       globs->pstruct+globs->pstructOffs);
    }
    /* 
     * Encoding for the extensible choice is finished.
     * Set the bit position pointer to the end of encoded open type.
     */
    bf_setBitpos (EndBitPos, globs);
  }
  /*
   * The chosen alternative belongs to the extension root.
   */
  else
  {    
    bf_writeBit (0, globs);
    /* CHOICE index is encoded only if there are more than one alternatives. */
    if (mcomp[melem[e_ref].elemRef].numOfComponents > 1)
    {
      bf_writeVal ((ULONG) UnionTag, (ULONG) bitSize[extensionBegin], globs);
    }
    PER_Encode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs);
  }

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