FreeCalypso > hg > freecalypso-sw
diff gsm-fw/ccd/asn1_choice_ext.c @ 648:970d6199f2c5
gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Thu, 04 Sep 2014 05:48:57 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/ccd/asn1_choice_ext.c Thu Sep 04 05:48:57 2014 +0000 @@ -0,0 +1,323 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : asn1_choice_ext.c ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose : Encoding and decoding functions for ASN1_CHOICE_EXTENSIBLE type ++----------------------------------------------------------------------------- +*/ + +/* + * Standard definitions like UCHAR, ERROR etc. + */ +#include "typedefs.h" +#include "header.h" + +/* + * Prototypes of ccd (USE_DRIVER EQ undef) for prototypes only + * look at ccdapi.h + */ +#undef USE_DRIVER +#include "ccdapi.h" + +/* + * Types and functions for bit access and manipulation + */ +#include "ccd_globs.h" +#include "bitfun.h" + +/* + * Prototypes and constants in the common part of ccd + */ +#include "ccd.h" + +/* + * Declaration of coder/decoder tables + */ +#include "ccdtable.h" +#include "ccddata.h" + +#ifndef RUN_INT_RAM +/* ++------------------------------------------------------------------------+ +| PROJECT : CCD (6144) MODULE : asn1_choice_ext | +| STATE : code ROUTINE : cdc_asn1_choice_ext_decode | ++------------------------------------------------------------------------+ + + PURPOSE : Decode PER extensible CHOICE type + + The value of the union tag must be calculated from the encoded + CHOICE index in the air message. + For CHOICE alternatives within the extension root: the index + bit-size relates to max index value in the extension root. + For CHOICE alternatives within the extension part: the index + is encoded as a normally small non-negative whole number. + + For decoding the CHOICE alternative itself, call the same + function as for non-extensible CHOICE types. +*/ +SHORT cdc_asn1_choice_ext_decode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) +{ + U32 extensionBegin; + T_ENUM UnionTag; /* default: only one alternative */ + ULONG calc_ref = calcidx[melem[e_ref].calcIdxRef].condCalcRef; + +#ifdef DEBUG_CCD + #ifndef CCD_SYMBOLS + TRACE_CCD (globs, "cdc_asn1_choice_ext_decode()"); + #else + TRACE_CCD (globs, "cdc_asn1_choice_ext_decode() %s", mcomp[melem[e_ref].elemRef].name); + #endif +#endif + + /* Don't do anything for empty choices */ + if (mcomp[melem[e_ref].elemRef].numOfComponents == 0) + { + return 1; + } + + globs->pstructOffs = melem[e_ref].structOffs; + + /* For optional elements we have already set the valid flag in the + * C-structure. We have done it while processing ASN1_SEQ. + */ + if ( ! cdc_isPresent(e_ref, globs) ) { + return 1; + } + + /* + * Get max value of CHOICE index within the extension root. + */ + if (calc_ref EQ NO_REF + OR + calc[calc_ref].operation NEQ 'P') + { + ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, + globs->pstruct+globs->pstructOffs); + return 1; + } + else + { + extensionBegin = calc[calc_ref].operand; + } + + /* + * Read the extensinon bit. + * If set to 1, read the CHOICE index as a normally samll + * non-negative whole number. Otherwise read it according + * to the bitSize of index in the extension root. + */ + if (bf_readBit (globs) EQ 0) + { + /* CHOICE index is encoded only if there are more than one alternatives. */ + if (mcomp[melem[e_ref].elemRef].numOfComponents > 1) + { + UnionTag = (T_ENUM)bf_getBits (bitSize[extensionBegin], globs); + } + else + UnionTag = 0; + + if (UnionTag >= (T_ENUM)extensionBegin) + { + ccd_recordFault (globs, ERR_ASN1_ENCODING, BREAK, (USHORT) e_ref, + globs->pstruct+globs->pstructOffs); + } + PER_Decode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs); + } + else + { + U32 finalBP=0; + UnionTag = (T_ENUM)Read_NormallySmallNonNegativeWholeNr (globs); + UnionTag += extensionBegin; + finalBP = Read_OpenTpye_Length (globs)*8; + finalBP += globs->bitpos; + + /* + * For unknown extension skip over the octets. + */ + if (UnionTag <= (T_ENUM)mcomp[melem[e_ref].elemRef].numOfComponents) + { + PER_Decode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs); + } + else + { +#ifdef DEBUG_CCD + TRACE_CCD (globs, "Unknown extension with CHOICE index = %ld...skipped to the bit %ld", UnionTag, finalBP); +#endif + } + bf_setBitpos (finalBP, globs); + } + + return 1; +} +#endif /* !RUN_INT_RAM */ + +#ifndef RUN_INT_RAM +/* ++------------------------------------------------------------------------+ +| PROJECT : CCD (6144) MODULE : asn1_choice_ext | +| STATE : code ROUTINE : cdc_asn1_choice_ext_encode | ++------------------------------------------------------------------------+ + + PURPOSE : Encode PER extensible CHOICE type + + Evaluate the union controller. + 1) It refers to a CHOICE alternative within the extension root: + Set the extension bit to 0. + Write the CHOICE index. + Then encode the chosen alternative. + ------------------------------------ + | extension | CHOICE | encoded | + | bit | index | alternative | + ------------------------------------ + + 2) It refers to a CHOICE alternative within the extension list: + Set the extension bit to 1. + Encode the CHOICE index as a normally small non-negative whole nr. + Skip over 6 bits dedicated to length determinant. + Encode the chosen alternative. + Calculate the bit size of the encoded alternative. + Encode the calculated bit size into the field of length + determinant. Right shift the encoded alternative, if 6 bits + are not enough for the length determinant. + ------------------------------------------------ + | extension | CHOICE | length | encoded | + | bit | index | determinant | alternative | + ------------------------------------------------ + + For encoding the CHOICE alternative itself, call the same + function as for non-extensible CHOICE types. +*/ +SHORT cdc_asn1_choice_ext_encode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) +{ + U16 startBitpos, Len, EndBitPos; + T_ENUM UnionTag; /* default: only one alternative */ + U32 extensionBegin; + ULONG calc_ref= calcidx[melem[e_ref].calcIdxRef].condCalcRef; + +#ifdef DEBUG_CCD + #ifndef CCD_SYMBOLS + TRACE_CCD (globs, "cdc_asn1_choice_ext_encode()"); + #else + TRACE_CCD (globs, "cdc_asn1_choice_ext_encode() %s", mcomp[melem[e_ref].elemRef].name); + #endif +#endif + + /* Don't do anything for empty choices */ + if (mcomp[melem[e_ref].elemRef].numOfComponents == 0) + { + return 1; + } + + globs->pstructOffs = melem[e_ref].structOffs; + + /* For optional elements we have already set the valid flag in the + * C-structure. We have done it while processing ASN1_SEQ. + */ + if ( ! cdc_isPresent(e_ref, globs) ) + return 1; + + /* + * Get max value of CHOICE index within the extension root. + */ + if (calc_ref EQ NO_REF + OR + calc[calc_ref].operation NEQ 'P') + { + ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK,(USHORT) e_ref, + globs->pstruct+globs->pstructOffs); + return 1; + } + else + { + extensionBegin = calc[calc_ref].operand; + } + + /* + * Get the value of chosen index (= union controller). + */ + UnionTag = *(T_ENUM *) (globs->pstruct+globs->pstructOffs); + + /* + * The chosen alternative belongs to the extension list. + */ + if ((U32)UnionTag >= extensionBegin) + { + /* Encode the extension bit first */ + bf_writeBit (1, globs); + /* Encode the CHOICE index. */ + Write_NormallySmallNonNegativeWholeNr (((U32)UnionTag - extensionBegin), globs); + + /* Skip over the bits estimated for the length determinant. */ + bf_incBitpos (8, globs); + startBitpos = globs->bitpos; + PER_Encode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs); + + /* + * Check if zero padding bits are necessary. If encoding + * consumed no bits, insert a zero-octet in the bit string. + * Then calculate length of the encoded open type in octets. + */ + if ((Len = globs->bitpos - startBitpos) EQ 0) + { + bf_writeVal (0, 8, globs); + Len = 1; + } + else + { + if ((Len&7) NEQ 0) + bf_incBitpos (8 - (Len&7), globs); + Len = (U16)(globs->bitpos - startBitpos) >> 3; + } + EndBitPos = globs->bitpos; + + /* + * Encode the length determinant. + */ + if (Len < 128) + { + bf_setBitpos (startBitpos-8, globs); + Write_OpenTpye_Length ((U32)Len, globs); + } + /* + * This case does not seem to happen very often. + */ + else + { + ccd_recordFault (globs, ERR_ASN1_ENCODING, BREAK,(USHORT) e_ref, + globs->pstruct+globs->pstructOffs); + } + /* + * Encoding for the extensible choice is finished. + * Set the bit position pointer to the end of encoded open type. + */ + bf_setBitpos (EndBitPos, globs); + } + /* + * The chosen alternative belongs to the extension root. + */ + else + { + bf_writeBit (0, globs); + /* CHOICE index is encoded only if there are more than one alternatives. */ + if (mcomp[melem[e_ref].elemRef].numOfComponents > 1) + { + bf_writeVal ((ULONG) UnionTag, (ULONG) bitSize[extensionBegin], globs); + } + PER_Encode_ASN1_CHOICE_alterative (e_ref, UnionTag, globs); + } + + return 1; +} +#endif /* !RUN_INT_RAM */