diff gsm-fw/ccd/ccd.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/ccd.c	Thu Sep 04 05:48:57 2014 +0000
@@ -0,0 +1,3424 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  
+|  Modul   : ccd.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 :  Condat Conder Decoder - 
+|             Definition of encoding and decoding functions of 
+|             air interface messages
++----------------------------------------------------------------------------- 
+*/ 
+
+#define CCD_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <setjmp.h>
+
+#ifdef _MSDOS
+  #include <dos.h>
+  #include <conio.h>
+#endif
+
+/*
+ * Standard definitions like UCHAR, ERROR etc.
+ */
+
+#include "typedefs.h"
+#include "header.h"
+
+/*
+ * Types and constants used by CCD
+ */
+#include "ccd_globs.h"
+
+/*
+ * Type definitions for CCD data tables
+ */
+#include "ccdtable.h"
+
+/*
+ * Function prototypes of CCD-CCDDATA interface 
+ */
+#include "ccddata.h"
+
+/*
+ * Error codes and prototypes of exported functions by 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 "bitfun.h"
+
+
+/*
+ * Prototypes of ccd internal functions
+ */
+#include "ccd.h"
+
+#if !(defined (CCD_TEST))
+#include "vsi.h"
+#include "os.h"
+#endif
+
+#ifdef SHARED_VSI
+  #define VSI_CALLER 0,
+#else
+  #define VSI_CALLER
+#endif
+
+#ifndef RUN_FLASH
+/* task_null is used in ccd_signup. It must have the same RUN_... setting. */
+static T_CCD_TASK_TABLE task_null;
+#endif /* !RUN_FLASH */
+
+//TISH modified for MSIM
+#if defined (CCD_TEST) || defined (_TOOLS_) || defined (WIN32)
+/* For the DLL and for all simple environment define the task list locally */
+/* 10 entries should be more than enough */
+#define MAX_ENTITIES 10
+T_CCD_TASK_TABLE* ccd_task_list[MAX_ENTITIES];
+#else
+extern T_CCD_TASK_TABLE* ccd_task_list[];
+#endif
+
+#ifndef RUN_FLASH
+const T_CCD_VarTabEntry*   mvar;
+const T_CCD_SpareTabEntry* spare;
+const T_CCD_CalcTabEntry*  calc;
+const T_CCD_CompTabEntry*  mcomp;
+const T_CCD_ElemTabEntry*  melem;
+const T_CCD_CalcIndex*     calcidx;
+const T_CCD_ValTabEntry*   mval;
+#else
+extern const T_CCD_VarTabEntry*   mvar;
+extern const T_CCD_SpareTabEntry* spare;
+extern const T_CCD_CalcTabEntry*  calc;
+extern const T_CCD_CompTabEntry*  mcomp;
+extern const T_CCD_ElemTabEntry*  melem;
+extern const T_CCD_CalcIndex*     calcidx;
+extern const T_CCD_ValTabEntry*   mval;
+#endif
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if one of the following static data shall be used in
+ * both, internal as well as external RAM, they must be made global.
+ */
+static USHORT max_message_id;
+
+/*
+ * CCD internal buffer for decoded message
+ */
+static UBYTE *ccd_decMsgBuffer; 
+/*
+ * Layer-specific cache for the bitlength of the message-identifier;
+ * A value of 0 indicates an empty (undetermined) entry
+ */
+static UBYTE *mi_length; 
+
+/*
+ * CCD internal variables used in each call to code or decode message
+ */
+
+static U8 aim_rrc_rcm;
+static U8 aim_rrlp;
+static U8 aim_sat;
+
+static T_CCD_Globs globs_all;
+#endif /* !RUN_FLASH */
+
+/*
+ * CCD will call its encoding/decoding functions through a jump table. 
+ */
+#include "ccd_codingtypes.h"
+#ifndef RUN_FLASH
+T_FUNC_POINTER  codec[MAX_CODEC_ID+1][2];
+#else
+extern T_FUNC_POINTER  codec[MAX_CODEC_ID+1][2];
+#endif
+
+#ifndef RUN_FLASH
+/* initialized is used in ccd_signup. It must have the same RUN_... setting. */
+/*
+ * Initialising flag
+ */
+BOOL initialized = FALSE;
+#endif /* !RUN_FLASH */
+
+#ifdef SHARED_CCD
+  /*
+   * If CCD is used in a premptive multithreaded system we need
+   * a semaphore to protect the coding and decoding sections.
+   */
+  #ifndef RUN_FLASH
+    T_HANDLE semCCD_Codec, semCCD_Buffer;
+  #else
+    extern T_HANDLE semCCD_Codec, semCCD_Buffer;
+  #endif /* RUN_FLASH */
+#endif /* SHARED_CCD */
+
+static U8* mempat;
+#define LOWSEGMASK 0xFFFFF000
+
+#ifndef RUN_FLASH
+#ifdef DEBUG_CCD
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)                 MODULE  : CCD                 |
+| STATE   : code                       ROUTINE : TRACE_CCD           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Error processing of the CCD.
+
+*/
+
+void TRACE_CCD (T_CCD_Globs *globs, char *format, ...)
+{
+  va_list varpars;
+  char trace_buf[256];
+  int i=0;
+
+  if (!globs->TraceIt)
+    return;
+
+  va_start (varpars, format); /* Initialize variable arguments. */
+#if defined CCD_TEST
+  /*
+   * use vsi_o_trace - prefix the tracestring with [CCD]
+   * so the PCO can display it in a CCD window
+   */
+  strcpy (trace_buf, "~CCD~");
+  i = 5; 
+#endif /* CCD_TEST */
+  vsprintf (trace_buf+i, format, varpars);
+  va_end (varpars);              /* Reset variable arguments.   */
+
+#ifdef CCD_TEST
+  printf ("\n%s\n", trace_buf);
+#else
+  vsi_o_ttrace (globs->me, TC_CCD, trace_buf);
+#endif /* CCD_TEST */
+
+}
+#endif /* !RUN_FLASH */
+
+#endif
+
+/*
+ * Stack operations
+ */
+#define ST_CLEAR(globs) globs->SP=0;globs->StackOvfl=FALSE;
+
+#define ST_OK(globs) (globs->StackOvfl EQ FALSE)
+
+#define ST_CHECK(A, globs) {if (!(globs->StackOvfl) AND globs->SP < MAX_UPN_STACK_SIZE)\
+                    {(A);}\
+                    else\
+                    {globs->StackOvfl = TRUE;}}
+
+#define ST_PUSH(A, globs) ST_CHECK ((globs->Stack[globs->SP++] = (A)), globs)
+
+#define ST_POP(A, globs)  ST_CHECK ((A = globs->Stack[--(globs->SP)]), globs)
+
+#define ST_TOP(A, globs)  ST_CHECK ((A = globs->Stack[globs->SP-1]), globs)
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if the static function calcUPN shall be used in
+ * both, internal as well as external RAM, it must be made global.
+ */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)                 MODULE  : CCD                 |
+| STATE   : code                       ROUTINE : calcUPN             |
++--------------------------------------------------------------------+
+
+  PURPOSE : calculates the UPN-term for an element.
+
+*/
+LOCAL BOOL calcUPN  (ULONG        op,
+                     ULONG        num_ops,
+                     ULONG       *result,
+                     T_CCD_Globs *globs)
+{
+  BOOL   opError;
+  ULONG  op1=0,op2=0;
+
+  opError = FALSE;
+  
+#ifdef DEBUG_CCD
+  TRACE_CCD (globs, "Calculation of UPN-term ");
+#endif
+
+  while (num_ops-- AND !opError AND ST_OK(globs))
+  {
+    switch (calc[op].operation)
+    {
+      case '+':
+        /*
+         * get the upper two elements from the stack, add them
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 + op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '+' causes invalid calculation");
+#endif
+        break;
+      case '-':
+        /*
+         * get the upper two elements from the stack, subtract them
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 - op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '-' causes invalid calculation");
+#endif
+        break;
+      case '*':
+        /*
+         * get the upper two elements from the stack, multiply them
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 * op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '*' causes invalid calculation");
+#endif
+        break;
+      case '/':
+        /*
+         * get the upper two elements from the stack, divide them
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          if (!op2)
+          {
+            ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, 
+                        (USHORT) (globs->bitpos), (USHORT) -1);
+          }
+          else
+          {
+            ST_POP(op1, globs);
+            ST_PUSH ((op1 / op2), globs);
+          }
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '/' causes invalid calculation");
+#endif
+        break;
+      case '&':
+        /*
+         * get the upper two elements from the stack, perform a
+         * binary AND
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 & op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '&' causes invalid calculation");
+#endif
+        break;
+      case '|':
+        /*
+         * get the upper two elements from the stack, perform a
+         * binary OR
+         * and push the result on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 | op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '|' causes invalid calculation");
+#endif
+        break;
+      case 'A':
+        /*
+         * get the upper two elements from the stack, perform a
+         * logical AND
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 AND op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'AND' causes invalid calculation");
+#endif
+        break;
+      case 'O':
+        /*
+         * get the upper two elements from the stack, perform a
+         * logical OR
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 OR op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'OR' causes invalid calculation");
+#endif
+        break;
+      case 'X':
+        /*
+         * get the upper two elements from the stack, perform a
+         * logical XOR
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ( ((op1 AND !op2) OR (!op1 AND op2)) , globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'XOR' causes invalid calculation");
+#endif
+        break;
+      case '=':
+        /*
+         * get the upper two elements from the stack, look if they
+         * are equal
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 EQ op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '=' causes invalid calculation");
+#endif
+        break;
+      case '#':
+        /*
+         * get the upper two elements from the stack, look if they
+         * are different
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 NEQ op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '#' causes invalid calculation");
+#endif
+        break;
+      case '>':
+        /*
+         * get the upper two elements from the stack, look if
+         * op1 > op2
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 > op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '>' causes invalid calculation");
+#endif
+        break;
+      case '<':
+        /*
+         * get the upper two elements from the stack, look if
+         * op1 < op2
+         * and push a TRUE or FALSE on the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op2, globs);
+          ST_POP(op1, globs);
+          ST_PUSH ((op1 < op2), globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '<' causes invalid calculation");
+#endif
+        break;
+      case 'P':
+        /*
+         * push a constant on the stack
+         */
+        ST_PUSH (calc[op].operand, globs);
+#ifdef DEBUG_CCD
+        if (globs->StackOvfl == TRUE)
+          TRACE_CCD (globs, "Constant can't be pused on UPN stack");
+#endif
+        break;
+      case ':':
+        /*
+         * duplicate the upper element on the stack
+         */
+        if (globs->SP >= 1)
+        {
+          ST_TOP (op1, globs);
+          ST_PUSH (op1, globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "No UPN stack element to duplicate");
+#endif
+        break;
+      case 'R':
+        /*
+         * push the content of a C-structure variable on the stack
+         */
+      {
+        /* if no register available some compilers may react with 
+           a warning like this: identifier p not bound to register
+        */
+        UBYTE *p;
+        ULONG           value;
+
+        /*
+         * normaly we have to check if the element is a VAR
+         * and not an array/substructure.
+         * - but this must be done by ccdgen
+         */
+
+        /*
+         * setup the read pointer to the element in the C-structure
+         */
+        p = globs->pstruct + melem[(USHORT) calc[op].operand].structOffs;
+
+        /*
+         * Get the element table entry from the element to read.
+         * if the element of the condition is conditional too
+         * then look for the valid flag of this element.
+         * if the element is not valid,
+         * we dont need to check the contents of it
+         */
+        if (melem[(USHORT) calc[op].operand].optional)
+        {
+          if (*(UBYTE *) p EQ FALSE)
+          {
+            ST_PUSH (0L, globs);
+            break;
+          }
+          else
+            p++;
+        }
+
+        /*
+         * read the contents of the element
+         */
+        switch (mvar[melem[(USHORT) calc[op].operand].elemRef].cType)
+        {
+          case 'B':
+            value = (ULONG) * p;
+            break;
+          case 'S':
+            value = (ULONG) * (USHORT *) p;
+            break;
+          case 'L':
+            value = *(ULONG *) p;
+            break;
+          default:
+            value = 0L;
+        }
+        ST_PUSH (value, globs);
+        break;
+      }
+      case 'S':
+        /*
+         * get the upper element from the stack an
+         * set the position of the bitstream pointer to this
+         * value
+         */
+        if (globs->SP >= 1)
+        {
+          ST_POP(op1, globs);
+#ifdef DEBUG_CCD
+          TRACE_CCD (globs, "SETBITPOS %d (byte %d.%d)",
+                     (USHORT) op1, (USHORT) (op1 / 8), (USHORT) (op1 % 8));
+#endif
+          bf_setBitpos ((USHORT) op1, globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'SETBITPOS' causes invalid calculation");
+#endif
+        break;
+      case 'G':
+        /*
+         * push the position of the bitstream pointer on the
+         * stack
+         */
+        ST_PUSH ((ULONG) globs->bitpos, globs);
+#ifdef DEBUG_CCD
+        TRACE_CCD (globs, "GETBITPOS %d (byte %d.%d)", 
+                   (USHORT) globs->bitpos, globs->bytepos, globs->byteoffs);
+#endif
+        break;
+      case '^':
+        /*
+         * swap the upper two elements of the stack
+         */
+        if (globs->SP >= 2)
+        {
+          ST_POP(op1, globs);
+          ST_POP(op2, globs);
+          ST_PUSH(op1, globs);
+          ST_PUSH(op2, globs);
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter '^' causes invalid calculation");
+#endif
+        break;
+      case 'K':
+        /*
+         * Keep a value in the KEEP register.
+         */
+        if (globs->SP >= 1)
+        {
+          ST_POP(op1, globs);
+          globs->KeepReg[calc[op].operand] = op1;
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'KEEP' causes invalid calculation");
+#endif
+        break;
+      case 'L':
+        /*
+         * Copy the L part of a TLV element from the KEEP register to the UPN stack.
+         */          
+        ST_PUSH(globs->KeepReg[0]*8, globs);
+#ifdef DEBUG_CCD
+        if (globs->StackOvfl == TRUE)
+          TRACE_CCD (globs, "Control parameter 'LTAKE' causes invalid calculation");
+#endif
+        break;
+      case 'T':
+        /*
+         * Take a value from the KEEP register and push it on the UPN stack.
+         */          
+        ST_PUSH(globs->KeepReg[calc[op].operand], globs);
+#ifdef DEBUG_CCD
+        if (globs->StackOvfl == TRUE)
+          TRACE_CCD (globs, "Control parameter 'TAKE' causes invalid calculation");
+#endif
+        break;
+      case 'C':
+        /*
+         * Compare the value on the UPN stack with the one stored in the KEEP register.
+         * Push the higher value in the KEEP register.
+         */
+        if (globs->SP >= 1)
+        {          
+          ST_POP(op1, globs);
+          if ((globs->KeepReg[calc[op].operand]) < op1)
+          {
+            globs->KeepReg[calc[op].operand] = op1;
+          }
+        }
+#ifdef DEBUG_CCD
+        else
+          TRACE_CCD (globs, "Control parameter 'MAX' causes invalid calculation");
+#endif
+        break;
+      case 'Z':
+        /*
+         *  Used to mark presence of an address information part error label
+         */          
+        globs->errLabel = ERR_ADDR_INFO_PART;
+          break;
+      case 'D':
+        /*
+         *  Used to mark presence of a distribution part error label
+         */          
+        globs->errLabel = ERR_DISTRIB_PART;
+          break;
+      case 'N':
+        /*
+         *  Used to mark presence of a non distribution part error label
+         */          
+        globs->errLabel = ERR_NON_DISTRIB_PART;
+          break;
+      case 'M':
+        /*
+         *  Used to mark presence of a message escape error label
+         */          
+        globs->errLabel = ERR_MESSAGE_ESCAPE;
+          break;
+      case 'I':
+        /*
+         *  Used to mark presence of an ignore error label
+         */          
+        globs->errLabel = ERR_IGNORE;
+          break;
+      case 'l':
+        /*
+         * Take a value from the CCD STO register and push it on the UPN stack.
+         */
+        opError = ccd_getStore (globs, calc[op].operand, &op1);
+        if (!opError)
+        {
+          ST_PUSH(op1, globs);
+#ifdef DEBUG_CCD
+          TRACE_CCD (globs, "Push CCD STORE register [%d] value to UPN stack",
+                     calc[op].operand);
+        }
+        else
+        {
+          TRACE_CCD (globs, "Reading from CCD STORE register [%d] impossible",
+                     calc[op].operand);
+#endif
+        }
+        break;
+      case 's':
+        /*
+         * Store a value in the CCD STO register.
+         */
+        if (globs->SP >= 1)
+        {
+          ST_POP(op1, globs);
+          opError =  ccd_writeStore (globs, calc[op].operand, op1);
+#ifdef DEBUG_CCD
+          TRACE_CCD (globs, "Store value in CCD STO register [%d]",
+                     calc[op].operand);
+        }
+        else
+        {
+          TRACE_CCD (globs, "Control parameter 'STORE' causes invalid calculation");
+#endif
+        }
+        break;
+ 
+      default:
+        opError = TRUE;
+        break;
+    }
+    op++;
+  }
+
+  if (!opError AND ST_OK(globs))
+  {
+    if (result NEQ (ULONG *) NULL)
+      ST_POP (*result, globs);
+    return (ST_OK(globs));
+  }
+  else
+  {
+#ifdef DEBUG_CCD
+    if(opError)
+      TRACE_CCD (globs, "Calculation of UPN-term failed ");
+    else
+      TRACE_CCD (globs, "Calculation of UPN-term failed due to stack overflow");
+#endif
+    return FALSE;
+  }
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)                 MODULE  : CCD                 |
+| STATE   : code                       ROUTINE : ccd_conditionOK     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Check if the conditions for an element are true.
+            The elemRef references an element entry from the elem tab.
+            The function returns TRUE if the defined
+            conditions are TRUE.
+
+*/
+
+BOOL ccd_conditionOK (const ULONG e_ref, T_CCD_Globs *globs)
+{
+  ULONG result, cond_calc_ref, num_cond_calcs, cix_ref;
+
+  cix_ref = melem[e_ref].calcIdxRef;
+  num_cond_calcs = calcidx[cix_ref].numCondCalcs;
+  cond_calc_ref  = calcidx[cix_ref].condCalcRef;
+
+
+  if (! calcUPN (cond_calc_ref,
+                 num_cond_calcs,
+                 &result,
+                 globs))
+    return FALSE;
+
+  return (result EQ TRUE);
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)                 MODULE  : CCD                 |
+| STATE   : code                       ROUTINE : ccd_calculateRep    |
++--------------------------------------------------------------------+
+
+  PURPOSE : For a given element (referenced by elemRef) calculate the
+            repeat value.
+
+*/
+
+BOOL ccd_calculateRep  (const ULONG  e_ref,
+                              ULONG *repeat,
+                              ULONG *max_repeat,
+                              T_CCD_Globs *globs)
+{
+  ULONG cix_ref, result;
+  ULONG remaining_repeats=0;
+  ULONG rep_calc_ref, num_rep_calcs;
+
+  BOOL   is_variable;
+
+  cix_ref = melem[e_ref].calcIdxRef;
+  num_rep_calcs = calcidx[cix_ref].numRepCalcs;
+  rep_calc_ref  = calcidx[cix_ref].repCalcRef;
+
+  *max_repeat  = (ULONG) melem[e_ref].maxRepeat;
+
+  if (num_rep_calcs EQ 0)
+  {
+    if (melem[e_ref].repType EQ 'i')
+    {
+      switch (melem[e_ref].elemType)
+      {
+        case 'S':
+          remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
+                           / spare[melem[e_ref].elemRef].bSize);
+          break;
+        case 'F': /* Code transparent pointer to base type */
+        case 'R': /* Pointer to base type */
+        case 'V':
+          remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
+                           / mvar[melem[e_ref].elemRef].bSize);
+          break;
+        case 'D': /* Code transparent pointer to composition */
+        case 'P': /* Pointer to composition */
+        case 'C':
+          /* for repeated compositions the remaining repeats
+             are set to the max repeats because of the unknown
+             size of one composition */
+          remaining_repeats = (ULONG) melem[e_ref].maxRepeat;
+          break;
+        default:
+          ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
+          break;
+      }
+
+      *repeat   = MINIMUM (*max_repeat, remaining_repeats);
+      is_variable = TRUE;
+    }
+    else
+    {
+      if (melem[e_ref].repType EQ 'b')
+      {
+        remaining_repeats = (ULONG)(globs->maxBitpos-globs->bitpos);
+        *repeat   = MINIMUM (*max_repeat, remaining_repeats);
+      }
+      else
+      {
+        *repeat     =  MINIMUM (*max_repeat,
+                                (ULONG) calcidx[cix_ref].repCalcRef);
+        if (*repeat < (ULONG) calcidx[cix_ref].repCalcRef) 
+          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
+                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
+      }
+      is_variable = FALSE;
+    }
+  }
+  else
+  {
+    is_variable = FALSE;
+    if (! calcUPN (rep_calc_ref,
+                   num_rep_calcs,
+                   &result,
+                   globs))
+    {
+      *repeat = *max_repeat = 0;
+
+      ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
+    }
+    else
+    {
+      if ((melem[e_ref].repType != 'b') && (melem[e_ref].repType != 's'))
+      {
+        is_variable = TRUE;
+      }
+      if (melem[e_ref].repType EQ 'i')
+      {
+        switch (melem[e_ref].elemType)
+        {
+          case 'S':
+            remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
+                             / spare[melem[e_ref].elemRef].bSize);
+            break;
+          case 'F': /* Code transparent pointer to base type */
+          case 'R': /* Pointer to base type */
+          case 'V':
+            remaining_repeats = (ULONG)((globs->maxBitpos-globs->bitpos)
+                             / mvar[melem[e_ref].elemRef].bSize);
+            break;
+          default:
+            ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
+            break;
+        }
+        *repeat = MINIMUM (result, remaining_repeats);
+      }
+      else
+      {
+        *repeat = MINIMUM (result, *max_repeat);
+        if (*repeat < result) 
+          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
+                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
+      }
+    }
+  }
+  return (is_variable);
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_performOperations |
++--------------------------------------------------------------------+
+
+  PURPOSE : Perform the operation for an element. This operations
+            are executed before an element is encoded or decoded.
+            The Operations work with the UPN-Stack.
+
+*/
+
+void ccd_performOperations (ULONG        num_of_ops,
+                            ULONG        op_def_ref,
+                            T_CCD_Globs *globs)
+{
+  if (! calcUPN (op_def_ref,
+                 num_of_ops,
+                 NULL,
+                 globs))
+    ccd_setError (globs, ERR_INVALID_CALC, BREAK, (USHORT) -1);
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if the static function ccd_isOptional shall be used in
+ * both, internal as well as external RAM, it must be made global.
+ */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_isOptional        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Checks if a given element is optional. If the element is
+            not optional and is a composition,
+            a recursive call is performed in order to check
+            if the composition contains only optional elements.
+            In this case the whole composition is optional.
+
+            In case of components concatenated with a CSN1 coding 
+            rules the meaning of the word <optional> differs from the 
+            traditional TI tool chain conventions. So far some coding 
+            types (like tagged types, e.g. GSM3_TV) characterise 
+            optional elements inherently. The value of their valid 
+            flag indicates the presence or absence of such an element.
+            Components concatenated with a CSN1 coding type cause 
+            these valid flags in the C header structure too. If you 
+            find a bit in the received message stream indicating 
+            optional values not included in the message (e. g. a 
+            CSN1_S1 element is represented by ??, CCD will set the 
+            valid flag to zero. But the whole element represented by 
+            the flag is present; only the value is absent! Therefor 
+            the valid flag in the C structure is not an indication of 
+            an element’s absence.
+*/
+
+LOCAL BOOL ccd_isOptional (ULONG e_ref, T_CCD_Globs *globs)
+{
+  ULONG  cix_ref;
+  
+  switch (melem[e_ref].codingType)
+  {
+  case CCDTYPE_CSN1_S1: /* Fall through. */
+  case CCDTYPE_CSN1_S0:
+  case CCDTYPE_CSN1_SHL:
+  
+    cix_ref = melem[e_ref].calcIdxRef;
+    /*
+     * If this element is conditional, check the condition.
+     */
+    if (calcidx[cix_ref].numCondCalcs NEQ 0
+    AND ! ccd_conditionOK (e_ref, globs))
+      return TRUE;
+      
+    if (melem[e_ref].repType == 'i' AND 
+        calcidx[melem[e_ref].calcIdxRef].repCalcRef == 0)
+      return TRUE;
+    else 
+      return FALSE;
+//    break;
+//    PATCH FROM M18
+   case CCDTYPE_CSN1_CONCAT:
+      return TRUE;
+
+  default:
+    break;
+  }
+  
+  if (! melem[e_ref].optional)
+  {
+    /*
+     * if the element is an array with an interval [0..x]
+     * it can be handled like an optional element
+     */
+    if ( ! (melem[e_ref].repType EQ 'i'
+        AND calcidx[melem[e_ref].calcIdxRef].repCalcRef EQ 0))
+    {
+      /*
+       * if the element is not optional but it is a composition
+       * we check recursive if the composition consists only of
+       * optional elements
+       */
+      if (melem[e_ref].elemType EQ 'C' OR
+	      melem[e_ref].elemType EQ 'D' OR
+	      melem[e_ref].elemType EQ 'P')
+      {
+        ULONG el, lel, c_ref;
+        
+        c_ref = melem[e_ref].elemRef;
+
+        el = (ULONG) mcomp[c_ref].componentRef;
+        lel = el + mcomp[c_ref].numOfComponents;
+   
+        while (el < lel)
+        {
+          if (! ccd_isOptional (el, globs))
+            return FALSE;
+          el++;
+        }
+      }
+      else
+        return FALSE;
+    }
+  }
+  return TRUE; 
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_decodeComposition |
++--------------------------------------------------------------------+
+
+  PURPOSE : decodes the bitstream to a C-Structure.The decoding
+            rules contains the element definitions for the
+            elements of this message.
+            This function may called recursivly because of a
+            substructured element definition.
+*/
+
+void ccd_decodeComposition (const ULONG c_ref, T_CCD_Globs *globs)
+{
+  /*
+   * index in table melem
+   */
+  ULONG  e_ref;       /* element reference */
+  ULONG  l_ref;       /* reference to the last element of a component */
+  SHORT  codecRet;
+  BOOL   ExtendedGroupActive = FALSE;
+  BOOL   GroupExtended       = FALSE;
+  BOOL   MoreData;
+  BOOL   SetPosExpected = FALSE;
+  int    i;
+  ULONG  act_err_label;
+
+#ifdef DEBUG_CCD
+  #ifndef CCD_SYMBOLS
+  TRACE_CCD (globs, "ccd_decodeComposition()");
+  #else
+  TRACE_CCD (globs, "ccd_decodeComposition(): Composition = %s",
+               mcomp[c_ref].name);
+  #endif
+#endif
+
+  act_err_label = (ULONG) globs->errLabel;
+  globs->ccd_recurs_level++;
+
+  /*
+   * setup the index in the melem table for this composition.
+   * If this function is called for the first time
+   * (ccd_recurs_level == 1) the elem-table entry for the msg_type
+   * was skipped.
+   */
+
+  l_ref = mcomp[c_ref].componentRef
+           + mcomp[c_ref].numOfComponents;
+
+  e_ref  = mcomp[c_ref].componentRef
+           + ((globs->ccd_recurs_level EQ 1) ? 1 : 0);
+
+  /*
+   * decode all elements
+   */
+  while (e_ref < l_ref)
+  {
+#ifdef ERR_TRC_STK_CCD
+    /* save the value for tracing in error case */
+    globs->error_stack[globs->ccd_recurs_level] = (USHORT) e_ref;
+#endif /* ERR_TRC_STK_CCD */
+
+    if (melem[e_ref].extGroup != ' ' && GroupExtended && !ExtendedGroupActive)
+    {
+      /*
+       * the last read extension bit signals an
+       * extension of the group but there are no
+       * more elements defined for this group.
+       * This indicates a protocol extension, that must be
+       * skipped by ccd.
+       */
+
+      do
+      {
+        /*
+         * read the ext-bit to determine the extension
+         * of this group
+         */
+        GroupExtended = (bf_readBit (globs) EQ 0);
+        /*
+         * skip to next octett
+         */
+#ifdef DEBUG_CCD
+        TRACE_CCD (globs, "skipping 7 bits");
+#endif
+        bf_incBitpos (7, globs);
+      } while (GroupExtended);
+    }
+
+    /*
+     * check if the bitstream has ended
+     */
+    if (bf_endOfBitstream(globs) AND !globs->TagPending)
+    {
+        ULONG  cix_ref, num_prolog_steps;
+        
+        cix_ref = melem[e_ref].calcIdxRef;
+        num_prolog_steps = calcidx[cix_ref].numPrologSteps;
+        
+      /* End of the bit stream is not reached if a call to bf_setBitpos()
+       * is expected for the next element of the current substructure. 
+       * An instructive example is an empty "mob_id"
+       */
+      if (num_prolog_steps)
+      {
+        ULONG prolog_step_ref = calcidx[cix_ref].prologStepRef;
+        
+        i = (int) (prolog_step_ref + num_prolog_steps);
+        
+        while (i >= (int) prolog_step_ref)
+        {
+          if (calc[i].operation == 'S')
+          {
+            SetPosExpected = TRUE;
+            break;
+          }
+          i--;
+        }
+      }
+
+     if (SetPosExpected EQ FALSE)
+     {
+       /*
+        * no more bits to decode.
+        * If at least one mandatory element is to decode
+        * generate an error.
+        */
+
+        while (e_ref < l_ref)
+        {
+          if (! ccd_isOptional (e_ref, globs))
+            ccd_setError (globs, ERR_MAND_ELEM_MISS, BREAK, (USHORT) -1);
+
+          e_ref++;
+        }
+        /* after the while loop the recursion level will be decremented. */
+        break;
+      }
+    }
+
+    /*
+     * look for extension group processing
+     */
+    if (melem[e_ref].extGroup NEQ ' ')
+    {
+      /*
+       * extended group symbol found
+       */
+      switch (melem[e_ref].extGroup)
+      {
+        case '+':
+          /*
+           * start of an extended group
+           */
+          ExtendedGroupActive = TRUE;
+          /*
+           * read the extension bit to determine the extension
+           * of this group
+           */
+          GroupExtended = (bf_readBit (globs) EQ 0);
+          /*
+           * use the jump-table for selecting the decode function
+           */
+          codecRet =
+            codec[melem[e_ref].codingType][DECODE_FUN](c_ref,
+                                                         (USHORT)e_ref, globs);
+          if (codecRet NEQ 0x7f)
+          {
+            /*
+             * set the e_ref to the next or the same element
+             */
+            e_ref += codecRet;
+          }
+          break;
+
+        case '-':
+          /*
+           * end of one extension,
+           * decode first and the read the extension bit.
+           */
+          /*
+           * use the jump-table for selecting the decode function
+           */
+          codecRet =
+            codec[melem[e_ref].codingType][DECODE_FUN](c_ref,
+                                                         (USHORT)e_ref, globs);
+          if (codecRet NEQ 0x7f)
+          {
+            /*
+             * set the e_ref to the next or the same element
+             */
+            e_ref += codecRet;
+          }
+
+          /*
+           * look if the previously readed extension bit
+           * alows an extension of this group
+           */
+          if (!GroupExtended)
+          {
+
+            ExtendedGroupActive = FALSE;
+            /*
+             * overread the following elements in the group
+             */
+            /*
+             * search the last element of the extended group
+             */
+            while (e_ref < l_ref
+            AND melem[e_ref].extGroup NEQ '*')
+            {
+#ifdef DEBUG_CCD
+#ifdef CCD_SYMBOLS
+              if (melem[e_ref].elemType EQ 'V')
+                TRACE_CCD (globs, "Skipping ext-group element %s",
+                           ccddata_get_alias((USHORT) e_ref, 1));
+              else if (melem[e_ref].elemType EQ 'C')
+                TRACE_CCD (globs, "Skipping ext-group element %s",
+                           mcomp[melem[e_ref].elemRef].name);
+              else
+                TRACE_CCD (globs, "Skipping ext-group spare");
+#else
+              TRACE_CCD (globs, "Skipping ext-group element %c-%d",
+                         melem[e_ref].elemType,
+                         e_ref);
+
+#endif
+#endif
+              e_ref++;
+            }
+            /*
+             * skip the last element
+             */
+            e_ref++;
+          }
+          else
+          {
+            /*
+             * read the extension bit to determine if the group
+             * extension holds on
+             */
+            GroupExtended = (bf_readBit (globs) EQ 0);
+          }
+          break;
+
+        case '*':
+          if (!ExtendedGroupActive)
+          {
+            /*
+             * this is a single element extended group
+             * often used for later extension of the protocol
+             */
+            /*
+             * read the extension bit to determine if a group
+             * extension is present
+             */
+            GroupExtended = (bf_readBit (globs) EQ 0);
+          }
+          ExtendedGroupActive = FALSE;
+
+          /*
+           * use the jump-table for selecting the decode function
+           */
+          codecRet =
+            codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
+          if (codecRet NEQ 0x7f)
+          {
+            /*
+             * set the e_ref to the next or the same element
+             */
+            e_ref += codecRet;
+          }
+          break;
+
+        case '!': /* Moredata bit */
+        case '#':
+          if ((MoreData = bf_readBit (globs)) EQ 1)
+          {
+            /*
+             * moredata-bit is set to 1
+             * process this element.
+             */
+
+            /*
+             * use the jump-table for selecting the decode function
+             */
+            codecRet =
+              codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
+
+            if (melem[e_ref].extGroup EQ '#')
+            {
+              /*
+               * if more data are signaled with an additional
+               * bit but there are no
+               * more elements defined for this group.
+               * This indicates a protocol extension, that must be
+               * skipped by ccd.
+               */
+
+              do
+              {
+                /*
+                 * read the ext-bit to determine the extension
+                 * of this group
+                 */
+                GroupExtended = (bf_readBit (globs) EQ 1);
+                /*
+                 * skip to next octett
+                 */
+          #ifdef DEBUG_CCD
+                TRACE_CCD (globs, "skipping 7 bits");
+          #endif
+                bf_incBitpos (7, globs);
+              } while (!bf_endOfBitstream(globs) AND GroupExtended);
+
+            }
+
+            if (codecRet NEQ 0x7f)
+            {
+              /*
+               * set the elemRef to the next or the same element(USHORT)
+               */
+              e_ref += codecRet;
+            }
+          }
+
+          if (!MoreData)
+          {
+            /*
+             * more data bit is cleared,
+             * overread the following elements in the group
+             * search the last element of the extended group
+             */
+            while (e_ref < l_ref
+            AND melem[e_ref].extGroup NEQ '#')
+            {
+#ifdef DEBUG_CCD
+#ifdef CCD_SYMBOLS
+              if (melem[e_ref].elemType EQ 'V')
+                TRACE_CCD (globs, "Skipping ext-group element %s",
+                           ccddata_get_alias((USHORT) e_ref, 1));
+              else if (melem[e_ref].elemType EQ 'C')
+                TRACE_CCD (globs, "Skipping ext-group element %s",
+                           mcomp[melem[e_ref].elemRef].name);
+              else
+                TRACE_CCD (globs, "Skipping ext-group spare");
+#else
+              TRACE_CCD (globs, "Skipping ext-group element %c-%d",
+                         melem[e_ref].elemType,
+                         e_ref);
+
+#endif
+#endif
+              e_ref++;
+            }
+
+            /*
+             * skip the last element of the moredata group
+             */
+            e_ref++;
+          }
+          break;
+        default:
+          ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, 
+                        (USHORT) (globs->bitpos), (USHORT) -1);
+          break;
+      }
+    }
+    else
+    {
+      /*
+       * no processing action for an extended group
+       */
+
+      /*
+       * use the jump-table for selecting the decode function
+       */
+      codecRet =
+        codec[melem[e_ref].codingType][DECODE_FUN](c_ref, e_ref, globs);
+      if (codecRet NEQ 0x7f)
+      {
+        /*
+         * set the e_ref to the next or the same element
+         */
+        e_ref += codecRet;
+      }
+    }
+  }
+
+  /* Reset indicator of exhaustion in the IEI table*/
+  for (i = 0; globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].valid== TRUE; i++)
+  {
+    globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].exhausted = FALSE;
+    globs->iei_ctx[globs->ccd_recurs_level].iei_table[i].act_amount = 0;
+
+  }
+
+  globs->iei_ctx[globs->ccd_recurs_level].countSkipped = 0;
+  globs->ccd_recurs_level--;
+  globs->errLabel  = (U8) act_err_label;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if this static function shall be used in
+ * both, internal as well as external RAM, it must be made global.
+ */
+static void SkipExtensionOctets (ULONG *e_ref, ULONG l_ref)
+{
+  /* The extended group is terminated. Skip over its IEs. */
+  while (*e_ref < l_ref && melem[*e_ref].extGroup != '*')
+    (*e_ref)++;
+  if (*e_ref < l_ref)
+    (*e_ref)++;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if this static function shall be used in
+ * both, internal as well as external RAM, it must be made global.
+ */
+LOCAL BOOL CheckBP_RecodeXB (ULONG ExtBitPos1, ULONG ExtBitPos2, 
+                             ULONG ExtBitPos3, T_CCD_Globs *globs)
+{
+  /* Absence due to validity flag, condition or a ccdWarning. */
+  if (ExtBitPos3 == globs->bitpos )
+  {
+    globs->bitpos --;    
+    if (ExtBitPos1 NEQ ExtBitPos2)
+      bf_recodeBit ((USHORT) ExtBitPos1, 1, globs);
+    return FALSE;
+  }
+  return TRUE;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_encodeComposition |
++--------------------------------------------------------------------+
+
+  PURPOSE : codes the content of a C-Structure into a bitstream.
+            This function may be called recursivly if an IE in the
+            structure is itself a structured IE.
+
+            For extended octet groups the following rules apply.
+            
+            Any IE within an extension octet is characterised by its 
+            extGroup which is one of the following:
+            
+            
+            '+'    octet begins with this IE.
+            ' '    octet continues with this IE or a new octet begins.
+            '-'    octet ends with this IE.
+            '*'    octet group ends with this IE.
+            
+            An octet may begin with '+', '-', ' ' or '*'.
+            An octet beginning with '-' or '*' is made of only one IE (7 bits).
+            A group made of one octet has only one IE with '*'.
+            If '+' is present, next IEs ending with '*' or '-' are present too.
+            If the beginning IE  with ' ' is not IE
+
+            Examples of extended group configurations.
+             _ _      _ _ _ 
+            | | |    | | | |
+            |+|*|    |+| |*|  one octet
+            |_|_|    |_|_|_|
+
+             _ _ _ _      _ _ _      _ _ _ _ 
+            | | | | |    | | | |    | | | | |
+            |+|-| |*|    |+|-|*|    |+| |-|*|  two octets
+            |_|_|_|_|    |_|_|_|    |_|_|_|_|
+
+
+             _ _ _ _ _ _ _ _ _ _ 
+            | | | | | | | | | | |
+            |+| | |-| |-| |-| |*|   four octets
+            |_|_|_|_|_|_|_|_|_|_|
+            
+            Also groups after groups are possible.
+             _ _ _ _ _ _ _ _ _
+            | | | | | | | | | |
+            |+| |-| |*|+|*|*|*|
+            |_|_|_|_|_|_|_|_|_|
+            
+            The status of encoding is given as follows:
+
+            ExtendedGroupActive is set to 1 if '+' is present in the encoding.
+            ExtendedGroupActive is changed from 1 to 0 when encoding '*'.
+            ExtendedGroupActive is set to 0 if an octet beginning with ' ' is
+            not present.
+            OpenNewOctet is set to 1 after encoding an IE with '-'.
+            ExtBitPos1 is set to the globs->bitpos when writing extension bit:
+            1) for '+' or 
+            2) for ' ' after '-'
+
+            Extension bit is set to 0 if a further octet is encoded for
+            the group. If an octet is the last one within a group, the 
+            extension bit is set to 1.
+
+            While processing the first IE of an octet (e.g. for '+'),
+            if the IE is absent, CCD will skip over all IEs up to the
+            ending '*'.
+            When processing IEs with ' ' and for ExtendedGroupActive=1 the valid
+            flag is set to 1 in order to compensate probable mistakes in PS.
+
+*/
+
+void ccd_encodeComposition (const ULONG c_ref, T_CCD_Globs *globs)
+{
+  ULONG  e_ref;
+  ULONG  l_ref;
+  BOOL   ExtendedGroupActive = FALSE, OpenNewOctet = FALSE;
+  ULONG  ext_bit_pos1=0, ext_bit_pos2=0, ext_bit_pos3=0, more_data_bit_pos=0;
+  int    ext_bit_pending=0;
+  UBYTE  codecRet;
+
+
+#ifdef DEBUG_CCD
+  #ifndef CCD_SYMBOLS
+    TRACE_CCD (globs, "ccd_encodeComposition()");
+  #else
+    TRACE_CCD (globs, "ccd_encodeComposition(): Composition = %s",
+               mcomp[c_ref].name);
+    #endif
+#endif
+
+  globs->ccd_recurs_level++;
+
+  /*
+   * setup the index in the melem table for this composition.
+   * If this function is called for the first time
+   * (ccd_recurs_level == 1) the elem-table entry for the msg_type
+   * was skipped.
+   */
+
+  l_ref = (USHORT)(mcomp[c_ref].componentRef
+           + mcomp[c_ref].numOfComponents);
+
+  e_ref  = (USHORT)(mcomp[c_ref].componentRef
+           + ((globs->ccd_recurs_level EQ 1) ? 1 : 0));
+
+  /*
+   * code all elements
+   */
+  while (e_ref < l_ref)
+  {
+#ifdef ERR_TRC_STK_CCD
+    /* 
+     * Save the value for tracing in error case.
+     */
+    globs->error_stack[globs->ccd_recurs_level] = (USHORT) e_ref;
+#endif /* ERR_TRC_STK_CCD */
+
+    /*
+     * look for extension group processing
+     */
+    if (melem[e_ref].extGroup NEQ ' ')
+    {
+      /*
+       * extended group symbol found
+       */
+      switch (melem[e_ref].extGroup)
+      {
+        case '+':
+
+          /*
+           * remember the position of the extension bit
+           * because we maybe have to recode it.
+           */
+          ext_bit_pos1 = ext_bit_pos2 = (ULONG) globs->bitpos;
+
+
+          /*
+           * write the extension bit. It may overwritten
+           * later. (ext=0 -> group extended)
+           */
+          bf_writeBit (0, globs);
+          ext_bit_pos3 = (USHORT) globs->bitpos;
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+          /* Use the jump-table for selecting encode function. */
+          codecRet = (UBYTE)
+            codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+
+          /* Absence due to validity flag, conditions or a ccdWarning. */
+          if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
+          {
+            ExtendedGroupActive = FALSE;
+            SkipExtensionOctets (&e_ref, l_ref);
+            continue;
+          }
+          /* Start of an extended group */
+          else
+          {
+            OpenNewOctet = FALSE;
+          }
+
+          ExtendedGroupActive = TRUE;
+          ext_bit_pending = 1;
+
+          if (codecRet NEQ 0x7f)
+          {
+            /* Set the elemRef to the next or the same element. */
+            e_ref += codecRet;
+          }
+          break;
+
+        /* End of one extension octet. */
+        case '-':
+          /* IE must be present if the previous one was not with '-'. */
+          if (OpenNewOctet == FALSE)
+          {
+#ifdef DEBUG_CCD
+            if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
+            {
+              TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
+                         e_ref);
+            }
+#endif
+            /* IE has to be present. Don't trust PS code. */
+            globs->pstruct [melem[e_ref].structOffs] = TRUE;
+          }
+          ext_bit_pos3 = (USHORT) globs->bitpos;
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+          /* Use the jump-table for selecting encode function. */
+          codecRet = (UBYTE)
+            codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+
+          if (OpenNewOctet == TRUE)
+          {
+            /* Absence due to validity flag, conditions or a ccdWarning. */
+            if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
+            {
+              ExtendedGroupActive = FALSE;
+              SkipExtensionOctets (&e_ref, l_ref);
+              continue;
+            }
+          }
+          
+          if (codecRet NEQ 0x7f)
+          {
+          /* Set the elemRef to the next or the same element. */
+            e_ref += codecRet;
+          }
+
+          /* IE with '-' belongs to the first octet. */
+          if (ext_bit_pending EQ 1)
+          {
+            ext_bit_pending++;
+          }
+          /*
+           * At least one octet has been encoded for the current group.
+           * Swap the stored positions of the extension bits.
+           */
+          else
+          {
+            ext_bit_pos1 = ext_bit_pos2;
+          }
+
+          /*
+           * Store the position of the extension bit
+           * because we maybe have to recode it.
+           */
+          ext_bit_pos2 = (ULONG) globs->bitpos;
+          /*
+           * write the extension bit. It may overwritten
+           * later. (ext=0 -> group extended)
+           */
+          bf_writeBit (0, globs);
+          OpenNewOctet = TRUE;
+
+          break;
+
+        case '*':
+          if (!ExtendedGroupActive)
+          {
+            /*
+             * This is a single element extended group, often
+             * used for later extension of the protocol
+             * Write '1' in extension bit since group is not extended yet.
+             */
+            bf_writeBit (1, globs);
+            ext_bit_pos3 = (USHORT) globs->bitpos;
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+            /* Use the jump-table for selecting encode function. */
+            codecRet = (UBYTE)
+              codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+            /* Absence due to the valid flag or a ccdWarning. */
+            if (ext_bit_pos3 == globs->bitpos)
+            {
+              globs->bitpos --;
+            }
+
+            if (codecRet NEQ 0x7f)
+            {
+              /* Set the elemRef to the next or the same element. */
+              e_ref += codecRet;
+            }
+          }
+          else
+          {
+            ExtendedGroupActive = FALSE;
+            /* IE must be present if the previous one was not with '-'. */
+            if (OpenNewOctet == FALSE)
+            {
+#ifdef DEBUG_CCD
+              if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
+              {
+                TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
+                           e_ref);
+              }
+#endif
+              /* IE has to be present. Don't trust PS code. */
+              globs->pstruct [melem[e_ref].structOffs] = TRUE;
+            }
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+             /* Use the jump-table for selecting the encode function. */
+            codecRet = (UBYTE)
+              codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+            ext_bit_pos3 = (USHORT) globs->bitpos;
+
+            if (codecRet NEQ 0x7f)
+            {
+              /* Set the elemRef to the next or the same element. */
+              e_ref += codecRet;
+            }
+
+            if ((ext_bit_pos3-1) NEQ ext_bit_pos2)
+            {
+              /*
+               * if the writepointer (ext_bit_pos3) have incremented
+               * since the first extension bit (NEQ ext_bit_pos1)
+               * at least one element of this group is valid
+               * and written into the bitstream.
+               */
+              /*
+               * the extended group is terminated,
+               * so we have to switch the previously written
+               * extBit from 0 to 1
+               */
+              bf_recodeBit ((USHORT) ext_bit_pos2, 1, globs);
+            }
+            else
+            {
+              /*
+               * break of an extended group, no element are coded
+               * since the last extension bit.
+               */
+              /*
+               * the extended group is terminated,
+               * so we have to switch the previously written
+               * extBit from 0 to 1
+               */
+              if (ext_bit_pos1 NEQ ext_bit_pos2)
+              {
+                bf_recodeBit ((USHORT) ext_bit_pos1, 1, globs);
+              }
+              /*
+               * delete the written ext-bit because the extended
+               * group ended.
+               */
+              bf_setBitpos ((USHORT) ext_bit_pos2, globs);
+            }
+          }
+          break;
+        case '!':
+        case '#':
+          more_data_bit_pos = (ULONG) globs->bitpos;
+          bf_writeBit (1, globs);
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+          /*
+           * use the jump-table for selecting the encode function
+           */
+          codecRet = (UBYTE)
+            codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+          if (codecRet NEQ 0x7f)
+          {
+            if (more_data_bit_pos+1 EQ globs->bitpos)
+            {
+              /*
+               * rewrite the written moredata bit to 0
+               */
+              bf_setBitpos (more_data_bit_pos, globs);
+              bf_writeBit (0, globs);
+              /*
+               * no coding performed -> extension group ended
+               * We skip all elements in this group
+               */
+              while (melem[e_ref].extGroup EQ '!')
+                e_ref++;
+
+              if (melem[e_ref].extGroup EQ '#')
+                e_ref++;
+            }
+            else
+            {
+              if (melem[e_ref].extGroup EQ '#')
+              {
+                /*
+                 * code a zero bit for the last element
+                 */
+                bf_writeBit (0, globs);
+              }
+              e_ref++;
+            }
+          }
+          break;
+        default:
+          ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, 
+                      (USHORT) (globs->bitpos), (USHORT) -1);
+        break;
+      }
+    }
+    else
+    {
+      if (ExtendedGroupActive)
+      {
+        ext_bit_pos3 = (USHORT) globs->bitpos;
+
+        /* IE in the middle part of an ext-octet. */
+        if (OpenNewOctet == FALSE)
+        {
+#ifdef DEBUG_CCD
+          if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
+          {
+            TRACE_CCD (globs, "Wrong value for valid flag!\n...changed to 1 for ccdID=%d",
+                       e_ref);
+          }
+#endif
+          globs->pstruct [melem[e_ref].structOffs] = TRUE;
+        }
+      }
+
+#if defined(_TOOLS_)
+      if (ccd_patch (globs, 0))
+        codecRet = 1;
+      else
+#endif /* _TOOLS_ */
+      /* Use the jump-table for selecting encode function. */
+      codecRet = (UBYTE)
+        codec[melem[e_ref].codingType][ENCODE_FUN](c_ref, e_ref, globs);
+
+      /* The following is only meant for IEs after an IE with '-'. */
+      if (ExtendedGroupActive)
+      {
+        if (OpenNewOctet == TRUE)
+        {
+          /* Absence due to validity flag, conditions or a ccdWarning. */
+          if (!CheckBP_RecodeXB (ext_bit_pos1, ext_bit_pos2, ext_bit_pos3, globs))
+          {
+            ExtendedGroupActive = FALSE;
+            SkipExtensionOctets (&e_ref, l_ref);
+            continue;
+          }
+          /* Start of an extension octet */
+          else
+          {
+            OpenNewOctet = FALSE;
+          }
+        }
+      }
+
+      if (codecRet NEQ 0x7f)
+      {
+        /* Set the elemRef to the next or the same element. */
+        e_ref += codecRet;
+      }
+    }
+  }
+
+  globs->ccd_recurs_level--;
+}
+#endif /* !RUN_FLASH */
+
+/* ---------------------------------------------------------------- */
+/* GLOBAL FUNCTIONS                                                 */
+/* ---------------------------------------------------------------- */
+
+#ifndef RUN_FLASH
+/*
++------------------------------------------------------------------------------
+|  Function     :  ccd_check_pointer
++------------------------------------------------------------------------------
+|  Description  :  This function checks the validity of a pointer
+|
+|  Parameters   :  ptr - the pointer
+|
+|  Return       :  ccdOK if pointer valid, otherwise ccdError
++------------------------------------------------------------------------------
+*/
+int ccd_check_pointer (U8* ptr)
+{
+  if (!ptr || ptr == mempat
+#ifdef WIN32
+      /* For windows: check also if ptr is too small */
+      || !(ptr && LOWSEGMASK)
+#endif
+     )
+  {
+    return ccdError;
+  }
+  return ccdOK;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_begin             |
++--------------------------------------------------------------------+
+
+
+  PARAMETERS:  none
+
+  PURPOSE:     Returns the address of the CCD buffer for decoded
+               messages and locks it until ccd_end() is called
+
+*/
+
+UBYTE* CCDDATA_PREF(ccd_begin) (void)
+{
+#ifdef SHARED_CCD
+  /*
+   * if the CCD is used in a premptive multithreaded system
+   * we must lock this critical section
+   */
+  vsi_s_get (VSI_CALLER semCCD_Buffer);
+#endif
+
+#ifdef DEBUG_CCD
+{
+  #ifndef _TMS470
+  T_CCD_Globs globs;
+  globs.me = 0;
+  globs.TraceIt = 1;
+  TRACE_CCD (&globs, "CCD Begin");
+  #endif
+}
+#endif
+  return ccd_decMsgBuffer;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_end               |
++--------------------------------------------------------------------+
+
+
+  PARAMETERS:  none
+
+  PURPOSE:     Unlocks the CCD buffer for decoded
+               messages
+
+*/
+
+void CCDDATA_PREF(ccd_end) (void)
+{
+#ifdef SHARED_CCD
+  /*
+   * if the CCD is used in a premptive multithreaded system
+   * we must unlock this critical section of accessing the
+   * decoded message buffer
+   */
+  vsi_s_release (VSI_CALLER semCCD_Buffer);
+#endif
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_GetGlobVars       |
++--------------------------------------------------------------------+
+
+
+  PARAMETERS:  
+
+  PURPOSE:     Determines which set of global variables to use
+               and locks the CCD buffer (semaphore) if necessary.
+
+*/
+T_CCD_Globs* ccd_GetGlobVars (T_CCD_ERR_LIST_HEAD** eentry, T_CCD_STORE_LIST** stoentry)
+{
+  T_CCD_TASK_TABLE* tentry;
+#ifndef SHARED_CCD
+  int me = 0;
+#else
+  T_HANDLE me;
+  me = vsi_e_handle (0, NULL);
+  if (me == VSI_ERROR)
+    me = 0;
+#endif /* !SHARED_CCD */
+
+  tentry = ccd_task_list[me];
+  tentry->ccd_globs->me = me;
+  *eentry = tentry->ccd_err_list;
+  *stoentry = tentry->ccd_store;
+#ifdef SHARED_CCD
+  if (tentry->ccd_globs == &globs_all)
+  {
+    /*
+     * if the CCD is used in a premptive multithreaded system
+     * we must lock this critical section
+     */
+    vsi_s_get (VSI_CALLER semCCD_Codec);
+  }
+#endif /* SHARED_CCD */
+  return tentry->ccd_globs;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_FreeGlobVars      |
++--------------------------------------------------------------------+
+
+
+  PARAMETERS:  none
+
+  PURPOSE:     Unlocks the CCD buffer for decoded messages 
+               if the entity is not GRR and if 
+               the CCD is used in a premptive multithreaded system.
+
+*/
+void ccd_FreeGlobVars (T_CCD_Globs* globs)
+{
+#ifdef SHARED_CCD
+  if (globs == &globs_all)
+  {   
+    vsi_s_release (VSI_CALLER semCCD_Codec);
+  }
+#endif /* SHARED_CCD */
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+#ifdef DEBUG_CCD
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_dump_msg          |
++--------------------------------------------------------------------+
+
+  PARAMETERS:  U16 l_buf
+                - Number of bits in the encoded message or IE.
+
+               U16 o_buf
+                - Offset of the bitstream buffer in bits.
+
+               U8 *buf
+                - Bitstream buffer of the encoded message or IE.
+
+               T_CCD_Globs globs
+                - Pointer to global variables
+
+  PURPOSE:     Dump contents of air interface message - for debugging
+
+*/
+void ccd_dump_msg (U16 l_buf, U16 o_buf, U8 *buf, T_CCD_Globs *globs)
+{
+
+  if (!globs->TraceIt)
+    return;
+  else
+  {
+    int  i, j, buflen;
+    char s[64], c[4];
+
+    buflen = (l_buf + o_buf + 7) >> 3;
+    TRACE_CCD (globs, "-------------------------------------------------");
+    TRACE_CCD (globs, " CCD: Decode Message");
+    TRACE_CCD (globs, " Before DECODING: lbuf= %d, obuf= %d", l_buf, o_buf);
+    TRACE_CCD (globs, " Hex dump of message to be decoded:");
+
+    s[0] = '\0';
+    for (i = o_buf>>3; i < buflen; i+=16)
+    {
+      for (j = 0; j < 16; j++)
+      {
+	if ((i+j) < buflen)
+	{
+	  sprintf(c, " %02x", buf[i+j]);
+	  strcat (s, c);
+	}
+      }
+      TRACE_CCD (globs, "%s", s);
+      s[0] = '\0';
+    }
+  }
+}
+#endif /* DEBUG_CCD */
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_common_decode_init|
++--------------------------------------------------------------------+
+
+  PARAMETERS:  
+
+  PURPOSE:     Perform common CCD initialization before message decode.
+
+*/
+void ccd_common_decode_init(U16 l_buf, U16 o_buf, U8 *buf, T_CCD_Globs *globs)
+{
+#if defined (DEBUG_CCD)
+  /* to avoid the vsprintf if the traces won't appear anyhow */
+  ULONG mask;
+  if (vsi_gettracemask (globs->me, globs->me, &mask) != VSI_ERROR)
+  {
+    globs->TraceIt = mask & TC_CCD;
+  }
+#endif
+
+  /*
+   * no call to setjmp() done. So ccd_Error performs no longjmp in
+   * case of an error
+   */
+  globs->jmp_mark_set = FALSE;
+
+  /* setup the bitbuffer */
+  globs->bitbuf = buf;
+  globs->bitpos = 0;
+
+  /* cleanup the read-caches */
+  globs->lastbytepos16 = globs->lastbytepos32 = 0xffff;
+
+  /* setup the bitoffset */
+  globs->bitoffs = o_buf;
+
+  
+  bf_incBitpos (o_buf, globs);
+
+  /*
+   * calclate the max bitpos to read
+   */
+  globs->buflen = l_buf + o_buf;
+  globs->maxBitpos = globs->buflen;
+  globs->msgLen = globs->buflen;
+  globs->errLabel = 0;
+  globs->continue_array = TRUE;
+  globs->SeekTLVExt = TRUE;
+
+  globs->ccd_recurs_level = 0;
+  globs->CCD_Error = ccdOK;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
+ * Attention: if this static function shall be used in
+ * both, internal as well as external RAM, it must be made global.
+ */
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : SeekForGSMExtensions  |
++--------------------------------------------------------------------+
+
+  PURPOSE:     Check if there are elements left in the air message
+               without being decoded. Assume that the next IE has the
+               type T, TV or a TLV. Seek for Comprehension Required
+               extensions.
+               1) Rules to distinguish between the types:
+               handling of unknown IEs (GSM 04.07, section 11.2.4)
+               "Bit 8 of the IEI octet is set to "1" indicates a TV 
+               formatted type 1 standard IE or a T formatted type 2 
+               IEs, and to "0" indicates a TLV formatted type 4 IE. 
+               Hence, a 1 valued bit 8 indicates that the whole IE is 
+               one octet long, and a 0 valued bit 8 indicates that the
+               following octet is a length octet.
+               1) Rules to read the length:
+               For TLV4 encode L in one byte.
+               For TLV5 and ASN.1 encode in one byte or more. Use
+               0x81, 0x82 etc in the first byte to say L is encoded
+               in one, two etc bytes.
+               For ASN.1 BER type use 0x80 in the first byte and
+               two otets of 0 bits after the encoded IE.
+               For all the three types it is possible to encode L
+               in only one byte.
+               TLV6 is not supported. TLV6 is not a GSM standard 
+               type. It has been defined in g23net software.
+*/
+static void SeekForGSMExtensions (U8 entity, T_CCD_Globs *globs)
+{
+  U8 *MsgBuf = (U8*)globs->bitbuf;
+  U16 BP = globs->bytepos;
+  U16 OctNr = (globs->buflen+7) >> 3;
+  U16 errPos = 0;
+  U8 errTag = 0xFF;
+  U8 errCode;
+
+#ifdef DEBUG_CCD
+  TRACE_CCD( globs, "SeekForGSMExtensions...");
+#endif
+  while (BP < OctNr)
+  {
+    U8 T = MsgBuf[BP];
+    BOOL tlv5 = FALSE;
+
+    /* Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set.
+     * Expecting other types than CCDTYPE_GSM5_TLV we get an unknown tag with
+     * comprehension required bits (5, 6, 7 and 8 of IEI according to GSM0407)
+     * are set to zero.
+     */
+    tlv5 = (aim_sat == entity);
+    if ( (tlv5 && ((T & 0x80) == 0x80))
+        ||
+         (!tlv5 && ((T & 0xf0) == 0)) )
+    {
+      errTag = T;
+      errPos = BP*8;
+      errCode = ERR_COMPREH_REQUIRED;
+      /* Report error. Do not analyse the rest. */
+      break;
+    }
+    else
+    {
+      errTag = T;
+      errPos = BP*8;
+      errCode = ERR_IE_NOT_EXPECTED;
+    }
+
+    /* The type is TLV or ASN.1. */
+    if ((T & 0x80) NEQ 0x80)
+    { 
+      /* BP points to the first L byte */
+      U16 L = MsgBuf[++BP]; 
+      switch (L)
+      {
+        /* End Of Content (ASN.1 BER) */
+        case 0x80:
+          do
+          {
+            BP++;
+          } while ((*(U16*)&MsgBuf[BP]) != 0 && BP < OctNr);
+          BP++;
+          L = 0;
+          break;
+
+        /* Length encoding in two bytes */
+        case 0x81:
+          L = MsgBuf[++BP];
+          break;
+
+        /* Length encoding in three bytes */
+        case 0x82:
+          L = (MsgBuf[++BP]) << 8;
+          L |= MsgBuf[++BP];
+          break;
+
+        /* Length encoding in one byte. */
+        default:
+          break;
+      }
+
+      /* Skip over the bytes. */
+      while (L > 0 && BP < OctNr)
+      {
+        --L;
+        ++BP;
+      } 
+
+    } /* if TLV */
+    /* else: The type is T or TV. Skip one byte (see next step). */
+
+    /* 
+     * BP points to the last byte of the skipped IE, 
+     * move to the next IE.
+     */
+    BP++;
+  }/* while bytes left unread */
+
+  /* Report the summary of the found erros. */
+  if (errTag != 0xFF)
+  {
+    ccd_setError (globs, errCode,
+      (U8)((errCode == ERR_COMPREH_REQUIRED) ? BREAK : CONTINUE),
+                  errTag,
+                  errPos,
+                  (USHORT) -1);
+  }
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_decodeMsg         |
++--------------------------------------------------------------------+
+
+
+  PARAMETERS:  UBYTE      entity
+                - specifies the calling entity of CCD. The Constants
+                  for each valid entity is defined in MCONST.CDG
+
+               UBYTE      direction
+                - specifies wether the message goes UPLINK or DOWNLINK.
+                  This is nessesary because there are same PDU-Type
+                  codes for different messages.
+
+	              T_MSGBUF * mBuf
+                - specifies the bitstream buffer of the message. The
+                  struct contains the l_buf and the o_buf elements.
+                  These elements specifies the length and offset in bits
+                  of the bitstream in the T_MSGBUF component buf.
+
+               UBYTE    * mStruct
+                - reference to the C-Structure of the decoded message.
+                  The type may differ so the Pointer is always typed as
+                  UBYTE* and must be casted after decoding. If this parameter
+                  is NULL CCD uses his internal buffer wich must be
+                  protected via ccd_begin() in a multithread environment.
+
+               UBYTE      mId
+                - specifies the PDU-Type of the bitstream. If this
+                  parameter is not equal 0xff the CCD does not decode
+                  the pdu-type from the bitstream to decide wich decoding
+                  rules to select. Normaly this param is set to 0xff.
+
+  PURPOSE:     decodes a bitstream, containing a valid TETRA-Message
+               of the Air-Interface to a corresponding C-Structure.
+
+*/
+
+BYTE CCDDATA_PREF(ccd_decodeMsg) (UBYTE         entity,
+                                  UBYTE         direction,
+                                  T_MSGBUF     *mBuf,
+                                  UBYTE        *mStruct,
+                                  UBYTE         mId)
+{
+  UBYTE theMsgId;
+  USHORT mcompRef;
+  int    jmp_ret;
+  T_CCD_Globs *globs;
+  T_CCD_ERR_LIST_HEAD* eentry;
+  T_CCD_STORE_LIST* stoentry;
+
+    globs = ccd_GetGlobVars (&eentry, &stoentry);
+
+    /*
+     * setup the structure-buffer
+     *
+     * if the parameter of the decoded message buffer address is NULL
+     * we use the internal one
+     */
+    globs->pstruct = (mStruct EQ NULL) ? ccd_decMsgBuffer : mStruct;
+    globs->pstructOffs = 0;
+
+    ccd_common_decode_init(mBuf->l_buf, mBuf->o_buf, mBuf->buf, globs);
+    ccd_err_reset (eentry);
+    globs->errLabel = 0;
+    globs->continue_array = TRUE;
+
+  #ifdef DEBUG_CCD
+    ccd_dump_msg(mBuf->l_buf, mBuf->o_buf, mBuf->buf, globs);
+  #endif
+
+    if (mId NEQ 0xff AND mId NEQ 0xfe)
+      globs->pstruct[0] = theMsgId = mId;
+    else
+    {
+      /* Read the message identifier */
+      globs->pstruct[0] = bf_decodeByteNumber ((ULONG) mi_length[entity], globs);
+      theMsgId = globs->pstruct[0];
+    }
+
+    /* Get entry in mmtx table for this message */
+    mcompRef = ccddata_get_mmtx(entity,theMsgId,direction);
+
+    /* Check the message identifier */
+    if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
+    {
+  #ifdef ERR_TRC_STK_CCD
+      globs->ccd_recurs_level = 255;
+  #endif /* ERR_TRC_STK_CCD */
+      ccd_setError (globs, ERR_INVALID_MID, BREAK,
+		    (USHORT) theMsgId, (USHORT) -1);
+      ccd_FreeGlobVars (globs);
+      ccd_err_free (eentry);
+      return (BYTE)globs->CCD_Error;
+    }
+  #ifdef ERR_TRC_STK_CCD
+    /* save the value for tracing in error case */
+    globs->error_stack[0] = mcompRef;
+  #endif /* ERR_TRC_STK_CCD */
+
+  #ifdef DEBUG_CCD
+  #ifdef CCD_SYMBOLS
+    TRACE_CCD (globs, "CCD decode: Message = %s",
+    mcomp[mcompRef].name);
+  #else
+    TRACE_CCD (globs, "CCD decode: MessageId = %x", theMsgId);
+  #endif
+  #endif
+
+  /* 
+   * Clean up the entite C-structure before decoding.
+   * Do not overwrite the MsgId (1. Byte)
+   */
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "CCD Cleaning struct %ld bytes",
+	       mcomp[mcompRef].cSize-1);
+  #endif
+  memset ((UBYTE *) &globs->pstruct[1], 0,
+    (size_t)(mcomp[mcompRef].cSize - 1));
+
+    /*
+     * clear the UPN stack
+     */
+    ST_CLEAR(globs);
+    memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
+
+    /*
+     * inform the GSM-CODEC about the begin of a new message
+     */
+    cdc_GSM_start (globs);
+
+    jmp_ret = setjmp (globs->jmp_mark);
+
+    if (jmp_ret EQ 0)
+    {
+      globs->jmp_mark_set = TRUE;
+      ccd_decodeComposition ((ULONG) mcompRef, globs);
+
+      /*
+       * The coding rules and the data tables must be able to lead CCD to
+       * understand the bit buffer, element by element. If for some reason
+       * the bit pointer points to a place after the message limit, the
+       * encoding action is not trustworthy. Nevertheless CCD reports a
+       * WARNING and not error.
+       * In development phase it is helpful to detect such cases.
+       * Otherwise the caller can supposedly still use the message.
+       */
+      if (globs->bitpos > globs->buflen)
+      {
+        ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, mcompRef, NULL);
+      }
+      /*
+       * Seek for GSM extensions with types T, TV and TLV.
+       * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
+       * Check only at octet border.
+       */
+      else if ((globs->SeekTLVExt) && !globs->byteoffs)
+      {
+        SeekForGSMExtensions (entity, globs);
+      }
+  }
+
+
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
+    TRACE_CCD (globs, "-------------------------------------------------");
+  #endif /* DEBUG_CCD */
+
+    ccd_FreeGlobVars (globs);
+    ccd_err_free (eentry);
+
+    return (BYTE) globs->CCD_Error;
+  }  /* end ccd_decodeMsg () */
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+  /*
+  +--------------------------------------------------------------------+
+  | PROJECT : CCD (6144)               MODULE  : CCD                   |
+  | STATE   : code                     ROUTINE : ccd_decodeMsgPtr      |
+  +--------------------------------------------------------------------+
+
+
+    PARAMETERS:  U8      entity
+		  - specifies the calling entity of CCD. The Constants
+		    for each valid entity is defined in MCONST.CDG
+
+		 U8      direction
+		  - specifies wether the message goes UPLINK or DOWNLINK.
+		    This is nessesary because there are same PDU-Type
+		    codes for different messages.
+
+		       U16 l_buf
+		  - Lenght of the bitstrem to be decoded.
+
+							   U16 o_buf
+		  - specifies the bitstream buffer of the message. The
+		    struct contains the l_buf and the o_buf elements.
+		    These elements specifies the length and offset in bits
+		    of the bitstream in the T_MSGBUF component buf.
+
+							   U8 *buf
+		  - specifies the bitstream buffer of the message. 
+
+		 U8 ** mStructPtr
+		  -	points to the pointer on the C-structure of the 
+		    decoded message. The buffer containing this message 
+		    structure will be allocated by CCD. After decoding 
+		    the first element in the message C-structure contains 
+		    the message (PDU) type as a UBYTE.
+
+		 U8  mId
+		  - specifies the PDU-Type of the bitstream. If this
+		    parameter is not equal 0xff the CCD does not decode
+		    the pdu-type from the bitstream to decide wich decoding
+		    rules to select. Normaly this param is set to 0xff.
+
+    PURPOSE:     Like ccd_decodeMsg, this function decodes a bitstream
+		 containing a valid TETRA-Message from the Air-Interface
+		 to a corresponding C-Structure, only this function
+		 allows the use of pointer types in the C-structure.
+
+  */
+  #if defined DYNAMIC_ARRAYS || defined _TOOLS_
+S8 CCDDATA_PREF(ccd_decodeMsgPtr) (U8   entity,
+		       U8   direction,
+		       U16  l_buf,
+		       U16  o_buf,
+		       U8*  buf,
+		       U8** mStructPtr,
+		       U8   mId)
+{
+  /*
+   * Make a dummy for the DLLs, even if DYNAMIC_ARRAYS is not defined to
+   * keep the ccd.def unique
+   */
+  #ifndef DYNAMIC_ARRAYS
+    return -1;
+}
+  #else /* DYNAMIC_ARRAYS */
+    UBYTE  theMsgId;
+    int    jmp_ret;
+    U32    msgsize;
+    USHORT mcompRef;
+    T_CCD_Globs *globs;
+    T_CCD_ERR_LIST_HEAD* eentry;
+    T_CCD_STORE_LIST* stoentry;
+
+    globs = ccd_GetGlobVars (&eentry, &stoentry);
+    ccd_common_decode_init(l_buf, o_buf, buf, globs);
+    ccd_err_reset (eentry);
+    globs->errLabel = 0;
+    globs->continue_array = TRUE;
+    globs->alloc_head = *mStructPtr = NULL;
+
+  #ifdef DEBUG_CCD
+    TRACE_CCD( globs, "======================================================");
+    TRACE_CCD( globs, "ccd_decodeMsgPtr: Decoding message with pointer types.");
+    ccd_dump_msg(l_buf, o_buf, buf, globs);
+  #endif
+
+	    /* Read the message identifier. */
+    if (mId NEQ 0xff AND mId NEQ 0xfe)
+      theMsgId = mId;
+    else
+      theMsgId = bf_decodeByteNumber ((ULONG) mi_length[entity], globs);
+
+    /* Get the entry in mmtx table for this message */
+    mcompRef = ccddata_get_mmtx (entity,theMsgId,direction);
+     
+    /* Check the validity of the message identifier */
+    if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
+    {
+  #ifdef ERR_TRC_STK_CCD
+      globs->ccd_recurs_level = 255;
+  #endif /* ERR_TRC_STK_CCD */
+      ccd_setError (globs, ERR_INVALID_MID, BREAK, (USHORT) theMsgId, (USHORT) -1);
+      ccd_FreeGlobVars (globs);
+      ccd_err_free (eentry);
+      return (BYTE) globs->CCD_Error;
+    }
+
+  #ifdef ERR_TRC_STK_CCD
+    /* save the value for tracing in error case */
+    globs->error_stack[0] = mcompRef;
+  #endif /* ERR_TRC_STK_CCD */
+
+  #ifdef DEBUG_CCD
+  #ifdef CCD_SYMBOLS
+    TRACE_CCD (globs, "CCD decode: Message = %s",
+    mcomp[mcompRef].name);
+  #else
+    TRACE_CCD (globs, "CCD decode: MessageId = %x", theMsgId);
+  #endif
+  #endif
+
+    /*
+     * Setup the structure-buffer.
+     * Make a first simple estimation of much memory to allocate.
+     * It is twice as much as the air interface message, rounded up 
+     * to the nearest kilobyte boundary.
+     */
+    msgsize = mcomp[mcompRef].cSize;
+    
+  #ifdef DEBUG_CCD
+    TRACE_CCD( globs, "Allocating %ld bytes for msg.", msgsize);
+  #endif
+    
+    globs->alloc_head = (U8 *) DRP_ALLOC(msgsize, DP_NO_FRAME_GUESS);
+
+    if (globs->alloc_head == NULL)
+    {
+      ccd_setError (globs, ERR_NO_MEM, BREAK, (USHORT) theMsgId, (USHORT) -1);
+      ccd_FreeGlobVars (globs);
+      ccd_err_free (eentry);
+      return (BYTE) globs->CCD_Error;
+    }
+    *mStructPtr = globs->alloc_head;
+    globs->pstruct = globs->alloc_head;
+    globs->pstructOffs = 0;
+
+    /*Write the MSG ID in the buffer*/
+    globs->pstruct[0] = theMsgId;
+
+    /* 
+     * Clean up the entite C-structure before decoding.
+     * Do not overwrite the MsgId (1. Byte)
+     */
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "CCD Cleaning struct %ld bytes", mcomp[mcompRef].cSize);
+  #endif
+  memset ((U8 *)globs->pstruct, 0, (size_t)(msgsize));
+
+    /* 
+     * Write the message identifier into the C-structure.
+     */
+    globs->pstruct[0] = theMsgId;
+
+    /*
+     * clear the UPN stack
+     */
+    ST_CLEAR(globs);
+    memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
+
+    /*
+     * inform the GSM-CODEC about the begin of a new message
+     */
+    cdc_GSM_start (globs);
+
+    jmp_ret = setjmp (globs->jmp_mark);
+
+    if (jmp_ret EQ 0)
+    {
+      globs->jmp_mark_set = TRUE;
+      ccd_decodeComposition ((ULONG) mcompRef, globs);
+      if (globs->byteoffs NEQ 0)
+      {
+       bf_incBitpos (8-globs->byteoffs, globs);
+  
+        /* There are more bits to be decoded than ccddata expects.
+         * The additional bits may belong to unknown non-critical extensions.
+         */
+        if (globs->bitpos > globs->buflen)
+        {
+         ccd_recordFault (globs, ERR_UNEXPECT_PAD, CONTINUE, mcompRef, NULL);
+        }
+        /*
+         * Seek for GSM extensions with types T, TV and TLV.
+         * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
+         * Check only at octet border.
+         */
+        else if ((entity != aim_rrc_rcm) 
+                && (entity != aim_rrlp)
+                && (globs->SeekTLVExt)
+                && !globs->byteoffs)
+        {
+          SeekForGSMExtensions (entity, globs);
+        }
+      }
+      else
+      {
+        if (globs->bitpos > globs->buflen)
+        {
+         ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, mcompRef, NULL);
+        }
+        /*
+         * Seek for GSM extensions with types T, TV and TLV.
+         * (GRR, RCM/RRC and RRLP assume other extension mechanisms.)
+         * Check only at octet border.
+         */
+        else if ((entity != aim_rrc_rcm) 
+                && (entity != aim_rrlp)
+                && (globs->SeekTLVExt)
+                && !globs->byteoffs)
+        {
+          SeekForGSMExtensions (entity, globs);
+        }
+      }
+    }
+
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
+    TRACE_CCD (globs, "-----------------------------------------------------");
+  #endif /* DEBUG_CCD */
+
+    ccd_FreeGlobVars (globs);
+    ccd_err_free (eentry);
+
+    return (BYTE) globs->CCD_Error;
+}  /* end ccd_decodeMsgPtr () */
+  #endif /* !DYNAMIC_ARRAYS */
+  #endif /* DYNAMIC_ARRAYS || _TOOLS_ */
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+  /*
+  +--------------------------------------------------------------------+
+  | PROJECT : CCD (6144)               MODULE  : CCD                   |
+  | STATE   : code                     ROUTINE : ccd_codeMsgPtr        |
+  +--------------------------------------------------------------------+
+
+   PARAMETERS:   UBYTE      entity
+		  - specifies the calling entity of CCD. The Constants
+		    for each valid entity is defined in MCONST.CDG
+
+		 UBYTE      direction
+		  - specifies wether the message goes UPLINK or DOWNLINK.
+		    This is nessesary because there are same PDU-Type
+		    codes for different messages.
+
+		 T_MSGBUF * mBuf
+		  - specifies the bitstream buffer of the message. The
+		    struct contains the l_buf and the o_buf elements.
+		    These elements specifies the length and offset in bits
+		    of the bitstream in the T_MSGBUF component buf.
+		    The o_buf component must be specified by the caller,
+		    the l_buf component is calculated by CCD.
+
+		 UBYTE    * mStruct
+		  - reference to the C-Structure containing the
+		    C-Representation of the decoded message.
+		    The type should be casted to UBYTE*. If this parameter
+		    is NULL CCD uses his internal buffer wich must be
+		    protected via ccd_begin() in a multithread environment.
+
+		 UBYTE      mId
+		  - specifies the PDU-Type of the bitstream. If this
+		    parameter is not equal 0xff the CCD does not read
+		    the pdu-type from the structure component pt
+		    to decide wich decoding rules to select.
+		    Normaly this param is set to 0xff.
+
+   PURPOSE:      encodes a C-Structure containing the C-Representation of
+		 a valid Air-interface message to a bitstream.
+
+  */
+
+S8 CCDDATA_PREF(ccd_codeMsgPtr)(U8   entity,
+		    U8   direction,
+		    U16* l_buf,
+		    U16  o_buf,
+		    U8   *buf,
+		    U8*  mStruct,
+		    U8   mId)
+{
+    UBYTE  theMsgId;
+    int    jmp_ret;
+    USHORT maxBytes, mcompRef;
+    T_CCD_Globs *globs;
+    T_CCD_ERR_LIST_HEAD* eentry;
+    T_CCD_STORE_LIST* stoentry;
+    
+    globs = ccd_GetGlobVars (&eentry, &stoentry);
+    ccd_err_reset (eentry);
+
+  #if defined (DEBUG_CCD)
+    {
+      /* to avoid the vsprintf if the traces won't appear anyhow */
+      ULONG mask;
+      if (vsi_gettracemask (globs->me, globs->me, &mask) != VSI_ERROR)
+      {
+	globs->TraceIt = mask & TC_CCD;
+      }
+    }
+  #endif
+
+    /*
+     * Set a sign that no call to setjmp() is done. So ccd_setError 
+     * performs no longjmp in case of an error.
+     */
+    globs->jmp_mark_set = FALSE;
+
+    /* Setup the bitbuffer. */
+    globs->bitbuf = buf;
+    globs->bitpos = 0;
+
+    /* and the structure-buffer */
+    globs->pstruct = (mStruct EQ NULL) ? ccd_decMsgBuffer : mStruct;
+    globs->pstructOffs = 0;
+
+    /* Cleanup the read-caches. */
+    globs->lastbytepos16 = globs->lastbytepos32 = 0xffff;
+
+    /* Setup the bitoffset. */
+    globs->bitoffs = o_buf;
+
+    
+    bf_incBitpos (o_buf, globs);
+
+    globs->bitbuf[globs->bytepos] = 0;
+
+    globs->ccd_recurs_level = 0;
+
+    globs->CCD_Error = ccdOK;
+
+    globs->continue_array = TRUE;
+
+    if (mId NEQ 0xff AND mId NEQ 0xfe)
+      theMsgId = mId;
+    else
+    {
+      theMsgId = globs->pstruct[0];
+    }
+
+    mcompRef = ccddata_get_mmtx(entity,theMsgId,direction);
+    /* Check the validity of the given message identifier. */
+    if (theMsgId > max_message_id OR mcompRef EQ NO_REF)
+    {
+  #ifdef ERR_TRC_STK_CCD
+      globs->ccd_recurs_level = 255;
+  #endif /* ERR_TRC_STK_CCD */
+      ccd_setError (globs, ERR_INVALID_MID, BREAK, (USHORT) theMsgId, (USHORT) -1);
+      ccd_FreeGlobVars (globs);
+      ccd_err_free (eentry);
+      return (BYTE) globs->CCD_Error;
+    }
+
+  #ifdef ERR_TRC_STK_CCD
+    /* save the value for tracing in error case */
+    globs->error_stack[0] = mcompRef;
+  #endif /* ERR_TRC_STK_CCD */
+
+  maxBytes = (*l_buf + 7)>>3;
+  globs->msgLen = *l_buf;
+
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "-------------------------------------------------");
+    TRACE_CCD (globs, "CCD: Code Message");
+    TRACE_CCD (globs, "Cleaning %d bits (%d bytes) of the bitstream",
+      mcomp[mcompRef].bSize, maxBytes);
+  #endif
+
+    /* 
+     * Clean up the bit buffer for the encoded message before encoding.
+     */
+    memset ((U8 *) &buf[(o_buf>>3)], 0, (size_t) maxBytes);
+    /* Store the length of ereased buffer to support error handling. */
+    globs->buflen = *l_buf;
+
+    if (mId EQ 0xff)
+    {
+      /* Write the message identifier. */
+      bf_writeBits ((U32)mi_length[entity], globs);
+    }
+
+  #ifdef DEBUG_CCD
+  #ifdef CCD_SYMBOLS
+    TRACE_CCD (globs, "CCD encode: Message = %s", mcomp[mcompRef].name);
+  #else
+    TRACE_CCD (globs, "CCD encode: MessageId = %x", theMsgId);
+  #endif
+  #endif
+
+    /*
+     * Clear the UPN stack.
+     */
+    ST_CLEAR(globs);
+    memset ((ULONG *) &(globs->KeepReg[0]), 0, MAX_KEEP_REG_SIZE);
+
+    /*
+     * Inform the GSM-CODEC about the begin of a new message.
+     */
+    cdc_GSM_start (globs);
+
+    jmp_ret = setjmp (globs->jmp_mark);
+
+    if (jmp_ret EQ 0)
+    {
+      /*
+       * no call to setjmp() done. So ccd_Error performs no longjmp in
+       * case of an error
+       */
+      globs->jmp_mark_set = TRUE;
+      ccd_encodeComposition ((ULONG) mcompRef, globs);
+      if (globs->bitpos > o_buf + *l_buf)
+      {
+	ccd_setError (globs, ERR_BUFFER_OF, CONTINUE, (USHORT) -1);
+      }
+      bf_writePadBits (globs);
+    }
+
+    *l_buf = (USHORT) globs->bitpos - (USHORT) o_buf;
+
+  #ifdef DEBUG_CCD
+  {
+    int i, j, buflen;
+    char s[64], c[4];  
+
+    buflen = (*l_buf + o_buf + 7) >> 3;
+
+    TRACE_CCD (globs, "-------------------------------------------------");
+    TRACE_CCD (globs, " After ENCODING: lbuf= %d, obuf= %d", *l_buf, o_buf);
+    TRACE_CCD (globs, " Hex dump of encoded message:"); 
+
+    s[0] = '\0';
+    for (i = o_buf >> 3; i < buflen; i+=16)
+    {
+      for (j = 0; j < 16; j++)
+      {
+	if ((i+j) < buflen)
+	{
+	  sprintf(c, " %02x", buf[i+j]);
+	  strcat (s, c);
+	}
+      }
+      TRACE_CCD (globs, "%s", s);
+      s[0] = '\0';
+    }
+  }
+  #endif
+
+  #ifdef DEBUG_CCD
+    TRACE_CCD (globs, "CCD-ERROR = %d", globs->CCD_Error);
+    TRACE_CCD (globs, "-------------------------------------------------");
+  #endif
+
+    ccd_FreeGlobVars (globs);
+    ccd_err_free (eentry);
+
+    return (BYTE)globs->CCD_Error;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+  /*
+  +--------------------------------------------------------------------+
+  | PROJECT : CCD (6144)               MODULE  : CCD                   |
+  | STATE   : code                     ROUTINE : ccd_codeMsg           |
+  +--------------------------------------------------------------------+
+
+   PARAMETERS:   UBYTE      entity
+		  - specifies the calling entity of CCD. The Constants
+		    for each valid entity is defined in MCONST.CDG
+
+		 UBYTE      direction
+		  - specifies wether the message goes UPLINK or DOWNLINK.
+		    This is nessesary because there are same PDU-Type
+		    codes for different messages.
+
+		 T_MSGBUF * mBuf
+		  - specifies the bitstream buffer of the message. The
+		    struct contains the l_buf and the o_buf elements.
+		    These elements specifies the length and offset in bits
+		    of the bitstream in the T_MSGBUF component buf.
+		    The o_buf component must be specified by the caller,
+		    the l_buf component is calculated by CCD.
+
+		 UBYTE    * mStruct
+		  - reference to the C-Structure containing the
+		    C-Representation of the decoded message.
+		    The type should be casted to UBYTE*. If this parameter
+		    is NULL CCD uses his internal buffer wich must be
+		    protected via ccd_begin() in a multithread environment.
+
+		 UBYTE      mId
+		  - specifies the PDU-Type of the bitstream. If this
+		    parameter is not equal 0xff the CCD does not read
+		    the pdu-type from the structure component pt
+		    to decide wich decoding rules to select.
+		    Normaly this param is set to 0xff.
+
+   PURPOSE:      encodes a C-Structure containing the C-Representation of
+		 a valid Air-interface message to a bitstream.
+
+  */
+
+BYTE CCDDATA_PREF(ccd_codeMsg) (UBYTE  entity,
+		    UBYTE         direction,
+		    T_MSGBUF     *mBuf,
+		    UBYTE        *mStruct,
+		    UBYTE         mId)
+{
+  return CCDDATA_PREF(ccd_codeMsgPtr) (entity, direction, &mBuf->l_buf,
+      mBuf->o_buf, mBuf->buf, mStruct, mId);
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++------------------------------------------------------------------------------
+|  Function    : ccd_init_ccddata
++------------------------------------------------------------------------------
+|  Description : Initialize local tables.
+|
+|  Parameters  : -
+|
+|  Return      : ccdOK, ccdWarning, or ccdError depending on the success.
++------------------------------------------------------------------------------
+*/
+ULONG CCDDATA_PREF(ccd_init_ccddata) (void)
+{
+  const T_CCD_CompTabEntry *msg;
+  USHORT                    mcompRef;  
+  UBYTE                     ret, entity, num_of_entities;
+  USHORT                    messageId;
+#ifdef DEBUG_CCD
+  T_CCD_Globs *globs = &globs_all;
+#endif
+
+  aim_rrc_rcm = (U8)ccddata_get_ccdent ("UMTS_AS_ASN1_MSG");
+  aim_rrlp    = (U8)ccddata_get_ccdent ("RRLP_ASN1_MSG");
+  aim_sat     = (U8)ccddata_get_ccdent ("SAT");
+
+  mcomp = ccddata_get_mcomp (0);
+  mvar = ccddata_get_mvar (0);
+  mval = ccddata_get_mval (0);
+  melem = ccddata_get_melem (0);
+  spare = ccddata_get_spare (0);
+  calc = ccddata_get_calc (0);
+  calcidx = ccddata_get_calcidx (0);
+
+  mi_length = ccddata_get_mi_length();
+  ccd_decMsgBuffer = ALIGN_BUF(ccddata_get_decmsgbuffer());
+  max_message_id = (USHORT) ccddata_get_max_message_id();
+
+#ifdef CCD_SYMBOLS
+  if (!ccddata_mccd_symbols())
+  {
+#ifdef CCD_TEST
+    printf ("CCD_SYMBOLS is not set in ccddata\n");
+#else     /* CCD_TEST */
+    vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+                  "CCD_SYMBOLS is not set in ccddata" );
+#endif    /* CCD_TEST */
+  }
+
+#else     /* CCD_SYMBOLS */
+  if (ccddata_mccd_symbols())
+  {
+#ifdef CCD_TEST
+    printf ("Undefine CCD_SYMBOLS in ccddata\n");
+#else     /* CCD_TEST */
+    vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+                  "Undefine CCD_SYMBOLS in ccddata" );
+#endif    /* CCD_TEST */
+  }
+#endif    /* CCD_SYMBOLS */
+
+#ifdef DEBUG_CCD
+  /* Only for TRACE_CCD call in ccd_init. */
+  globs->me = 0;
+  globs->TraceIt = 1;
+#endif /* DEBUG_CCD */
+
+  num_of_entities = (UBYTE) ccddata_get_num_of_entities();
+  for (entity = 0; entity < num_of_entities; entity++)
+  {
+    /*
+     * Point to the first defined Message, to get the length
+     * of the message identifier
+     */
+    msg = NULL;
+    messageId = 0;
+    while (msg EQ NULL AND messageId <= max_message_id)
+    {
+      /* 
+       * If there is no UPLINK-decoding, try the DOWNLINK.
+       */
+      if ((mcompRef = ccddata_get_mmtx(entity, messageId, UPLINK)) NEQ NO_REF)
+        msg = (T_CCD_CompTabEntry *) &mcomp[mcompRef];
+      else
+        if ((mcompRef = ccddata_get_mmtx(entity, messageId, DOWNLINK)) NEQ NO_REF)
+          msg = (T_CCD_CompTabEntry *) &mcomp[mcompRef];
+        else
+          messageId++;
+    }
+    if (msg NEQ NULL
+    AND melem[msg->componentRef].elemType EQ 'V'
+    AND melem[msg->componentRef].elemRef NEQ NO_REF)
+    {
+      /*
+       * if there is a message for this layer - get the length
+       * of the first element (msg_type or pdu_type)
+       */
+      mi_length[entity] =(UBYTE) (mvar[melem[msg->componentRef].elemRef].bSize); 
+    }
+    else
+      mi_length[entity] = 0;
+
+#ifdef DEBUG_CCD
+  TRACE_CCD (globs, "MI-LEN [ENTITY %d] = %d", entity, mi_length[entity]);
+#endif
+  }
+
+  /*
+   * Register all needed coding/decoding functions in the jump table.
+   */
+  ret = cdc_init (codec);
+    
+  if (ret EQ ccdError)
+    return ccdError;
+
+#ifdef DEBUG_CCD
+  if (ret EQ ccdWarning)
+  {
+    TRACE_CCD (globs, "CCD: Mismatch between CCD and CCDDATA. Check the codec list.");//return ccdWarning;
+  }
+#endif
+
+  return ccdOK;
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++------------------------------------------------------------------------------
+|  Function     :  ccd_signup
++------------------------------------------------------------------------------
+|  Description  :  This function sets up the local CCD data for the calling
+|                  entity.
+|
+|  Parameters   :  ccd_reg - set if called by ccd_register, not set if called
+|                            by ccd_init
+|                  decmsgbuf_size - further enhancement: size of the entity's
+|                                   decoded msg buffer size
+|
+|  Return       :  ccdErr or ccdOK depending on the success
++------------------------------------------------------------------------------
+*/
+
+static int ccd_signup (int ccd_reg, int decmsgbuf_size)
+{
+#ifndef _TOOLS_
+    UBYTE                     ret;
+#endif
+  #ifdef SHARED_CCD
+    T_HANDLE me;
+  #else
+    int me = 0;
+  #endif
+  T_CCD_TASK_TABLE* tentry;
+
+#ifdef SHARED_CCD
+  me = vsi_e_handle (0, NULL);
+  if (me == VSI_ERROR)
+  {
+    me = 0;
+    tentry = ccd_task_list[0] = &task_null;
+    task_null.ccd_globs = &globs_all;
+#ifdef DEBUG_CCD
+    TRACE_CCD (&globs_all, "Ccd initialization: task could not be identified. Try to continue with a non reentrant init");
+#endif
+  }
+  else
+  {
+    if (!ccd_task_list[me])
+    {
+      ccd_task_list[me] = D_ALLOC (sizeof (T_CCD_TASK_TABLE));
+      if (!ccd_task_list[me])
+      {
+        vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+                  "Could not allocate memory for ccd task table entry" );
+      }
+      else
+      {
+        ccd_task_list[me]->ccd_globs = NULL;
+        ccd_task_list[me]->ccd_err_list = NULL;
+        ccd_task_list[me]->ccd_store = NULL;
+      }
+    }
+    tentry = ccd_task_list[me];
+    tentry->decmsgbuf = NULL;
+    if (ccd_reg)
+    {
+      if (!tentry->ccd_globs)
+      {
+        if (decmsgbuf_size != CCD_REENTRANT)
+        {
+#ifdef DEBUG_CCD
+          TRACE_CCD (tentry->ccd_globs, "Ccd_register (task %d): ignore %d for parameter decmsgbuf_size. Make non reentrant ccd_init instead.", me, decmsgbuf_size);
+#endif
+          tentry->ccd_globs = &globs_all;
+        }
+        else
+        {
+          tentry->ccd_globs = D_ALLOC (sizeof(T_CCD_Globs));
+          if (!tentry->ccd_globs)
+          {
+            vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+                      "Could not allocate memory for ccd_globs" );
+          }
+        }
+      }
+    }
+    else
+    {
+      tentry->ccd_globs = &globs_all;
+    }
+  }
+#else   /* SHARED_CCD */
+  tentry = ccd_task_list[0] = &task_null;
+  task_null.ccd_globs = &globs_all;
+#endif
+
+  tentry->ccd_globs->me = me;
+  if (ccd_err_init (&tentry->ccd_err_list))
+  {
+  #ifdef CCD_TEST
+    printf ("Cannot initialize error list: out of memory\n");
+  #else   /* CCD_TEST */
+    vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+	  "Cannot initialize error list: out of memory" );
+  #endif  /* CCD_TEST */
+    return ccdError;
+  }
+
+  if (ccd_store_init (&tentry->ccd_store))
+  {
+#ifdef CCD_TEST
+    printf ("Cannot initialize store register: out of memory\n");
+#else   /* CCD_TEST */
+    vsi_o_assert( VSI_CALLER OS_SYST_ERR, __FILE__, __LINE__,
+	  "Cannot initialize store register: out of memory" );
+#endif  /* CCD_TEST */
+    return ccdError;
+  }
+
+  if (!initialized)
+  {
+#ifdef SHARED_CCD
+   /*
+   * if the CCD is used in a premptive multithreaded system
+   * we must create a semaphore for the coding and decoding
+   */
+    semCCD_Codec  = vsi_s_open (VSI_CALLER "CCD_COD",1);
+    semCCD_Buffer = vsi_s_open (VSI_CALLER "CCD_BUF",1);
+
+#endif     /* SHARED_CCD */
+  
+#ifndef _TOOLS_
+    ret = (UBYTE)ccd_init_ccddata ();
+    if (ret != ccdOK)
+    return  ret;
+
+#endif /* !_TOOLS_ */
+    initialized = TRUE;
+    /* save memory init pattern */
+    mempat = (U8*) CCDDATA_PREF(ccd_get_numFaults ());
+  }
+  return ccdOK;
+}
+
+BYTE CCDDATA_PREF(ccd_init) (void)
+{
+  return (BYTE) ccd_signup (0, 0);
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  ccd_register
++------------------------------------------------------------------------------
+|  Description  :  This function sets up the local CCD data for the calling
+|                  entity.
+|                  Entities calling this function with a parameter 0 will
+|                  get an own set of CCD local data, i.e., they don't have to
+|                  synchronize with other entities to use CCD.     
+|
+|  Parameters   :  decmsgbuf_size - further enhancement: size of the entity's
+|                                   decoded msg buffer size
+|
+|  Return       :  ccdErr or ccdOK depending on the success
++------------------------------------------------------------------------------
+*/
+
+int ccd_register (int decmsgbuf_size)
+{
+  return ccd_signup (1, decmsgbuf_size);
+}
+#endif /* !RUN_FLASH */
+
+#ifndef RUN_FLASH
+/*
++--------------------------------------------------------------------+
+| PROJECT : CCD (6144)               MODULE  : CCD                   |
+| STATE   : code                     ROUTINE : ccd_exit              |
++--------------------------------------------------------------------+
+
+ PURPOSE:  performs a shutdown of CCD.
+
+*/
+
+int CCDDATA_PREF(ccd_exit) (void)
+{
+#ifdef SHARED_CCD
+  T_CCD_TASK_TABLE* tentry;
+  T_HANDLE me = vsi_e_handle (0, NULL);
+  if (me == VSI_ERROR)
+    return ccdError;
+  tentry = ccd_task_list[me]; 
+  if (tentry->ccd_globs && (tentry->ccd_globs != &globs_all))
+  {
+    D_FREE (tentry->ccd_globs);
+    tentry->ccd_globs = 0;
+  }
+  ccd_store_exit();
+  ccd_err_exit (); 
+  D_FREE (ccd_task_list[me]);
+  ccd_task_list[me] = NULL;
+#else
+  ccd_store_exit();
+  ccd_err_exit (); 
+#endif /* SHARED_CCD */
+  return ccdOK;
+}
+#endif /* !RUN_FLASH */