line source
+ − /*
+ − +-----------------------------------------------------------------------------
+ − | 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 */