FreeCalypso > hg > fc-tourmaline
view src/gpf/ccd/asn1_choice_ext.c @ 303:f76436d19a7a default tip
!GPRS config: fix long-standing AT+COPS chance hanging bug
There has been a long-standing bug in FreeCalypso going back years:
sometimes in the AT command bring-up sequence of an ACI-only MS,
the AT+COPS command would produce only a power scan followed by
cessation of protocol stack activity (only L1 ADC traces), instead
of the expected network search sequence. This behaviour was seen
in different FC firmware versions going back to Citrine, and seemed
to follow some law of chance, not reliably repeatable.
This bug has been tracked down and found to be specific to !GPRS
configuration, stemming from our TCS2/TCS3 hybrid and reconstruction
of !GPRS support that was bitrotten in TCS3.2/LoCosto version.
ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3
version and had to be pulled from TCS2 - but as it turns out,
there is a new field in the MMR_REG_REQ primitive that needs to be
set correctly, and that psa_mms.c module is the place where this
initialization needed to be added.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 08 Jun 2023 08:23:37 +0000 |
parents | 4e78acac3d88 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | 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 */