FreeCalypso > hg > freecalypso-sw
view gsm-fw/ccd/asn1_seq.c @ 1022:24440bc7cee8
gsm-fw/configs: gtamodem-gsmtch-{ext,int} configurations added
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Tue, 03 May 2016 13:43:31 +0000 |
parents | 970d6199f2c5 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : asn1_seq.c +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : Definition of encoding and decoding functions for ASN1_SEQUENCE | elements +----------------------------------------------------------------------------- */ #define ASN1_SEQ_C /* * Standard definitions like UCHAR, ERROR etc. */ #include "typedefs.h" #include "header.h" /* * Prototypes of ccd (USE_DRIVER EQ undef) for prototypes only * look at ccdapi.h */ #undef USE_DRIVER #include "ccdapi.h" /* * Types and functions for bit access and manipulation */ #include "ccd_globs.h" #include "bitfun.h" /* * Prototypes and constants in the common part of ccd */ #include "ccd.h" #include "ccd_codingtypes.h" /* * Declaration of coder/decoder tables */ #include "ccdtable.h" #include "ccddata.h" EXTERN T_FUNC_POINTER codec[MAX_CODEC_ID+1][2]; #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : asn1_seq | | STATE : code ROUTINE : Read_SEQ_BitMap | +--------------------------------------------------------------------+ PURPOSE : Decode the bit-map preamble for OPTIONAL elements or those with DEFAULT value. */ void Read_SEQ_BitMap (const ULONG first_elem, const ULONG last_elem, T_CCD_Globs *globs) { ULONG elem = first_elem; while (elem < last_elem) { if (melem[elem].optional) { /* * For optional elements read the corresponding bit in the preamble * and set the valid flag in the C-Structure to it. */ if (melem[elem].elemType < 'P' OR melem[elem].elemType > 'R') { globs->pstruct[melem[elem].structOffs] = (UBYTE) bf_readBit(globs); } else { if(bf_readBit(globs)) /*elemType P, Q or R*/ { /*If present set the pointer to -1 (0xFFFF) - anything else than NULL, because the element is present*/ *(void**) &globs->pstruct[melem[elem].structOffs] = (void *) 0xFFFF; } else /*Not present set the pointer to NULL*/ *(void**) &globs->pstruct[melem[elem].structOffs] = NULL; } } /* * For optional elements read the corresponding bit in the preamble * and set the valid flag in the C-structure to it. */ else if (melem[elem].codingType EQ CCDTYPE_ASN1_INTEGER) { /* * Check if this variable has a default value. * As long as the DEFAULT values are given with ranges it is right to * look for isDefault in the second entry in mval.cdg. * There is no valid flag for elements with default value. But we use * the first byte of this element within the C-structure for giving a * signal to this function. The only simple type which has DEFAULT is INTEGER. */ if (mval[mvar[melem[elem].elemRef].valueDefs+1].isDefault EQ 2) { globs->pstruct[melem[elem].structOffs] = (UBYTE) bf_readBit(globs); } } elem++; } } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_GSM | | STATE : code ROUTINE : cdc_asn1_seq_decode | +--------------------------------------------------------------------+ PURPOSE : Decoding of the SEQUENCE and SEQUENCE OF type for UMTS The element can be a field of fixed or variable length. It can contain OPTIONAL elements or integer elements with a DEFAULT value. A special case is when the element is a so called msg_data. According to CCDDATA a message is made of a msg_type and a msg_data part. If the msg_data has a coding type of ASN1_SEQUENCE this function is called. In this case CCD needs to pass over the msg_type by incrementing globs->pstruct. A msg_data sequence can not be optional. Nor it can be an array of msg_data. If the sequence is not a msg_data this function is called as an equivalent to ccd_decodeComposition. Hence the increment on globs->ccd_recurs_level. A non-msg_data sequence can be optional or an array. */ SHORT cdc_asn1_seq_decode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) { ULONG repeat=1, max_rep=1; ULONG cSize, first_elem, last_elem, elem; UBYTE *old_pstruct; #ifdef DEBUG_CCD static S8 trace_nesting_level = -1; #endif #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_asn1_seq_decode()"); #else TRACE_CCD (globs, "cdc_asn1_seq_decode() %s", mcomp[melem[e_ref].elemRef].name); #endif #endif /* * This function is called as an equivalent to ccd_decodeComposition. * Hence the increment on globs->ccd_recurs_level. */ globs->ccd_recurs_level ++; /* * Set pstrcutOffs and max_rep. * Check the valid flag in case of optional elements. */ if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK) { globs->ccd_recurs_level --; return 1; } /* * Prepare for decoding of the same sequence type up to max_rep times. * Set the upper and lower bound of elemRef for processing of each repeatition. * Read the C-size to go ahead in the C-structure after each repeatition. */ switch (melem[e_ref].elemType) { case 'C': case 'D': case 'E': case 'P': case 'Q': elem = (ULONG) melem[e_ref].elemRef; first_elem = (ULONG) mcomp[elem].componentRef; last_elem = first_elem + mcomp[elem].numOfComponents; cSize = (ULONG) mcomp[elem].cSize; break; case 'F': case 'R': first_elem = e_ref; last_elem = e_ref + 1; cSize = (ULONG) mvar[e_ref].cSize; break; default: ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) (globs->bitpos), (USHORT) -1); return 1; }; /* * Store the current value of the C-structure pointer. * After decoding the SEQUENCE component we will set the pointer * to this stored value. Then we will use pstructOffs for pointing * to the next element. */ old_pstruct = globs->pstruct; #ifdef DYNAMIC_ARRAYS /* * Allocate memory for this whole composition, if elemType is * one of the pointer types. */ if ( is_pointer_type(e_ref)) { if ( PER_allocmem_and_update(e_ref, max_rep, globs) NEQ ccdOK ) { /* No memory - Return. Error already set in function call above. */ globs->ccd_recurs_level --; return 1; } } #endif globs->pstruct += globs->pstructOffs; /* * Decode all elements of the field. */ while (repeat <= max_rep) { Read_SEQ_BitMap (first_elem, last_elem, globs); elem = first_elem; /* * Decode all elements of the array */ #ifdef DEBUG_CCD trace_nesting_level++; #endif while (elem < last_elem) { #ifdef ERR_TRC_STK_CCD /* * Save the value for tracing in error case. */ globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem; #endif /* ERR_TRC_STK_CCD */ #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "decoding level %d element %d", trace_nesting_level, elem - first_elem); #else TRACE_CCD (globs, "decoding level %d element %d '%s'",trace_nesting_level, elem - first_elem, ccddata_get_alias((USHORT) elem, 1)); #endif #endif /* * Use the jump-table for selecting the decode function. * Possible types are 0, ASN1_INTEGER, BITSTRING, ASN1_CHOICE and * ASN1_SEQUENCE. In case of 0 function cdc_STD_decode will be called. */ (void) codec[melem[elem].codingType][DECODE_FUN] (c_ref, elem, globs); elem ++; } #ifdef DEBUG_CCD trace_nesting_level--; #endif /* * Set the pointer of the C-structure on the next element. */ globs->pstruct += cSize; repeat ++; } /* * Prepare for decoding the next element. */ globs->pstruct = old_pstruct; globs->ccd_recurs_level--; return 1; } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : asn1_seq | | STATE : code ROUTINE : Write_SEQ_BitMap | +--------------------------------------------------------------------+ PURPOSE : Encode the bit-map preamble for OPTIONAL elements or those with DEFAULT value. */ void Write_SEQ_BitMap (const ULONG first_elem, const ULONG last_elem, T_CCD_Globs *globs) { ULONG elem = first_elem; while (elem < last_elem) { if (melem[elem].optional) { /* * For optional elements read the valid flag in the C-Structure * and overwrite the corresponding bit in the preamble. */ #if defined _TOOLS_ int patch; U16 stelem; stelem = globs->error_stack[globs->ccd_recurs_level]; globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem; patch = ccd_patch (globs, 1); globs->error_stack[globs->ccd_recurs_level] = stelem; if (patch) { bf_writeBit(1, globs); elem++; continue; } #endif /* _TOOLS_ */ #ifdef DYNAMIC_ARRAYS if ( is_pointer_type(elem) ) { BOOL present; /* * Check for NULL pointer (== notPresent/not valid) for this element. */ present = (*(U8 **)(globs->pstruct + melem[elem].structOffs) NEQ NULL); /* * Double check for 'D' to 'F' types. Both NULL pointer and * valid flag. (Strictly not necessary, but may catch uninitialized * flags/pointers). */ if (present AND (melem[elem].elemType >= 'D' AND melem[elem].elemType <= 'F')) { present = (BOOL)globs->pstruct[melem[elem].structOffs]; } bf_writeBit(present, globs); } else #endif bf_writeBit((BOOL)globs->pstruct[melem[elem].structOffs], globs); } else if (melem[elem].codingType EQ CCDTYPE_ASN1_INTEGER) { /* * Check if this variable has a default value. * As long as the DEFAULT values are given with ranges it is right to * look for isDefault in the second entry in mval.cdg. * There is no valid flag for elements with default value. So we need * to read the value from C-structure and compare it with the DEFAULT * value given in the mval table. The only simple type which has * DEFAULT is INTEGER. */ if (mval[mvar[melem[elem].elemRef].valueDefs+1].isDefault EQ 2) { U32 value=0; UBYTE *p; /* * setup the read pointer to the element in the C-structure */ #ifdef DYNAMIC_ARRAYS if ( is_pointer_type(elem) ) { /* * NULL pointers should be caught as part of the optionality * check in PER_CommonBegin() */ p = *(U8 **)(globs->pstruct + globs->pstructOffs); if (ccd_check_pointer(p) != ccdOK) { ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) elem, &globs->pstruct[globs->pstructOffs]); return; } } else #endif p = globs->pstruct + melem[elem].structOffs; /* * Default values are all positive and small values (< 64K) * in the current version of umts. The cases 'L' and 'C' are added * to be ready for a future change where we need also a check of * possible errors through type casting. */ switch (mvar[melem[elem].elemRef].cType) { case 'B': value = (U32)*(UBYTE *) p; break; case 'C': value = (U32)(S32)*(S8 *) p; break; case 'S': value = (U32)(*(USHORT *) p); break; case 'T': value = (U32)(S32)*(S16 *) p; break; case 'L': value = (U32)*(S32 *) p; break; case 'M': value = (U32)*(U32 *) p; break; default: ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) -1); break; } /* * Compare the value to be encoded with the default value. * Write the presence flag into the preamble. */ if (value EQ (U32)mval[mvar[melem[elem].elemRef].valueDefs+1].startValue) { bf_writeBit(0, globs); } else { bf_writeBit(1, globs); } } } elem++; } } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +--------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : CDC_GSM | | STATE : code ROUTINE : cdc_asn1_seq_encode | +--------------------------------------------------------------------+ PURPOSE : Decoding of the SEQUENCE and SEQUENCE OF type for UMTS The element can be a field of fixed or variable length. It can contain OPTIONAL elements or integer elements with a DEFAULT value. A special case is when the element is a so called msg_data. According to CCDDATA a message is made of a msg_type and a msg_data part. If the msg_data has a coding type of ASN1_SEQUENCE this function is called. In this case CCD needs to pass over the msg_type by incrementing globs->pstruct. A msg_data sequence can not be optional. Nor it can be an array of msg_data. If the sequence is not a msg_data this function is called as an equivalent to ccd_encodeComposition. Hence the increment on globs->ccd_recurs_level. A non-msg_data sequence can be optional or an array. */ SHORT cdc_asn1_seq_encode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) { ULONG repeat=1, max_rep=1; ULONG cSize, first_elem, last_elem, elem; UBYTE *old_pstruct; #ifdef DEBUG_CCD static S8 trace_nesting_level = -1; #endif #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_asn1_seq_encode()"); #else TRACE_CCD (globs, "cdc_asn1_seq_encode() %s", mcomp[melem[e_ref].elemRef].name); #endif #endif /* * This function is called as an equivalent to ccd_encodeComposition. * Hence the increment on globs->ccd_recurs_level. */ globs->ccd_recurs_level ++; /* * Set pstrcutOffs and max_rep. * Check the valid flag in case of optional elements. */ if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK) { globs->ccd_recurs_level --; return 1; } /* * Prepare for encoding of the same sequence type up to max_rep times. * Set the upper and lower bound of elemRef for processing of each repeatition. * Read the C-size to go ahead in the C-structure after each repeatition. */ switch (melem[e_ref].elemType) { case 'C': case 'D': case 'E': case 'P': case 'Q': { elem = (ULONG) melem[e_ref].elemRef; first_elem = (ULONG) mcomp[elem].componentRef; last_elem = first_elem + mcomp[elem].numOfComponents; cSize = (ULONG) mcomp[elem].cSize; break; } case 'F': case 'R': { first_elem = e_ref; last_elem = e_ref + 1; cSize = (ULONG) mvar[e_ref].cSize; break; } default: ccd_setError (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) (globs->bitpos), (USHORT) -1); return 1; } /* * Store the current value of the C-structure pointer. * After encoding the SEQUENCE component we will set the pointer * to this stored value. Then we will use pstructOffs for pointing * to the next element. */ old_pstruct = globs->pstruct; globs->pstruct += globs->pstructOffs; #ifdef DYNAMIC_ARRAYS if ( is_pointer_type(e_ref) ) { if (ccd_check_pointer(*(U8 **)globs->pstruct) == ccdOK) { globs->pstruct = *(U8 **) globs->pstruct; } else { ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, &globs->pstruct[globs->pstructOffs]); return 1; } } #endif /* * Encode all elements of the field. */ while (repeat <= max_rep) { Write_SEQ_BitMap (first_elem, last_elem, globs); /* * Encode all elements */ #ifdef DEBUG_CCD trace_nesting_level++; #endif elem = first_elem; while (elem < last_elem) { #ifdef ERR_TRC_STK_CCD /* * Save the value for tracing in error case. */ globs->error_stack[globs->ccd_recurs_level] = (USHORT) elem; #endif /* ERR_TRC_STK_CCD */ #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "encoding level %d element %d", trace_nesting_level, elem - first_elem); #else TRACE_CCD (globs, "encoding level %d element %d '%s'", trace_nesting_level, elem - first_elem ,ccddata_get_alias((USHORT) elem, 1)); #endif #endif #if defined _TOOLS_ if (!ccd_patch (globs, 0)) #endif /* _TOOLS_ */ /* * Use the jump-table for selecting the code function. * Possible types are 0, ASN1_INTEGER, BITSTRING, ASN1_CHOICE and * ASN1_SEQUENCE. In case of 0 function cdc_STD_encode will be called. */ (void) codec[melem[elem].codingType][ENCODE_FUN] (c_ref, elem, globs); /* * Set the elemRef to the next element. */ elem ++; } #ifdef DEBUG_CCD trace_nesting_level--; #endif /* * Set the pointer of the C-structure on the next element. */ globs->pstruct += cSize; repeat ++; } /* * Prepare for encoding the next element. */ globs->pstruct = old_pstruct; globs->ccd_recurs_level--; return 1; } #endif /* !RUN_INT_RAM */