FreeCalypso > hg > freecalypso-sw
view gsm-fw/ccd/asn1_integ_ext.c @ 944:51f580665110
gsm-fw: C139 works with non-volatile FFS enabled
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Sun, 01 Nov 2015 05:03:35 +0000 |
parents | 970d6199f2c5 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : asn1_integ_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_INTEGER_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_integ_ext | | STATE : code ROUTINE : cdc_asn1_integ_ext_decode | +------------------------------------------------------------------------+ PURPOSE : Decode UNALIGNED PER extensible ENUMERATED and INTEGER type PER-visible constraints restrict the integer value to be a constrained whole number. This gives a lower and an upper bound for the integer. The lb is also called offset. The encoded value is the difference between the actual and the offset value. A possible and meant default value is never encoded. If the value is in the extension root, it will be encoded as a normally small non-negative whole number. Otherwise it will be encoded in the smalles number of bits needed to express every enumeration. */ SHORT cdc_asn1_integ_ext_decode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) { ULONG repeat=1, max_rep=1, var_ref, val_ref; BOOL DefaultFound= FALSE; S32 IfnotPresent; UBYTE *value, *old_pstruct = NULL; var_ref = (ULONG) melem[e_ref].elemRef; #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_asn1_integ_ext_decode()"); #else TRACE_CCD (globs, "cdc_asn1_integ_ext_decode() %s", ccddata_get_alias((USHORT) e_ref, 1)); #endif #endif /* * For integer with only one possible value in the extension root: * If the extensinon bit is 0, the encoded value is in the extension root. * In this case no arrays are expected. * For other types: * The extension bit and the value will be read in the while-loop below. */ if (mvar[var_ref].bSize EQ 0) { if (bf_readBit (globs) EQ FALSE) { Read_unique_Integer (e_ref, globs); return 1; } else { bf_incBitpos (-1, globs); } } val_ref = (ULONG) mvar[var_ref].valueDefs; /* * Set pstrcutOffs and max_rep. Check the valid flag in case of optional elements. */ if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK) return 1; #ifdef DYNAMIC_ARRAYS /* * Allocate memory if this is a pointer type (dynamic array) */ if ( is_pointer_type(e_ref) ) { old_pstruct = globs->pstruct; if ( PER_allocmem_and_update(e_ref, max_rep, globs) NEQ ccdOK) /* No memory - Return. Error already set in function call above. */ return 1; } #endif /* * Check if there is a default value for the element. * If yes, just set it aside for a later comparision. */ if (mval[val_ref+1].isDefault EQ 2) { IfnotPresent = mval[val_ref+1].startValue; DefaultFound = TRUE; } /* * Decode all elements of the array. */ while ( repeat <= max_rep) { value = globs->pstruct + globs->pstructOffs; /* * There is a default value for this integer elment. * While decoding of the ASN1-SEQUENCE contiaing this integer * we have used a particular byte of C-structure to signalize * the decoding of a default value (byte set to 0). */ if (DefaultFound AND !globs->pstruct[melem[e_ref].structOffs]) { switch (mvar[var_ref].cType) { case 'B': *(U8*) value = (U8) IfnotPresent; break; case 'C': *(S8*) value = (S8) IfnotPresent; break; case 'S': *(U16*) value = (U16) IfnotPresent; break; case 'T': *(S16*) value = (S16) IfnotPresent; break; case 'L': *(U32*) value = (U32) IfnotPresent; break; case 'M': *(S32*) value = (S32) IfnotPresent; break; default: ccd_recordFault (globs,ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, value); break; } } /* * There is no default value defined for this integer elment. * Read the value from the bit buffer. */ else { U32 ub, lb; ULONG readBits; U32 DecodedValue; lb = mval[val_ref].startValue; ub = mval[val_ref].endValue; /* * Read first the extensinon bit. * Then the non-negative value from the air message. */ if (bf_readBit (globs) EQ FALSE) { readBits = bf_getBits (mvar[var_ref].bSize, globs); } /* Value out of the extension root. */ else { U16 calcRef = calcidx[melem[e_ref].calcIdxRef].condCalcRef; /* * Get max value of integer within the extension root. */ if (calcRef EQ NO_REF OR calc[calcRef].operation NEQ 'P') { ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, globs->pstruct+globs->pstructOffs); } else { lb = calc[calcRef].operand; } readBits = Read_NormallySmallNonNegativeWholeNr (globs); } if (readBits <= (U32)(ub - lb)) { DecodedValue = lb + readBits; /* * Add the offset to the read value to get the actual one. */ switch (mvar[var_ref].cType) { case 'B': *(U8*) value = (U8) DecodedValue; break; case 'C': *(S8*) value = (S8) DecodedValue; break; case 'S': *(U16*) value = (U16) DecodedValue; break; case 'T': *(S16*) value = (S16) DecodedValue; break; case 'L': *(U32*) value = (U32) DecodedValue; break; case 'M': *(S32*) value = (S32) DecodedValue; break; default: ccd_recordFault (globs,ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, value); break; } } else { #ifdef DEBUG_CCD TRACE_CCD (globs, "integer out of range! %ld require: %ld .. %ld ", DecodedValue, lb, ub); #endif if (melem[e_ref].optional) ccd_recordFault (globs, ERR_ASN1_OPT_IE, CONTINUE, (USHORT) e_ref, value); else ccd_recordFault (globs, ERR_ASN1_MAND_IE, CONTINUE, (USHORT) e_ref, value); } } repeat ++; globs->pstructOffs += mvar[var_ref].cSize; }/*while*/ #ifdef DYNAMIC_ARRAYS if (old_pstruct NEQ NULL) globs->pstruct = old_pstruct; #endif return 1; } #endif /* !RUN_INT_RAM */ #ifndef RUN_INT_RAM /* +------------------------------------------------------------------------+ | PROJECT : CCD (6144) MODULE : asn1_integ_ext | | STATE : code ROUTINE : cdc_asn1_integ_ext_encode | +------------------------------------------------------------------------+ PURPOSE : UNALIGNED PER extensible ENUMERATED and INTEGER type PER-visible constraints restrict the integer value to be a constrained whole number. This gives a lower and an upper bound for the integer. The lb is also called offset. The encoded value is the difference between the actual and the offset value. A possible and meant default value is never encoded. If the value is in the extension root, it will be encoded as a normally small non-negative whole number. Otherwise it will be encoded in the smalles number of bits needed to express every enumeration. ----------------------------------------------- | extension | value encoded as a normally | | bit = 1 | non-negtive integer whole number | ----------------------------------------------- ----------------------------------------------- | extension | value encoded in the bit size | | bit = 0 | needed to express ub - lb | ----------------------------------------------- */ SHORT cdc_asn1_integ_ext_encode (const ULONG c_ref, const ULONG e_ref, T_CCD_Globs *globs) { ULONG repeat=1, max_rep=1, var_ref, val_ref; BOOL DefaultFound= FALSE; S32 IfnotPresent; U8 *base_pstruct; #ifdef DEBUG_CCD #ifndef CCD_SYMBOLS TRACE_CCD (globs, "cdc_asn1_integ_ext_encode()"); #else TRACE_CCD (globs, "cdc_asn1_integ_ext_encode() %s", ccddata_get_alias((USHORT) e_ref, 1)); #endif #endif var_ref = (ULONG) melem[e_ref].elemRef; val_ref = (ULONG) mvar[var_ref].valueDefs; /* * Set pstrcutOffs and max_rep. Check the valid flag in case of optional elements. */ if (PER_CommonBegin (e_ref, &max_rep, globs) NEQ ccdOK) return 1; /* * Check if there is a default value for the element. * If yes, just set it aside for a later comparision. */ if (mval[val_ref+1].isDefault EQ 2) { IfnotPresent = mval[val_ref+1].startValue; DefaultFound = TRUE; } #ifdef DYNAMIC_ARRAYS if ( is_pointer_type(e_ref) ) { base_pstruct = *(U8 **)(globs->pstruct + globs->pstructOffs); if (ccd_check_pointer(base_pstruct) == ccdOK) { globs->pstructOffs = 0; } else { ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, &globs->pstruct[globs->pstructOffs]); return 1; } } else #endif base_pstruct = globs->pstruct; /* * Encode all elements of the array. */ while ( repeat <= max_rep) { S32 ub, lb, value; U32 extension_lb; UBYTE *p; U16 calcRef = calcidx[melem[e_ref].calcIdxRef].condCalcRef; /* * Get offset value of integer in the extension addition. */ if (calcRef EQ NO_REF OR calc[calcRef].operation NEQ 'P') { ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK,(USHORT) e_ref, globs->pstruct+globs->pstructOffs); return 1; } else { extension_lb = calc[calcRef].operand; } /* * setup the read pointer to the element in the C-structure */ p = base_pstruct + globs->pstructOffs; switch (mvar[var_ref].cType) { case 'B': value = (S32)*(UBYTE *) p; break; case 'C': value = (S32)*(S8 *) p; break; case 'S': value = (S32)*(USHORT *) p; break; case 'T': value = (S32)*(S16 *) p; break; case 'L': /* * This type casting can be critical. * Thus the case of bSize=32 will be handled separately. */ if (mvar[var_ref].bSize < 32) { value = (S32)*(U32 *) p; } break; case 'M': value = *(S32 *) p; break; default: ccd_recordFault (globs,ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref, p); return 1; } if (mvar[var_ref].cType EQ 'L' AND (mvar[var_ref].bSize EQ 32)) { U32 CriticalValue; CriticalValue = *(U32 *) p; if (CriticalValue >= extension_lb) { bf_writeBit (1, globs); if (!DefaultFound OR (U32)IfnotPresent NEQ CriticalValue) Write_NormallySmallNonNegativeWholeNr (CriticalValue - extension_lb, globs); } else { bf_writeBit (0, globs); if (!DefaultFound OR (U32)IfnotPresent NEQ CriticalValue) { U32 lb, ub; lb = (U32) mval[val_ref].startValue; ub = (U32) mval[val_ref].endValue; if (lb <= CriticalValue && CriticalValue <= ub) { bf_writeVal (CriticalValue - lb, mvar[var_ref].bSize, globs); } else { #ifdef DEBUG_CCD TRACE_CCD (globs, "integer out of range! %ld require: %ld .. %ld ", value, lb, ub); #endif ccd_recordFault (globs, ERR_INT_VALUE, CONTINUE, (USHORT) e_ref, p); } } } } else { /* * Encode only non-default values. */ if (!DefaultFound OR IfnotPresent NEQ value) { /* * Set the extension bit to 0 if the value belongs to the extension root. * Otherwise set it to 1. * A non-negative-binary-integer will be encoded since the offset must * be subtracted from the value read from the C-structure. */ lb = mval[val_ref].startValue; ub = mval[val_ref].endValue; if (value >= (S32)extension_lb AND value <= ub) { bf_writeBit (1, globs); Write_NormallySmallNonNegativeWholeNr ((U32)value - extension_lb, globs); } else if (lb <= value AND value <= ub) { bf_writeBit (0, globs); /* * Do not encode single valued extension roots. */ if (mvar[var_ref].bSize NEQ 0) bf_writeVal ((ULONG)(value-lb), mvar[var_ref].bSize, globs); } else { #ifdef DEBUG_CCD TRACE_CCD (globs, "integer out of range! %ld require: %ld .. %ld ", value, lb, ub); #endif ccd_recordFault (globs, ERR_INT_VALUE, CONTINUE, (USHORT) e_ref, p); } } } /* value not critical*/ repeat ++; globs->pstructOffs += mvar[var_ref].cSize; }/* while-loop */ return 1; } #endif /* !RUN_INT_RAM */